Evilham.com

FreeBSD home router -- Access Point and IPv6-only

Introduction

Last time I wrote about setting up a FreeBSD-based eXO router, this builds upon a system that can correctly ping and ping6 to the internet.

The goal here is to setup the bits of the router needed for everyday usage.

This is part of a series on home routing with FreeBSD.

Table of Contents

Home router

As mentioned on the previous post, this setup is based on an APU2d4, with three ethernet interfaces: igb0 for egress/wan, igb1 for local devices and, igb2 as a management interface.

The current state is that the machine can setup the connection to eXO and can correctly accept the IPv6 and IPv4 routes and delegations, and is able to ping and ping6 devices on the internet.

This is similar to what Kamila did with her router, but has a few twists and only focuses on the home router bits, leaving the installation and 3G and PPPoE bits somewhere else.

Create the bridge

Creating network bridges on FreeBSD is pretty straightforward with man 8 ifconfig and man 5 rc.conf being the magical man pages.

To do it once:

# Create the bridge with a deterministic name
ifconfig bridge create name lair
# Add the necessary interfaces
ifconfig lair addm igb1 addm wlan0 inet6 auto_linklocal

To do it permanently, add in /etc/rc.conf:

cloned_interfaces="bridge0"
# Have a deterministic name
ifconfig_bridge0_name="lair"
# Add the necessary interfaces
ifconfig_lair="addm igb1 addm wlan0"
# While at it, ensure we have a link local address
ifconfig_lair_ipv6="auto_linklocal"

Setup the wireless network

This is done with hostapd, which is also in the base system. The magical man pages for this are man 8 hostapd and man 5 hostapd.conf as well as man 5 rc.conf.

First of all, we setup things in /etc/rc.conf:

# Setup the wireless interface
wlans_ath0="wlan0"
ifconfig_wlan0="HOSTAP"
# Respect local regulations and all that -- ES is the country code
create_args_wlan0="wlanmode hostap country ES"
# Enable the access point daemon
hostapd_enable="YES"

Now, we create /etc/hostapd-wlan0.conf as follows:

interface=wlan0
debug=0
ctrl_interface=/var/run/hostapd
ctrl_interface_group=wheel
ssid=eXO-wlan
wpa=2
wpa_passphrase=WirelessPassword
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP

Become a gateway

Now most of the things are in place in order to forward traffic for other clients in the local network.

A very important step that is missing is becoming a gateway! Here also man 5 rc.conf is a magical man page.

Add following to /etc/rc.conf:

# Act as gateway
gateway_enable="YES"
ipv6_gateway_enable="YES"
# Setup dependent: Accept Route Advertisements even with
#   IPv6 forwarding enabled.
#   In my case, this is not needed as DHCP6 is used for prefix delegation.
#   The value should be the interface where your ISP will be doing RA.
#ipv6_cpe_wanif="exoppp"

This is effective after a reboot, using sysctl and so on is possible, but…

Provide IPv6 connectivity with SLAAC

This is also done with the base system, in this case man 5 rtadvd.conf, man 5 rc.conf and man 8 rtadvd are the magic man pages.

It further follows the pattern, we setup /etc/rc.conf:

rtadvd_enable="YES"
rtadvd_interfaces="lair"

And the software in /etc/rtadvd.conf:

# rtadvd will try to get the data from the kernel's routing table
# TODO: use own DNS servers, this uses quad9.
lair:\
    :mininterval#5:\
    :maxinterval#10:\
    :rdnss="2620:fe::fe,2620:fe::9"\
    :mtu#auto:\
    :rltime#60:

And then start it with

service rtadvd start

At this point we also modify /usr/local/etc/dhcp6c.conf to assign a delegated /64 to the lair interface as opposed to the igb1 one. See previous post for the base config.

Now, when another system connects to the lair bridge (that includes the access point on wlan0), it will automagically receive the /64 prefix information and derive its addresses as necessary (temporary, non-temporary, random, it’s all black magic).

BUT! Keep on reading, this is important!

Secure the firewall

Up until now only our router was accessible from the internet without a firewall, but it also had no services running (besides SSH with Public Key based authentication); with the previous step though, besides providing internet to the network, we provide our internal network to the internet :-).

Remember that up until now /etc/pf.conf was empty.

My firewall rules are non-trivial and keep evolving, so they won’t be replicated here, instead there will be some cdist type with them soon.

Needless to say, man pf.conf, man pf and man pfctl are the magical man pages and block all the things.

TODO: publish the cdist types and link them here

Remaining work

Legacy IPv4

  • Setup dhcpd to hand out local IPv4s
  • Setup NAT
  • Create cdist types for all the things

Internal network bits

  • Monitoring (Prometheus)
  • DNS (unbound)
  • Traffic dashboards (taking into account the percentiles)