A promiscuous, NFQUEUE-based DHCP, DHCPv6 and Router Advertisement server for virtual machine hosting
nfdhcpd
is a userspace daemon written in python and based on
NFQUEUE meant
to process DHCP, IPv6 Neighbor Solicitations (NS), IPv6 Router Solicitations (RS)
and DHCPv6 requests. The daemon should run on the hosts of virtualization environments
in order to directly reply to VMs' requests without these leaving the hosts. An
administrator can enable processing of those requests on individual TAP interfaces
by injecting nfdhcpd in the processing pipeline for IP packets dynamically. This is
done by mangling the relevant packets on those interfaces using iptables and
redirecting them to NFQUEUE target using the appropriate queue number.
nfdhcpd
is mainly targeted to be used in a routed setup where the
instances are not on the same broadcast domain with the external router,
but that does not mean it can't be used on bridged setup, even though one
might consider it a bit redundant.
nfdhcpd
periodically sends Router Advertisements to all IPv6 enabled
interfaces it monitors to enable addressing through SLAAC. DHCPv6 functionality
is currently limited to supplying Other Configuration data like DNS Recursive
Name Server and Domain Search List as supplementary to Router Advertisements.
The daemon is controlled by manipulating files under its state directory. Creation of a new file under this directory ("binding file") instructs the daemon to reply to the requests arriving on the specified TAP interface. These files are meant to be created by the software managing the instances on the host.
nfdhcpd
is meant to work with Ganeti and
gnt-networking. Instances inside the
cluster will obtain their configuration dynamically in a completely transparent
way without being aware of nfdhpcd's existence.
There's one binding file per network interface.
Here's a sample binding file (e.g. /var/lib/nfdhcpd/tap10
):
INDEV=tap10
IP=192.0.2.100
MAC=aa:6b:39:22:33:44
HOSTNAME=testing-vm
TAGS=""
GATEWAY=192.0.2.1
SUBNET=192.0.2.0/24
GATEWAY6=2001:db8:aaaa:bbbb::1
SUBNET6=2001:db8:aaaa:bbbb::/64
EUI64=2001:db8:aaaa:bbbb:a86b:39ff:fe22:3344
PRIVATE=
MTU=
MACSPOOF=
Here's a sample global configuration file (/etc/nfdhcpd/nfdhcpd.conf
):
## nfdhcpd sample configuration file
## General options
[general]
pidfile = /var/run/nfdhcpd/nfdhcpd.pid
datapath = /var/lib/nfdhcpd # Where the client configuration will be read from
logdir = /var/log/nfdhcpd # Where to write our logs
user = nobody # An unprivileged user to run as
## DHCP options
[dhcp]
enable_dhcp = yes
lease_lifetime = 604800 # 1 week
lease_renewal = 3600 # 1 hour
server_ip = 192.0.2.1
server_on_link = no
dhcp_queue = 42 # NFQUEUE number to listen on for DHCP requests
# IPv4 nameservers to include in DHCP responses
nameservers = 192.0.2.2, 192.0.2.3
# Optional domain to serve with the replies
domain = example.com
## IPv6-related functionality
[ipv6]
enable_ipv6 = yes
mode = auto
ra_period = 300 # seconds
rs_queue = 43 # NFQUEUE number to listen on for router solicitations
ns_queue = 44 # NFQUEUE number to listen on for neighbor solicitations
dhcpv6_queue = 45 # NFQUEUE number to listen on for DHCPv6 Information-Requests
# IPv6 nameservers to send using the ICMPv6 RA RDNSS option (RFC 5006)
# since it is not supported by several OS we serve them to DHCPv6 replies
nameservers = 2001:db8:100::1, 2001:db8:200::2
domains = example.com
To send packets to nfdhcpd
for processing, one must configure a few packet
filtering rules. To process packets coming from TAP interfaces that are members
of bridges one needs to use the -m physdev
option of iptables. There's a
sample ferm
ruleset in contrib/ferm
directory.
iptables for DHCP:
iptables -A PREROUTING -i tap+ -p udp -m udp --dport 67 -j NFQUEUE --queue-num 42
iptables -A PREROUTING -p udp -m physdev --physdev-in tap+ -m udp --dport 67 -j NFQUEUE --queue-num 42
ip6tables for RA,RS and DHCPv6:
ip6tables -A PREROUTING -i tap+ -p ipv6-icmp -m icmp6 --icmpv6-type 133 -j NFQUEUE --queue-num 43
ip6tables -A PREROUTING -i tap+ -p ipv6-icmp -m icmp6 --icmpv6-type 135 -j NFQUEUE --queue-num 44
ip6tables -A PREROUTING -i tap+ -p udp -m udp --dport 547 -j NFQUEUE --queue-num 45
We provide Debian packages for Debian 7 (wheezy) & 8 (jessie) in our APT repository. To use them:
echo deb http://apt.dev.grnet.gr $(lsb_release -s -c)/ > /etc/apt/sources.list.d/apt.dev.grnet.gr.list
echo deb-src http://apt.dev.grnet.gr $(lsb_release -s -c)/ >> /etc/apt/sources.list.d/apt.dev.grnet.gr.list
curl https://dev.grnet.gr/files/apt-grnetdev.pub | apt-key add -
apt-get update
apt-get install nfdhcpd
Warning: DHCPv6 functionality needs python-scapy>2.3
and one currently
needs to either get a package from Debian stretch
or use the patched version found
in apt.dev.grnet.gr
PyPI:
Non PyPI-resolvable:
On a Debian/Ubuntu system you can install them using:
apt-get install python-nfqueue python-cap-ng
This codebase has been created by merging the original nfdhcpd code with snf-nfdhcpd and nfdhcpd by David Halls.