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.
