WIDE DHCPv6 flood

On FreeBSD we generally use WIDE DHCPv6 (also known as KAME DHCPv6, dhcp6c or simply dhcp6) as DHCPv6 client. However a rare bug can trigger this client to flood the DHCP server with requests. This happened to us and quickly prompted online.net to block our server for outgoing flood. This scared me a bit at first, as I thought we might have been part of a DDoS attack. Thankfully that was not the case.

But we still had to disable dhcp6 (and consequently IPv6). On Linux it is generally recommended to limit the DHCPv6 traffic using iptables rules. However this is not as simple with PF on FreeBSD. You cannot provide a limit on the packet rate per rule. You can limit the connection rate (see max-src-conn-rate), but I’m not sure this could be of any use here. It should be possible to use altq but this is not part of the GENERIC kernel. I really didn’t want to compile a custom kernel just as a workaround.

Instead I used another DHCPv6 client, namely ISC DHCP client (isc-dhcp43-client). Just create /usr/local/etc/dhclient6.conf and configure your DUID:

interface "igb0" {
  send dhcp6.client-id <DUID>;
}

On FreeBSD, isc-dhcp43-client doesn’t come with any rc starting script, so here is one for DHCPv6 (you should place it in /usr/local/etc/rc.d/dhclient6:

#!/bin/sh
#
# PROVIDE: dhclient6
# REQUIRE: DAEMON
# KEYWORD: dhcp
#
# Add the following lines to /etc/rc.conf to enable dhclient6:
#
# dhclient6_enable="YES"
#

. /etc/rc.subr

name="dhclient6"
desc="ISC DHCPv6 client"
rcvar="dhclient6_enable"

start_cmd="dhclient6_start"
stop_cmd="dhclient6_stop"

dhclient6_start()
{
  /usr/local/sbin/dhclient -cf "${dhclient6_conf}" -P -v "${dhclient6_iface}"
}

dhclient6_stop()
{
  if [ -r "${dhclient6_pid}" ]
  then
    kill -- -$(cat "${dhclient6_pid}")
    rm -f "${dhclient6_pid}"
  fi
}

load_rc_config ${name}

: ${dhclient6_enable="NO"}
: ${dhclient6_pid="/var/run/dhclient6.pid"}
: ${dhclient6_conf="/usr/local/etc/dhclient6.conf"}
: ${dhclient6_iface=""}

run_rc_command "$1"

Finally enable this in /etc/rc.conf:

dhclient6_iface="igb0"
dhclient6_enable="YES"