OpenBSD Router, 2nd draft
Welcome back to the thunderdome: a one-stop-shop to get your brain thoroughly bashed with incomprehensible ideas and ineffable concepts.
That is to say, welcome back to the OpenBSD router discussion. This is the short version: a bit of interstitial text, but mostly just a place to put all the separate config files and scripts that need to be synchronized.
We assume this is a fresh installation of OpenBSD 6.9 on a dedicated physical box which has separate ethernet ports for each subnet and the egress point.
When each of the following pieces have been added, reboot the router. That’s the simplest way to get everything started properly.
network design
0.0.0.0/0
+-----------------------------+
| open internet |
+-+---------------------------+
|
|
| 123.12.23.2
+-+---------------------------+
| ISP-assigned router |
| device: em2 |
+-+---------------------------+
|
|
| 192.168.1.102
+-+---------------------------+
| firewall / router |
| (OpenBSD) |
+-+--+------------------------+
| |
| |
| | 10.0.1.1/24 +------------+-----------------------+
| | +------------------------+ | | |
| +--+ (insecure network) +---+ +--------+---------+ +----------+----------+
| | device: em0 | |wifi access points| |laptops, servers, etc|
| +------------------------+ +------------------+ +---------------------+
|
|
| 10.0.2.1/24 +------------+-----------------------+
| +------------------------+ | | |
+-----+ (secure network) +---+ +--------+---------+ +----------+----------+
| device: em1 | |wifi access points| |laptops, servers, etc|
+------------------------+ +------------------+ +---------------------+
Note, depending on the OpenBSD firewall/router box configuration, there can also be virtual machines inside that box which are connected to one or more of the subnets.
The router will have an ip address on each of the subnets; this is referred to as the ‘gateway address’, since the router is literally a gateway out of the sub-network. That IP address is usually the first in the available series: i.e., 100.100.1.1 and 100.100.2.1 in the two examples above.
I like having the wireless clients on the same subnet as the wired clients, but that’s my use case. It can be nearly as easy to put all the wifi APs on their own subnet.
router construction
Allow packets to be forwarded between network devices on the OpenBSD machine.
echo 'net.inet.ip.forwarding=1' > /etc/sysctl.conf
Request an IP address using DHCP for the network device port connected to the open internet (em2
).
echo 'dhcp' > /etc/hostname.em2
It should (IIRC) now be possible to get online now by restarting the system network connections with the new configuration.
sh /etc/netstart
Define the subnets provided by each network device port.
echo 'inet 10.0.0.1 255.255.255.0 10.0.0.255 description "secure network"' > /etc/hostname.em0
echo 'inet 10.0.1.1 255.255.255.0 10.0.1.255 description "insecure network"' > /etc/hostname.em1
DHCP (IP address assignment)
Start the dhcpd
daemon, and tell it which network device ports will need the dhcp service available.
rcctl enable dhcpd
rcctl set dhcpd flags em0 em1
Modify the dhcpd config file.
/etc/dhcpd.conf
option domain-name "ninthiteration.lab";
subnet 10.0.0.0 netmask 255.255.255.0 {
option routers 10.0.0.1;
option domain-name-servers 10.0.0.1;
range 10.0.0.10 10.0.0.254;
}
subnet 10.0.1.0 netmask 255.255.255.0 {
option routers 10.0.1.1;
option domain-name-servers 10.0.1.1;
range 10.0.1.10 10.0.1.254;
}
PF (firewall)
An exhaustive (believe me, it was exhausting to make) explanation of the contents of this file is in the longer version of this post.
/etc/pf.conf
secure = "em0"
insecure = "em1"
table <martians> { 0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 \
172.16.0.0/12 192.0.0.0/24 192.0.2.0/24 224.0.0.0/3 \
192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 \
203.0.113.0/24 }
set block-policy drop
set loginterface egress
set skip on lo0
match in all scrub (no-df random-id max-mss 1440)
match out on egress inet from !(egress:network) to any nat-to (egress:0)
antispoof quick for { egress $secure $insecure }
block in quick on egress from <martians> to any
block return out quick on egress from any to <martians>
block all
pass out quick inet
pass in on { $secure $insecure } inet
DNS
Enable the unbound
DNS daemon.
rcctl enable unbound
The unbound daemon puts itself in a chroot after starting, so its config file is buried a little deeper than the others.
/var/unbound/etc/unbound.conf
server:
interface: 10.0.0.1
interface: 10.0.1.1
interface: 127.0.0.1
access-control: 0.0.0.0/0 refuse
access-control: 10.0.0.1/24 allow
access-control: 10.0.1.1/24 allow
do-not-query-localhost: no
hide-identity: yes
hide-version: yes
forward-zone:
name: "."
forward-addr: 192.168.43.79 # IP of the upstream resolver
Nameserver
We want router to use its own unbound DNS cache.
/etc/resolv.conf
nameserver 127.0.0.1
nameserver 192.168.43.79
Problem is, this gets overwritten every time dhcp runs, because part of the dhcp protocol is a record of the server which provided the IP address. We have our own such server, and we want to use it instead.
/etc/dhclient.conf
interface "em2" {
ignore domain-name-servers;
}