Using OpenWRT / LEDE for Out-of-Band Management

My day job is IT security for large, blue-chip organisations. I usually work on diverse, heterogeneous networks and have to remember which commands, menus, and options are applicable to whichever piece of equipment I might be using at the time. There ain’t no such thing as a single standard, so it’s important that I retain some sort of mental dexterity if I’m to have any hope of carrying out my job.

At home, I use Microsoft Windows, Linux, Apple macOS, Apple iOS, and Android interchangeably, in a laudable laughable attempt to prevent my brain from going stale. And my home network is similarly diverse. My network kit runs the gamut from cheap (or free) embedded devices, to enterprise-grade fully-managed devices.

My ISP graciously provides a /29 subnet for my use, and I have segmented it up like a proper enterprise network and everything. Well, sort of. You can only get a maximum of four /31’s from a /29, but it’s still better than a single dynamic IP address, right?

My external WAN router is an Ubiquiti EdgeRouter Lite. Behind that is a Cisco ASA 5506-X firewall. Providing inner LAN routing duties and Wi-Fi is an ageing Buffalo WZR-HP-G300NH running LEDE 17.01.4. DNS is provided by a Raspberry Pi running Pi-hole. I also have an OpenVPN server so I can connect via VPN to home when I’m out and about. There are even a Cisco Catalyst 2960-C, a Netgear M4100-D12G, a Netgear GS105Ev2, and a Netgear GS108Tv2 in the mix. Nearly all of this equipment was picked up for peanuts on eBay.

I call it Project Overkill. Because too much is never enough.

Recently it occurred to me: all this gadgetry might be fine and dandy, but what happens if my Internet connection drops when I’m away from home? I can’t connect to the VPN to check things out. Equally, what if I do something boneheaded and ham-fisted to the WAN router or firewall and lose Internet access?

Well, I could wait until I get home, or I could get off my fat, lazy backside and walk into the next room and plug a console cable into the offending device. But that’s too sensible and easy. This is Project Overkill, after all. Instead, what about configuring a separate out-of-band management network, for those times when something inevitably goes wrong?

The WAN router and firewall both have console ports for out-of-band management. I installed a Perle IOLAN STS8 console server, a spare TP-Link TL-WR810N, also running LEDE 17.01.4, and a Netgear LB2120 LTE bridge with a SIM from a separate Internet Service Provider.

The ISP in question is one of the few mobile data ISP’s in the UK which provides a static, routed public IP address, instead of using NAT and dynamic RFC1918 addresses. The monthly subscription for the service is only a couple of quid, but that does not include any data. All data usage is billed, and it’s expensive: £25 per gigabyte, with no caps.

As a result, I need to be very careful about what traffic I permit over the mobile data network, to keep usage costs at a minimum. I don’t fancy eating bread and water for months at a time. Fortunately, LEDE and OpenWRT use the old, familiar iptables to manage traffic.

If all this nonsense sounds like it might be right up your alley, here’s how you can do something equally berserk. This is a work in progress, and will be refined as I learn new, “improved” ways of doing things… or merely change my fickle mind.

My requirements

  • Outbound traffic on the TL-WR810N’s WAN interface should be restricted to the LB2120 bridge’s management page and the ISP’s time servers only. No other outbound traffic should be permitted on the WAN interface at all, not even DNS.
  • Inbound traffic to the TL-WR810N’s WAN interface should be permitted solely to a VPN, specifically OpenVPN. Other VPN options may be investigated as and if I get opportunity/motivation. I’ve been using OpenVPN for around a decade or so. It’s reliable and easy enough to configure. It’s not the fastest choice, but it suits my needs for now.
  • The VPN should be disguised by port knocking; no ports should be directly exposed to the Internet. Paranoia is an essential part of Project Overkill. Remember, kids: too much is never enough.
  • Minimal ports open on the TL-WR810N: tcp/22 (SSH), tcp/443 (OpenVPN), and udp/1194 (OpenVPN).
  • uhttpd should be disabled. I can manage the TL-WR810N via the command line; if I ever need GUI administration I can enable uhttpd as required, and it will be HTTPS only.
  • dnsmasq and odhcpd should both be disabled; the TL-WR810N does not need to provide DHCP or DNS services for this.
  • Key-based authentication for SSH; no passwords should be allowed.

