++blog: dhcp/router advertisement blocking

This commit is contained in:
Nico Schottelius 2020-08-27 11:25:52 +02:00
parent 4280510712
commit 23b5be2448

View file

@ -0,0 +1,106 @@
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).