title: Blocking DHCP servers and router advertisements with nftables --- pub_date: 2020-08-27 --- author: ungleich --- twitter_handle: ungleich --- _hidden: no --- _discoverable: yes --- abstract: Blocking typical data center workloads with nftables --- body: ## Motivation Here at [ungleich](https://ungleich.ch) we are providing a variety of hosting services in the [Data Center Light](https://datacenterlight.ch). One of the workloads we offer is VM hosting and we need to take some security measures to prevent one customer abusing another customer. ## The problem The virtual machines in our next generation uncloud hosting will be using standard DHCP and IPv6 address assignments and not the [OpenNebula](https://github.com/OpenNebula/addon-context-linux) contextualisation scripts that read the networking information from an attached ISO. While this makes it easier to create VM images and VMs behave even more like regular computers, this exposes the VMs to attacks where one customer runs a DHCP server or IPv6 router advertisement daemon and tricks the other VMs into sending traffic to it. ## The architecture VMs are connected to a single shared network in which they get their IP addresses (in uncloud usually only IPv6) and then they can retrieve more information from a metadata server. So the main protection that is required is preventing to trick other customers into using a wrong IP address or route. ## Fixing it So the easiest thing to do is to disallow IPv6 router advertisements and IPv4 DHCP server answers. However as all the interfaces are put into one bridge, we will need to filter on bridge and not ip level: ``` table bridge filter { chain prerouting { type filter hook prerouting priority 0; policy accept; } ``` Next we create a chain to drop the packets we dislike: ``` chain drop_ra_dhcp { # 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 } ``` Now the only thing left is to correctly classify the traffic: * Let's assume the bridge is named **br100** * Let's assume the upstream interface that should allow RA/DHCP is named **vxlan100** Then we can connect the chains together: ``` table bridge filter { chain prerouting { type filter hook prerouting priority 0; policy accept; iifname != vxlan100 meta ibrname br100 jump drop_ra_dhcp } chain drop_ra_dhcp { # 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 } } ``` This way we have a very simple filter to prevent router advertisements or dhcp answers to come from customer VMs. If something does not make sense, you can ask on our [open chat](/u/projects/open-chat/) or [consult the nftables reference](https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Meta).