Equipment I had lying around

  • TP-Link TL-WR810N, running LEDE 17.01.4
  • 8GB USB flash drive
  • Netgear LB2120 4G LTE bridge
  • Netgear GS105Ev2 switch
  • Perle IOLAN STS8 terminal server

I connected the above together thusly:

  • WAN port of the TL-WR810N to the LAN port of the LB2120
  • LAN port of the TL-WR810N to the GS105Ev2 switch
  • Ethernet port of the STS8 to the same GS105Ev2 switch
  • USB stick in the USB socket of the TL-WR810N

I configured the LB2120 in bridge mode, so that it passes the public IP address through to the TL-WR810N. The other option, router mode, wasn’t suitable. I want to allow inbound connections, and the LB2120 does not offer any DMZ or port forwarding features. So bridge mode it is, and the TL-WR810N can control the inbound traffic.

The TL-WR810N has only 8MB of built-in storage. For normal use this is fine, but successive upgrades of the various included software packages, plus the installation of additional software packages for this project, soon ate away at the available storage, to the point where I ran out of space while testing.

This is where the 8GB USB stick comes into play. 8GB is a ridiculous amount of storage for something like this (even 16MB would have been sufficient), but it was the smallest-capacity device I had to hand.

LEDE offers a feature called extroot, which allows the device’s filesystem to be mounted from an external device, in this case a USB stick, and the device can make use of all of the available space on the USB stick. Goodbye 8MB, hello 8GB!

The OpenWRT page on extroot explains how to use it just for the writable area of the built-in storage, called the overlay, but it’s easy enough to adapt the instructions and use it for the entire system. extroot is straightforward to configure. First, format the USB stick as ext4. Then install some additional software packages on the TL-WR810N to support a USB stick:

opkg update
opkg install block-mount kmod-usb-storage kmod-fs-ext4

Verify that the USB stick is now visible to LEDE:

