155 lines
4.4 KiB
Markdown
155 lines
4.4 KiB
Markdown
title: How to build an OpenStack alternative: Step 2, secure the network
|
|
---
|
|
pub_date: 2020-01-12
|
|
---
|
|
author: ungleich virtualisation team
|
|
---
|
|
twitter_handle: ungleich
|
|
---
|
|
_hidden: no
|
|
---
|
|
_discoverable: yes!
|
|
---
|
|
abstract:
|
|
Let's secure the VM network
|
|
---
|
|
body:
|
|
|
|
In the second step of building an OpenStack alternative we have a look
|
|
on how to secure the network.
|
|
|
|
In the first step we described [how to setup a
|
|
protoype](../how-to-build-an-openstack-alternative-step-1).
|
|
|
|
Note: the name of our OpenStack alternative is
|
|
**uncloud**.
|
|
|
|
## Securing the network - of what?
|
|
|
|
Users should be able to do what they want and not limited in their
|
|
actions. On the other hand, users should be unable to disturb other
|
|
users. It's very much like in real life.
|
|
|
|
## General policy: no firewall
|
|
|
|
So for most of the user generated traffic there should be no firewall
|
|
rules in uncloud. Users should be free to configure
|
|
their own policies on the VM.
|
|
|
|
## Network types
|
|
|
|
Before applying any security mechanism, we have to think about what
|
|
kind of networks can exist in a cloud environment. We see two types of
|
|
networks:
|
|
|
|
* shared networks - more than one customer is in this network
|
|
* private networks - only one customer has access in this network
|
|
|
|
## Filtering IP address management packets
|
|
|
|
So when we share a network, we don't want one customer to be able to
|
|
assign IP addresses to other customers. Instead IP addresses should
|
|
only be assigned from the operator.
|
|
|
|
This means that we need to prevent rogue
|
|
|
|
* [Router advertisements (IPv6)](https://en.wikipedia.org/wiki/Neighbor_Discovery_Protocol)
|
|
* [DHCPv6](https://en.wikipedia.org/wiki/DHCPv6) server answers
|
|
* [DHCPv4](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol) server answers
|
|
|
|
In our prototype we are using [nftables instead of
|
|
iptables](https://ungleich.ch/en-us/cms/blog/2018/08/18/iptables-vs-nftables/)
|
|
for firewalling, but the rules can be translated from one to another
|
|
firewall system.
|
|
|
|
To drop router advertisements, we can use the following rule:
|
|
|
|
```
|
|
icmpv6 type nd-router-advert drop
|
|
```
|
|
|
|
To drop DHCPv6 server answers we can use
|
|
|
|
```
|
|
ip6 version 6 udp sport 547 drop
|
|
```
|
|
|
|
And finally to prevent DHCPv4 server anwers, we use
|
|
|
|
```
|
|
ip version 4 udp sport 67 drop
|
|
```
|
|
|
|
Note: while uncloud does not use IPv4 or DHCPv4 to the VMs, a rogue
|
|
DHCPv4 server might still trick other VMs into assigning themself an
|
|
IPv4 address. So we also need to block this one.
|
|
|
|
## Filtering MAC and IP spoofing
|
|
|
|
A VM should not be able to spoof the
|
|
[MAC address](https://en.wikipedia.org/wiki/MAC_address) or
|
|
IP address of another machine. We can achieve this by adding a chain
|
|
specific for each VM network interface:
|
|
|
|
```
|
|
iifname tap1 ether saddr 02:00:f0:a9:c4:4e ip6 saddr 2a0a:e5c1:111:888:0:f0ff:fea9:c44e accept
|
|
```
|
|
|
|
With this we can even allow routing a network to a VM and allowing
|
|
it to use any IPv6 address in that network:
|
|
|
|
```
|
|
iifname v343a-0 ether saddr 02:00:f0:a9:c4:4f ip6 saddr 2a0a:e5c1:111:888:0:f0ff:fea9:c44f accept
|
|
iifname v343a-0 ether saddr 02:00:f0:a9:c4:4f ip6 saddr 2a0a:e5c1:111:1234::/64 accept
|
|
```
|
|
|
|
## Putting it all together
|
|
|
|
The following code is a full nftable ruleset
|
|
for securing the VM network traffic.
|
|
Note that it uses the prerouting hook so
|
|
that we can use the **ibrname** statement.
|
|
This is necessary because we don't want to
|
|
filter after routing or in a forwarding mode, but we want to already filter it
|
|
**prerouting** (hence the name).
|
|
|
|
```
|
|
flush ruleset
|
|
|
|
table bridge filter {
|
|
chain prerouting {
|
|
type filter hook prerouting priority 0;
|
|
policy accept;
|
|
|
|
ibrname br100 jump br100
|
|
}
|
|
|
|
chain br100 {
|
|
# Allow all incoming traffic from outside
|
|
iifname vxlan100 accept
|
|
|
|
# Default blocks: router advertisements, dhcpv6, dhcpv4
|
|
icmpv6 type nd-router-advert drop
|
|
ip6 version 6 udp sport 547 drop
|
|
ip version 4 udp sport 67 drop
|
|
|
|
jump br100_vmlist
|
|
drop
|
|
}
|
|
chain br100_vmlist {
|
|
# VM1
|
|
iifname tap1 ether saddr 02:00:f0:a9:c4:4e ip6 saddr 2a0a:e5c1:111:888:0:f0ff:fea9:c44e accept
|
|
|
|
# VM2
|
|
iifname v343a-0 ether saddr 02:00:f0:a9:c4:4f ip6 saddr 2a0a:e5c1:111:888:0:f0ff:fea9:c44f accept
|
|
iifname v343a-0 ether saddr 02:00:f0:a9:c4:4f ip6 saddr 2a0a:e5c1:111:1234::/64 accept
|
|
}
|
|
}
|
|
```
|
|
|
|
## Status
|
|
|
|
With this second step we create the basis for actually running VMs
|
|
that we (as an operator) don't trust. So now we have a prototype and
|
|
we have network security. We probably want to begin to automate things
|
|
in the next step.
|