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.