root@oob-router /root [#]# block info
/dev/mtdblock2: UUID="b9987b6c-6483eae0-ddc9a928-146c8265" VERSION="4.0" MOUNT="/rom" TYPE="squashfs"
/dev/mtdblock3: TYPE="jffs2"
/dev/sda1: UUID="9c085c88-cf5d-401c-91ce-ac8eee893aa5" LABEL="usb" VERSION="1.0" MOUNT="/" TYPE="ext4"

/dev/sda1 is the usable area on the USB stick. If it’s not visible, try rebooting the TL-WR810N or even unplugging and reinserting the USB stick.

Now create a folder and mount the USB stick so that it can be used:

mkdir /mnt/usb
mount /dev/sda1 /mnt/usb

Then copy the contents of the TL-WR810N’s storage to the USB stick:

mkdir -p /tmp/rootcopy
mount --bind / /tmp/rootcopy
tar -C /tmp/rootcopy -cvf - . | tar -C /mnt/usb -xf -
umount /tmp/rootcopy

Then update /etc/config/fstab so that the USB stick is mounted automatically every time the TL-WR810N boots. Add these lines to the end of that file:

config 'mount'
 option target /
 option device /dev/sda1
 option fstype ext4
 option options rw,sync
 option enabled 1
 option enabled_fsck 0

When the device next reboots, those lines will force it to mount the USB stick at the root (/) mount point, and a lot more space will be available:

root@oob-router /root [#]# mount
[...]
/dev/sda1 on / type ext4 (rw,sync,relatime,data=ordered)
[...]

root@oob-router /root [#]# df -h
Filesystem Size Used Available Use% Mounted on
[...]
/dev/sda1 7.2G 30.9M 6.8G 0% /
[...]

Once this was achieved, I upgraded every installed software package which needed to be upgraded:

opkg update
opkg list-upgradable
opkg upgrade <package 1> <package 2> <package 3> etc. ...

Then I installed these additional software packages:

  • luci-ssl (adds HTTPS support to the GUI administration)
  • openvpn-openssl (the VPN server)
  • fwknopd (the port knocking server)
opkg install luci-ssl openvpn-openssl fwknopd

luci-ssl enabled HTTPS for the GUI administration, but the SSL certificates were not recognised by any of my web browsers. This caused warnings in my browsers, so I followed the very comprehensive tutorial at jamielinux.com, set up a Certificate Authority (CA), issued my own SSL certificates, and configured my web browsers to trust them.

Using the same CA, I created certificates for the OpenVPN server as well as for each of the clients which might be likely to connect. Then I set about configuring OpenVPN, and used another very comprehensive tutorial at cavebeat.org to harden it. I hadn’t realised just how many additional security features had been introduced into OpenVPN since I first started using it a decade ago! It was a welcome – and much-needed – reminder to keep abreast of this stuff.

I wanted the option to connect via either TCP or UDP, so my configuration file creates configurations for two separate OpenVPN instances, duplicating everything except the protocol and port number.

/etc/config/openvpn

config openvpn 'routed_udp'
# VPN on/off
 option enabled '1'

# Protocol
 option dev_type 'tun'
 option dev 'udp_tun'
 option topology 'subnet'
 option proto 'udp'
 option port '1194'
 option local 'x.x.x.x'
# Replace x.x.x.x with your own public IP address


# Routing
 option server '192.168.50.0 255.255.255.0'
 option ifconfig '192.168.50.1 255.255.255.0'
 list push 'route 172.16.0.0 255.255.255.0'

# Client configs
 option ccd_exclusive '1'
 option client_config_dir '/etc/openvpn/clients/'
 option max_clients '10'
 option client_to_client '1'

# Encryption
 option ca '/etc/openvpn/chain.crt'
 option cert '/etc/openvpn/srv.crt'
 option key '/etc/openvpn/srv.key'
 option dh '/etc/openvpn/dh4096.pem'
 option tls_crypt '/etc/openvpn/ta.key'
 option cipher 'AES-256-GCM'
 option auth 'sha512'
 option tls_server '1'
 option tls_version_min '1.2'
 option tls_cipher 'TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384'
 option reneg_sec '1800'
 option reneg_bytes '64000000'
 option remote_cert_tls 'client'
 option verify_client_cert '1'

# Logging
 option log_append '/tmp/log/openvpn/openvpn-udp.log'
 option status '/tmp/log/openvpn-udp-status.log'
 option mute '5'
 option verb '4'

# Connection
 option keepalive '10 60'
 option compress 'lzo'
 option script_security '1'

# Connection reliability
 option persist_key '1'
 option persist_tun '1'

# Permissions
 option user 'nobody'
 option group 'nogroup'

config openvpn 'routed_tcp'
# VPN on/off
 option enabled '1'

# Protocol
 option dev_type 'tun'
 option dev 'tcp_tun'
 option topology 'subnet'
 option proto 'tcp'
 option port '443'
option local 'x.x.x.x'
# Replace x.x.x.x with your own public IP address

# Routing
 option server '192.168.60.0 255.255.255.0'
 option ifconfig '192.168.60.1 255.255.255.0'
 list push 'route 172.16.0.0 255.255.255.0'

# Client configs
 option ccd_exclusive '1'
 option client_config_dir '/etc/openvpn/clients/'
 option max_clients '10'
 option client_to_client '1'

# Encryption
 option ca '/etc/openvpn/chain.crt'
 option cert '/etc/openvpn/srv.crt'
 option key '/etc/openvpn/srv.key'
 option dh '/etc/openvpn/dh4096.pem'
 option tls_crypt '/etc/openvpn/ta.key'
 option cipher 'AES-256-GCM'
 option auth 'sha512'
 option tls_server '1'
 option tls_version_min '1.2'
 option tls_cipher 'TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384'
 option reneg_sec '1800'
 option reneg_bytes '64000000'
 option remote_cert_tls 'client'
 option verify_client_cert '1'

# Logging
 option log_append '/tmp/log/openvpn/openvpn-tcp.log'
 option status '/tmp/log/openvpn-tcp-status.log'
 option mute '5'
 option verb '4'

# Connection
 option keepalive '10 60'
 option compress 'lzo'
 option script_security '1'

# Connection reliability
 option persist_key '1'
 option persist_tun '1'

# Permissions
 option user 'nobody'
 option group 'nogroup'

The VPN will only permit connections from devices it recognises (the “Client configs” section). If I forget to add appropriate files for each client in /etc/openvpn/clients then attempts to connect from an unrecognised device will be rejected, even if the certificates match. Paranoid? Of course! Again, this is Project Overkill.

The firewall is, as noted above, the trusty, reliable iptables. It also has a configuration file in /etc/config to control its behaviour.

/etc/config/firewall

# Certain iptables rules cannot be defined in this config file,
# and must instead be explicitly created in a script. This calls
# the script in question.

config include
 option path '/etc/firewall.user'


# The following lines configure iptables to drop all unrecognised
# traffic from everywhere. Then, individual rules will permit
# specific traffic. This is more restrictive than the default
# configuration of OpenWRT/LEDE, which assumes that a typical
# user will want to allow all outbound traffic. Not so in this
# case; remember the need to keep outbound traffic to a minimum
# to mitigate against a large ISP bill.

config defaults
 option syn_flood '1'
 option drop_invalid '1'
 option input 'DROP'
 option output 'DROP'
 option forward 'DROP'

config zone
 option name 'lan'
 option input 'DROP'
 option output 'DROP'
 option forward 'DROP'
 option network 'lan'

config zone
 option name 'wan'
 option masq '1'
 option input 'DROP'
 option output 'DROP'
 option forward 'DROP'
 option network 'wan'

config zone
 option name 'vpn'
 option input 'DROP'
 option output 'DROP'
 option forward 'DROP'
 option network 'openvpn_tcp openvpn_udp'


# The only device permitted to supply DHCP to the TL-WR810N is
# the LB2120.

config rule
 option name 'Allow-DHCP-Renew'
 option src 'wan'
 option src_ip '192.168.5.1'
 option proto 'udp'
 option family 'ipv4'
 option dest_port '68'
 option target 'ACCEPT'


# All devices on the LAN are assumed to be trusted, and may
# communicate with the TL-WR810N.

config rule
 option name 'LAN: Ping me'
 option src 'lan'
 option proto 'icmp'
 option icmp_type 'echo-request'
 option family 'ipv4'
 option dest_ip '172.16.0.2'
 option target 'ACCEPT'

config rule
 option name 'LAN: SSH to me'
 option src 'lan'
 option proto 'tcp'
 option family 'ipv4'
 option dest_ip '172.16.0.2'
 option dest_port '22'
 option target 'ACCEPT'

config rule
 option name 'LAN: HTTPS to me'
 option src 'lan'
 option proto 'tcp'
 option family 'ipv4'
 option dest_ip '172.16.0.2'
 option dest_port '443'
 option target 'ACCEPT'


# Similarly, certain subnets on the LAN may communicate with the
# LB2120 LTE bridge.

config rule
 option name 'LAN: Ping LB2120'
 option src 'lan'
 option src_ip '192.168.20.0/24'
 option proto 'icmp'
 option icmp_type 'echo-request'
 option family 'ipv4'
 option dest 'wan'
 option dest_ip '192.168.5.1'
 option target 'ACCEPT'

config rule
 option name 'LAN: Ping LB2120'
 option src 'lan'
 option src_ip '192.168.30.0/24'
 option proto 'icmp'
 option icmp_type 'echo-request'
 option family 'ipv4'
 option dest 'wan'
 option dest_ip '192.168.5.1'
 option target 'ACCEPT'

config rule
 option name 'LAN: Ping LB2120'
 option src 'lan'
 option src_ip '192.168.40.0/24'
 option proto 'icmp'
 option icmp_type 'echo-request'
 option family 'ipv4'
 option dest 'wan'
 option dest_ip '192.168.5.1'
 option target 'ACCEPT'

config rule
 option name 'LAN: HTTP to LB2120'
 option src 'lan'
 option src_ip '192.168.20.0/24'
 option proto 'tcp'
 option family 'ipv4'
 option dest 'wan'
 option dest_ip '192.168.5.1'
 option dest_port '80'
 option target 'ACCEPT'

config rule
 option name 'LAN: HTTP to LB2120'
 option src 'lan'
 option src_ip '192.168.30.0/24'
 option proto 'tcp'
 option family 'ipv4'
 option dest 'wan'
 option dest_ip '192.168.5.1'
 option dest_port '80'
 option target 'ACCEPT'

config rule
 option name 'LAN: HTTP to LB2120'
 option src 'lan'
 option src_ip '192.168.40.0/24'
 option proto 'tcp'
 option family 'ipv4'
 option dest 'wan'
 option dest_ip '192.168.5.1'
 option dest_port '80'
 option target 'ACCEPT'


# Successfully authenticated VPN clients may communicate with
# devices on the LAN.

config rule
 option name 'VPN: Ping LAN'
 option src 'vpn'
 option proto 'icmp'
 option icmp_type 'echo-request'
 option family 'ipv4'
 option dest 'lan'
 option target 'ACCEPT'

config rule
 option name 'VPN: SSH to me'
 option src 'vpn'
 option proto 'tcp'
 option family 'ipv4'
 option dest_ip '172.16.0.2'
 option dest_port '22'
 option target 'ACCEPT'

config rule
 option name 'VPN: HTTPS to me'
 option src 'vpn'
 option proto 'tcp'
 option family 'ipv4'
 option dest_ip '172.16.0.2'
 option dest_port '443'
 option target 'ACCEPT'

config rule
 option name 'VPN: Ping LB2120'
 option src 'vpn'
 option proto 'icmp'
 option icmp_type 'echo-request'
 option family 'ipv4'
 option dest 'wan'
 option dest_ip '192.168.5.1'
 option target 'ACCEPT'

config rule
 option name 'VPN: HTTP to LB2120'
 option src 'vpn'
 option proto 'tcp'
 option family 'ipv4'
 option dest 'wan'
 option dest_ip '192.168.5.1'
 option dest_port '80'
 option target 'ACCEPT'

config rule
 option name 'VPN: SSH to STS'
 option src 'vpn'
 option proto 'tcp'
 option family 'ipv4'
 option dest 'lan'
 option dest_ip '172.16.0.3'
 option dest_port '22'
 option target 'ACCEPT'

config rule
 option name 'VPN: HTTPS to STS'
 option src 'vpn'
 option proto 'tcp'
 option family 'ipv4'
 option dest 'lan'
 option dest_ip '172.16.0.3'
 option dest_port '443'
 option target 'ACCEPT'

The script called by the firewall configuration file contains some direct iptables commands. The firewall configuration file assumes that traffic originates or finishes in a zone known to the firewall, or finishes at the TL-WR810N, but does not have any facility to control traffic which originates from the TL-WR810N. For this, direct iptables commands are required.

/etc/firewall.user

# Allow outbound ping to other LAN subnets, for testing/diagnostics
iptables -I zone_lan_output -s 172.16.0.2/32 -p icmp -m icmp --icmp-type 8 -d 192.168.0.0/24 -j ACCEPT
iptables -I zone_lan_output -s 172.16.0.2/32 -p icmp -m icmp --icmp-type 8 -d 192.168.1.0/24 -j ACCEPT
iptables -I zone_lan_output -s 172.16.0.2/32 -p icmp -m icmp --icmp-type 8 -d 192.168.2.0/24 -j ACCEPT
iptables -I zone_lan_output -s 172.16.0.2/32 -p icmp -m icmp --icmp-type 8 -d 192.168.3.0/24 -j ACCEPT
iptables -I zone_lan_output -s 172.16.0.2/32 -p icmp -m icmp --icmp-type 8 -d 192.168.20.0/24 -j ACCEPT

# Allow DNS queries outbound via LAN
iptables -I zone_lan_output -s 172.16.0.2/32 -p udp -m udp --dport 53 -j ACCEPT

# Allow OPKG package updates via LAN
iptables -I zone_lan_output -s 172.16.0.2/32 -p tcp -m tcp --dport 80 -j ACCEPT
iptables -I zone_lan_output -s 172.16.0.2/32 -p tcp -m tcp --dport 443 -j ACCEPT

# Allow NTP queries outbound via LAN
iptables -I zone_lan_output -s 172.16.0.2/32 -p udp -m udp --dport 123 -j ACCEPT

# Allow NTP queries outbound via WAN
iptables -I zone_wan_output -s x.x.x.x/32 -p udp -m udp --dport 123 -j ACCEPT
# Replace x.x.x.x with your own public IP address.

The firewall still blocks unsolicited inbound traffic to the WAN interface, so the VPN will not be usable until ports tcp/443 and udp/1194 are opened up to the outside world. This is achieved by port knocking, using a program called fwknopd. This listens for specially crafted traffic (knocking) and then adjusts the firewall to permit the OpenVPN traffic for a short duration. If no VPN client connects, the ports are closed after 30 seconds. If a VPN client does connect, the traffic is permitted as long as the session is active. As with most other packages on OpenWRT/LEDE, it is configured by a file in /etc/config.

/etc/config/fwknopd

config global
 option uci_enabled '1'
# UCI is the simplified, abstracted configuration language used by
# OpenWRT/LEDE. This option tells fwknopd to use the configuration 
# generated by this file, instead of its own configuration elsewhere.

config access
 option keytype 'Base 64 key'
 option hkeytype 'Base 64 key'
 option FW_ACCESS_TIMEOUT '30'
 option SOURCE 'ANY'
 option OPEN_PORTS 'tcp/443,udp/1194'
 option KEY_BASE64 'PUT YOUR SHORTER KEY HERE'
 option HMAC_KEY_BASE64 'PUT YOUR LONGER HMAC KEY HERE'

config config
 option PCAP_INTF 'eth0'
 option ENABLE_IPT_FORWARDING 'y'
 option ENABLE_NAT_DNS 'y'

The network interfaces are also defined in a file in /etc/config.

/etc/config/network

config interface 'loopback'
 option ifname 'lo'
 option proto 'static'
 option ipaddr '127.0.0.1'
 option netmask '255.0.0.0'

config globals 'globals'

config interface 'lan'
 option ifname 'eth1'
 option proto 'static'
 option delegate '0'
 option ipaddr '172.16.0.2'
 option netmask '255.255.255.0'
 option gateway '172.16.0.1'
# All outbound network traffic is routed through the LAN interface
# by default, with a few exceptions below. This also helps to
# guard against unwanted outbound traffic driving up the ISP's
# monthly bill.
 option broadcast '172.16.0.255'
 option dns '10.0.0.2'

config interface 'wan'
 option ifname 'eth0'
 option proto 'dhcp'
 option delegate '0'
 option defaultroute '0'
 option peerdns '0'

config interface 'openvpn_tcp'
 option ifname 'tcp_tun'
 option proto 'none'
 option delegate '0'

config interface 'openvpn_udp'
 option ifname 'udp_tun'
 option proto 'none'
 option delegate '0'


# In bridge mode, the LB2120 gives the TL-WR810N a public IP
# address, and sets itself up as the next hop. This is in a
# different subnet from the LB2120's management address. This
# route directs management traffic for the LB2120 to the next
# hop set up by the LB2120, preserving the ability to manage it
# on the address 192.168.5.1.

config route
 option interface 'wan'
 option target '192.168.5.1'
 option gateway 'y.y.y.y'
# replace y.y.y.y with the appropriate gateway for your scenario.
 option metric '0'


# The mobile data ISP maintains two NTP servers. Similar to the
# LB2120 management traffic above, these routes direct traffic
# for those two servers.

config route
 option interface 'wan'
 option target 'z.z.z.1'
# replace z.z.z.1 with the IP address of your first desired NTP server.
 option gateway 'y.y.y.y'
# replace y.y.y.y with the appropriate gateway for your scenario.
 option metric '0'

config route
 option interface 'wan'
 option target 'z.z.z.2'
# replace z.z.z.2 with the IP address of your second desired NTP server.
 option gateway 'y.y.y.y'
# replace y.y.y.y with the appropriate gateway for your scenario.
 option metric '0'

Some pauses during booting are needed to give everything a chance to initialise properly. Then some key services are restarted, and a vital route is added.

/etc/rc.local

sleep 10

# The earlier network configuration directs all traffic, with only
# a couple of exceptions for NTP, via the LAN interface. However,
# the VPN needs to know where to send VPN-related traffic during
# a session.

# With the configuration above, the TL-WR810N will try to send
# replies via the LAN interface. This is asymmetric routing and is
# not desirable for this scenario. Instead, there needs to be a
# way to tell the TL-WR810N to send any WAN-related traffic out
# through the LB2120.

# In a nutshell, the TL-WR810N needs an extra piece of
# configuration to tell it to send any replies out through the WAN
# interface, if the originating traffic was received in via the WAN
# interface.

# This is achieved by combining the firewall (which permits the
# traffic after the port knocking challenge is passed) with a
# specific route instruction to direct replies to WAN traffic.

# These next two lines add a route configuration which tells the
# TL-WR810N to override the default LAN route for traffic which
# has entered via the WAN, i.e. any successful VPN traffic. It's
# a crude variant of policy-based routing.

# Doing it this way allows for inbound connections from unknown
# or dynamic IP addresses. I can't always guarantee that I'd be
# connecting from the same IP address every time, which means
# a normal static route isn't suitable. Instead, a route based
# on the interface of the inbound traffic achieves the desired
# result.

ip rule add from x.x.x.x table wan
# Replace x.x.x.x with your own public IP address.

ip route add default via y.y.y.y dev eth0 table wan
# Replace y.y.y.y with the real next hop for your public IP address.

sleep 10
/etc/init.d/openvpn restart

sleep 10
/etc/init.d/fwknopd restart

sleep 10
/etc/init.d/firewall restart

exit 0

And finally, I should adjust the SSH server configuration to prohibit password authentication and to display a login banner to warn off any bad guys. Because they all pay attention to that stuff, right?

/etc/config/dropbear

config dropbear
 option Port '22'
 option Interface 'lan'
 option PasswordAuth 'off'
 option RootPasswordAuth 'off'
 option BannerFile '/etc/dropbear/dropbearbanner'

/etc/dropbear/authorized_keys

ssh-rsa AAAAB3Nz [...] Am78= sshkeyname

/etc/dropbear/dropbearbanner

+===============================================================+
|                                                               |
| This is a private system. All unauthorised use is prohibited. |
|                                                               |
|   All access is logged, and any misuse will be prosecuted.    |
|                                                               |
+===============================================================+

(The above looks better in a monospaced font. One day I’ll get to grips with this WordPress thing…)

After all this activity, I now have a separate means of connecting to my external WAN router and firewall, which persists even if my main Internet connection drops or I inevitably bungle some configuration and break my internal network.

I can also use it to monitor service-disrupting firmware upgrades: I can connect to the out-of-band network, then to the STS8 terminal server, and then to the console port of the device I’m upgrading, and can watch the entire progress of the upgrade instead of blindly trusting that the upgrade will succeed and the device will come back online without any problems…

Further adventures in Project Overkill will follow, including setting up IP telephony, setting up a security camera or two (when I finally decide which one to buy), and anything else which both takes my fancy and is ludicrously excessive for a small home network.