💾 Archived View for paritybit.ca › sysadmin › openbsd-router.gmi captured on 2022-03-01 at 15:04:30. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

OpenBSD Router

Hardware

The hardware consists of an HP Compaq Pro 4300 SFF PC with the following specifications:

Software

There are three major software components to this router:

DHCP

DHCP is handled by dhcpd, configuration is in `/etc/dhcpd.conf`.

This is the configuration:

option domain-name "paritybit.ca";

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.51 10.0.0.254;
	host hades {
		fixed-address 10.0.0.2;
		hardware ethernet 70:85:c2:54:98:92;
	}
	host hecate {
		fixed-address 10.0.0.3;
		hardware ethernet a4:1f:72:61:f4:fc;
	}
	host cerberus {
		fixed-address 10.0.0.4;
		hardware ethernet b0:83:fe:9b:8a:e3;
	}
	host eurynomos {
		fixed-address 10.0.0.5;
		hardware ethernet f8:bc:12:87:39:93;
	}
}
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.3 10.0.1.254;
}

There are two subnets, one for LAN (10.0.0.0/24) and one for WLAN (10.0.1.0/24).

There are reserved addresses for hades (my desktop), hecate (my test server), cerberus (my main server), and eurynomos (my NAS). The reserved addresses range for the LAN network is probably larger than it needs to be, but I won't have anywhere close to 200 devices/services anyways.

Firewall

The firewall is handled by pf which stores its configuration at `/etc/pf.conf`.

This is the basic configuration, with port-forwarding rules appended if needed:

WAN  = "em0"
LAN  = "em1"
WLAN = "bge0"

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 basic firewall settings
set block-policy drop
set loginterface egress
set skip on lo0

# Normalize incoming packets and perform NAT translation
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)

# Protect from spoofed addresses and block traffic to/from non-routables
block in from no-route
block in quick from urpf-failed
block in quick on egress from <martians> to any
block return out quick on egress from any to <martians>

# Default deny incoming traffic
block all

# Block all DNS requests not addressed to this router
block return in quick on $LAN proto { udp tcp } to ! $LAN port { 53 853 }
block return in quick on $WLAN proto { udp tcp } to ! $WLAN port { 53 853 }

# Allow all outbound traffic
pass out quick inet

# Allow internal LAN/WLAN traffic
pass in on { $LAN $WLAN } inet

DNS

DNS is provided by unbound which keeps its configuration at `/var/unbound/etc/unbound.conf`.

Here is the configuration:

server:
	interface: 10.0.0.1
	interface: 10.0.1.1
	interface: 127.0.0.1

	access-control: 127.0.0.1/8 allow
	access-control: 10.0.0.0/24 allow
	access-control: 10.0.1.0/24 allow
	do-not-query-localhost: no

	hide-identity: yes
	hide-version: yes

	cache-min-ttl: 3600
	prefetch: yes

	# Perform DNSSEC validation.
	auto-trust-anchor-file: "/var/unbound/db/root.key"
	val-log-level: 2

	# Synthesize NXDOMAINs from DNSSEC NSEC chains.
	# https://tools.ietf.org/html/rfc8198
	aggressive-nsec: yes

forward-zone:
	name: "."
	forward-addr: 1.1.1.1

remote-control:
	control-enable: yes
	control-interface: /var/run/unbound.sock

Note that, because the WAN address is acquired with DHCP, the following is required in `/etc/dhclient.conf`:

interface "em0" {
	ignore domain-name-servers;
}

Reverse Proxy

table <webserver>      { 127.0.0.1 }
table <webserver2>     { 127.0.0.1 }
table <matrixserver>   { 127.0.0.1 }

http protocol "https" {
	tcp { nodelay, sack, socket buffer 65536, backlog 128 }

	tls keypair "paritybit.ca"
	tls keypair "jbauer.ca"

	return error

        match header set "X-Client-IP" \
                value "$REMOTE_ADDR:$REMOTE_PORT"
        match header set "X-Forwarded-For" \
                value "$REMOTE_ADDR"
        match header set "X-Forwarded-By" \
                value "$SERVER_ADDR:$SERVER_PORT"

	# set CORS header for .well-known/matrix/server, .well-known/matrix/client
	# httpd does not support setting headers, so do it here
	match request path "/.well-known/matrix/*" tag "matrix-cors"
	match response tagged "matrix-cors" header set "Access-Control-Allow-Origin" value "*"

	pass quick path "/_matrix/*" forward to <matrixserver>
	pass quick path "/_synapse/client/*" forward to <matrixserver>

	pass request quick header "Host" value "matrix.paritybit.ca" \
		forward to <matrixserver>

	# pass other traffic to webserver
	pass request header "Host" value "paritybit.ca" forward to <webserver>
	pass request header "Host" value "www.paritybit.ca" forward to <webserver>
	pass request header "Host" value "ftp.paritybit.ca" forward to <webserver>
	pass request header "Host" value "jbauer.ca" forward to <webserver2>
}

relay "https_traffic" {
	listen on egress port https tls
	protocol "https"
	forward to <matrixserver> port 8008 check tcp
	forward to <webserver> port 8080 check tcp
	forward to <webserver2> port 8081 check tcp
}

http protocol "matrix" {
	tcp { nodelay, sack, socket buffer 65536, backlog 128 }
	tls keypair "paritybit.ca"
	block
	pass quick path "/_matrix/*" forward to <matrixserver>
	pass quick path "/_synapse/client/*" forward to <matrixserver>
}

relay "matrix_federation" {
	listen on egress port 8448 tls
	protocol "matrix"
	forward to <matrixserver> port 8008 check tcp
}