Guardian

This document describes how to build Guardian, a switch, router, and firewall. Guardian runs on commodity router hardware and provides a number of features, including:

  • a wireless access point,
  • a switch comprised of a number of Gigabit Ethernet ports,
  • a firewall and NAT translator, and
  • a print service.

Guardian is made up of the following hardware components:

  • a Microtik RouterBoard 493G,
  • a Microtik RouterBoard R52n-M miniPCI wireless adapter,
  • a Microtik 5V USB power injector,
  • a RouterBoard 493G case with interior USB extension cable,
  • two whip antennas,
  • a Belkin USB-to-RS-232 adapter,
  • an RS-232 cable,
  • a null-modem adapter,
  • a GFP121U-0520 GME switching AC/DC power adapter, and
  • a USB printer.

I purchased my hardware from Baltic Networks.

Selecting the software for a Guardian image

This section describes how to gather and select the OpenWrt source code which makes up Guardian.

  1. Obtain the OpenWrt source tree using git clone https://git.openwrt.org/openwrt/openwrt.git.
  2. Enter the OpenWrt source tree and modify the package configuration provided by feeds.conf to use src-git packages ssh://git@github.com/MikePetullo/packages.git. Run ./scripts/feeds update.
  3. Activate the necessary packages using:
./scripts/feeds install ca-certificates \
                        ddns-scripts \
                        freifunk-watchdog \
                        libustream-openssl \
                        openvpn \
                        p910nd \
                        rsync \
                        wget \
                        zoneinfo-core \
                        zoneinfo-northamerica
  1. Run make menuconfig and select:
  • Target System: Atheros ATH79 (DTS)
  • Subtarget: Mikrotik devices
  • Target Profile: MikroTik RouterBoard 493G
  • Target Images: ramdisk then tar.gz (Note that you need to build twice for the RB493G: (1) for a TFTP image and (2) for an installable rootfs image.)
  • Base system:
    • ca-certificates
    • Kernel Modules:
      • Netfilter Extensions: kmod-ipt-tee
      • Other modules: kmod-softdog
      • USB Support:
        • kmod-usb-ohci
        • kmod-usb-printer
        • kmod-usb2
      • Wireless Drivers: kmod-ath9k
  • LuCI: Freifunk: freifunk-watchdog
  • Network:
    • File Transfer:
      • rsync
      • wget
    • Firewall: iptables-mod-tee
    • IP Addresses and Names:
      • ddns-scripts
      • ddns-scripts_no-ip.com
    • Printing: p910nd
    • VPN:
      • openvpn-openssl
  • Utilities:
    • zoneinfo: zoneinfo-northamerica
  1. Create the directory files and populate it as described in the following sections.

Configuring the network interfaces

Aside from the standard loopback device, Guardian provides for four networks:

  1. a private LAN for workstations and internal servers (192.168.1.128/25),
  2. a public LAN for Internet-facing servers (192.168.1.0/25),
  3. a WAN (DHCP-assigned), and
  4. a network for use with OpenVPN (192.168.2.0/24).

Guardian splits its switch ports between the private and public LANs. Guardian also provides WiFi connectivity to its private and public LANs.

  1. /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 switch
	option name switch0
	option enable 1
	option reset 1
	option enable_vlan 1

config switch
	option name switch1
	option enable 1
	option reset 1
	option enable_vlan 1

# Private:
config switch_vlan
	option device switch0
	option vlan 0
	option vid 100
	# 0: CPU, 1--4: phy. ports, 5 unused.
	# t indicates packets sent will be VLAN tagged; rec'd must match tag. 
	option ports "0t 1 2 3 4"

config interface privlan
	option ifname 'eth0.100 tap0' # Bridge in OpenVPN tap device.
	option type bridge
	option proto static
	option ipaddr 192.168.1.129
	option netmask 255.255.255.128

# Public:
config switch_vlan
	option device switch1
	option vlan 1
	option vid 200
	# 0: CPU, 1--4: phy. ports, 5 below.
	# t indicates packets sent will be VLAN tagged; rec'd must match tag. 
	option ports "0t 1 2 3 4"

config interface publan
	option ifname eth1.200
	option type bridge
	option proto static
	option ipaddr 192.168.1.1
	option netmask 255.255.255.128

# WAN:
config switch_vlan
	option device switch1
	option vlan 2
	option vid 300
	# t indicates packets sent will be VLAN tagged; rec'd must match tag. 
	option ports "0t 5"

config interface wan
	option ifname eth1.300
	option proto dhcp
	# Use OpenDNS (not ISP DNS) for content filter.                              
	option dns  "208.67.222.123 208.67.220.123"                                  
	option peerdns 0 

# OpenVPN:
config interface vpn
	option ifname tun0
	option proto none
  1. /etc/config/wireless (replace PCIPATH, ExampleCom, ExampleComGuest, KEY1, and KEY2):
config wifi-device radio0
	option type     mac80211
	option country	US
	option channel  11
	option hwmode   11ng
	option htmode   HT20
	option path     PCIPATH
	list ht_capab   SHORT-GI-40
	list ht_capab   TX-STBC
	list ht_capab   RX-STBC1
	list ht_capab   DSSS_CCK-40

config wifi-iface                  
	option device   radio0     
	option network  privlan    
	option mode     ap         
	option ssid     ExampleCom
	option encryption psk2       
	option key      KEY1

config wifi-iface                                                               
	option device   radio0                                                  
	option network  publan                                                  
	option mode     ap                                                      
	option ssid     ExampleComGuest
	option encryption psk2                                                  
	option key      KEY2

Configuring the firewall

Guardian’s firewall drops most incoming traffic destined for its private and OpenVPN LANs. Guardian also blocks outgoing DNS queries from its LANs which are destined to servers other than Guardian. Aside from this, Guardian allows:

  • connections from the private LAN to Guardian,
  • connections from the OpenVPN LAN to Guardian,
  • DHCP and DNS requests from the public LAN to Guardian,
  • and OpenVPN connections from anywhere to Guardian.

Guardian allows LDAPS and Kerberos traffic to flow from the public LAN to the private LAN because it assumes that the network’s authentication services exist on the private LAN.

Guardian redirects connections for the following services from the WAN to 192.168.1.5 on the public LAN:

  • SSH,
  • HTTP,
  • HTTPS,
  • SMTP,
  • XMPP client-to-server connections, and
  • XMPP server-to-server connections.

Guardian also provides a copy of all packets to 192.168.1.8 for analysis.

  1. /etc/config/firewall:
config include
	option path /etc/firewall.user

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

# WAN: NAT, drop incoming; accept outgoing; drop forward.
config zone
	option name wan
	option network wan
	option input DROP
	option output ACCEPT
	option forward DROP
	option masq 1

# Private LAN: drop incoming; accept outgoing; reject forward.
config zone
	option name privlan
	option network privlan
	option input DROP
	option output ACCEPT
	option forward REJECT

# Public (guest) LAN: drop incoming; accept outgoing; reject forward.
config zone
	option name publan
	option network publan
	option input DROP
	option output ACCEPT
	option forward REJECT

# OpenVPN LAN: drop incoming; accept outgoing; reject forward.
config zone
	option name vpn
	option network vpn
	option input DROP
	option output ACCEPT
	option forward REJECT

# Forward from private LAN to WAN.
config forwarding
	option src privlan
	option dest wan

# Forward from public LAN to WAN.
config forwarding
	option src publan
	option dest wan

# Forward from OpenVPN LAN to WAN.
config forwarding
	option src vpn
	option dest wan

# Forward from private LAN to public LAN.
config forwarding
	option src privlan
	option dest publan

# Forward from OpenVPN LAN to public LAN.
config forwarding
	option src vpn
	option dest publan

# Forward from OpenVPN LAN to private LAN.
config forwarding
	option src vpn
	option dest privlan

# Forward from private LAN to OpenVPN LAN.
config forwarding
	option src privlan
	option dest vpn

# Forbid DNS requests to outside servers unless from router.
config rule
	option target REJECT
	option src *
	option dest wan
	option dest_port 53
	option proto tcpudp

# Allow DNS requests from public LAN.
config rule
	option target ACCEPT
	option src publan
	option dest_port 53
	option proto tcpudp

# Allow ALL connections from private LAN to router.
config rule
	option target ACCEPT
	option src privlan
	option proto all

# Allow ALL connections from OpenVPN LAN to router.
config rule
	option target ACCEPT
	option src vpn
	option proto all

# Allow OpenVPN connections from anywhere to router.
config rule
	option target ACCEPT
	option src *
	option dest_port 1194
	option proto udp

# Allow DHCP requests from public LAN to router.
config rule
	option target ACCEPT
	option src publan
	option src_port 67-68
	option dest_port 67-68
	option proto udp

# Allow LDAPS requests from public LAN to private LAN.
config rule
	option target ACCEPT
	option src publan
	option dest privlan
	option dest_port 636
	option proto tcp

# Allow Kerberos requests from public LAN to private LAN.
config rule
	option target ACCEPT
	option src publan
	option dest privlan
	option dest_port 88
	option proto tcp

# Redirect HTTP to herald.
config redirect
	option target DNAT
	option src wan
	option proto tcp
	option src_dport 80
	option dest_ip 192.168.1.5
	option dest publan

# Redirect HTTPS to herald.
config redirect
	option target DNAT
	option src wan
	option proto tcp
	option src_dport 443
	option dest_ip 192.168.1.5
	option dest publan

# Redirect SMTP to herald.
config redirect
	option target DNAT
	option src wan
	option proto tcp
	option src_dport 25
	option dest_ip 192.168.1.5
	option dest publan

# Redirect Jabber client-to-server connections to herald.
config redirect
	option target DNAT
	option src wan
	option proto tcp
	option src_dport 5222
	option dest_ip 192.168.1.5
	option dest publan

# Redirect Jabber server-to-server connections to herald.
config redirect
	option target DNAT
	option src wan
	option proto tcp
	option src_dport 5269
	option dest_ip 192.168.1.5
	option dest publan
  1. /etc/firewall.user:
iptables -t mangle -A INPUT  ! -s 192.168.1.8/32 -j TEE --gateway 192.168.1.8
iptables -t mangle -A OUTPUT ! -d 192.168.1.8/32 -j TEE --gateway 192.168.1.8
iptables -t mangle -A FORWARD ! -d 192.168.1.8/32 ! -s 192.168.1.8/32 -j TEE --gateway 192.168.1.8

Configure OpenVPN

Guardian accepts OpenVPN connections, allowing access to its private LAN from remote workstations.

/etc/config/openvpn (replace example.com):

package openvpn

config openvpn privlan
	option enable 1
	option port 1194
	option proto udp
	option dev tun0
	option txqueuelen 1000
	option tun-mtu 1500
	option mssfix 1300
	option ca /etc/openvpn/ca.cert
	option cert /etc/openvpn/example.com.cert
	option key /etc/openvpn/example.com.key
	option dh /etc/openvpn/dh2048.pem
	option ifconfig-pool-persist /tmp/ipp.txt
	option keepalive '10 120'
	option persist-key 1
	option persist-tun 1
	option status /var/log/openvpn-status.log
	option verb 3
	option server '192.168.2.0 255.255.255.0'
	option client-to-client 1
	option tls-version-min 1.2
	option tls ECDHE-RSA-AES256-GCM-SHA384
	list push 'redirect-gateway def1'
	list push 'dhcp-option DNS 192.168.1.129'
	list push 'route 192.168.1.0   255.255.255.128'
	list push 'route 192.168.1.128 255.255.255.128'

# Configure basic system settings

1. `/etc/config/p910nd`:

config p910nd option device /dev/usb/lp0 option port 0 option bidirectional 1 option enabled 1

2. `/etc/config/system`:

config system option hostname guardian.example.com option timezone EST5EDT,M3.2.0,M11.1.0

config timeserver ntp list server 0.openwrt.pool.ntp.org list server 1.openwrt.pool.ntp.org list server 2.openwrt.pool.ntp.org list server 3.openwrt.pool.ntp.org option enabled 1 option enable_server 0

3 `/etc/config/ddns` (replace `examplecom`, `example.com`, `USERNAME`, and `PASSWORD`):

config service ‘examplecom’ option enabled ‘1’ option interface ‘wan’ option service_name ‘no-ip.com’ option lookup_host ‘www.example.com’ option domain ‘example.com’ option username ‘USERNAME’ option password ‘PASSWORD’ option use_https ‘1’ option cacert ‘/etc/ssl/certs’ option use_syslog ‘3’ 4. /etc/config/freifunk-watchdog:

config process
	option process dropbear	
	option initscript /etc/init.d/dropbear

config process
	option process crond
	option initscript '/etc/init.d/cron'
	
config process
	option process dnsmasq
	option initscript /etc/init.d/dnsmasq
	
config process
	option process p910nd
	option initscript /etc/init.d/p910nd
  1. /etc/config/dropbear:
config dropbear
	option PasswordAuth 'off'
	option RootPasswordAuth 'off'
	option Port         '22'
  1. /etc/config/dhcp:
config dhcp privlan
	option interface    privlan
	option start        138 # Room for static at bottom.
	option limit        254 # Room for OpenVPN at top.
	option leasetime    24h
	# GW, DNS:
	list dhcp_option "3,192.168.1.129"
	list dhcp_option "6,192.168.1.129"

config dhcp publan
	option interface    publan
	option start        10
	option limit        126
	option leasetime    24h
	# GW, DNS:
	list dhcp_option "3,192.168.1.1"
	list dhcp_option "6,192.168.1.1"

config dnsmasq
	option leasefile   '/tmp/dhcp.leases'
	option resolvfile  '/tmp/resolv.conf.auto'
	option localise_queries 1

config odhcpd 'odhcpd'
	option maindhcp '0'
	option leasefile '/tmp/hosts/odhcpd'
	option leasetrigger '/usr/sbin/odhcpd-update'

config host
	option name 'host.example.com'
	option ip '192.168.1.2'
	option mac 'aa:bb:cc:dd:ee:ff'
  1. /etc/hosts (replace examplecom):
127.0.0.1 localhost
192.168.1.1 guardian.example.com
192.168.1.5 www.example.com example.com

Build software and perform installation

  1. Run make V=99.
  2. Install the image you just built onto your router. The instructions here require a computer running Linux, in addition to the Guardian device.
  • On the Linux computer:
    1. Install dhcp-server, tftp-server, minicom, mtd-utils, and mtd-utils-ubi. Configure minicom to emulate an 115,200-bps 8N1 terminal without hardware flow control and without software flow control.
    2. Temporarily disable the host’s firewall (or allow incoming TFTP requests).
    3. Run the tftp service with in.tftpd -v -s -p -L /var/lib/tftpboot/.
    4. Place openwrt-ath79-mikrotik-mikrotik_routerboard-493g-initramfs-kernel.bin in /var/lib/tftpboot.
    5. Set the computer’s IP address to 192.168.1.3 using ip addr add 192.168.1.3/24 dev enp0s25. (You might have to do this repeatedly, because the Linux computer’s interface might drop its IP address when the router reboots.)
    6. Configure DHCP as shown below (replace XX:XX:XX:XX:XX:XX with your router’s MAC address (likely eth1), which you can discover using the router’s firmware utility), and start the DHCP server with systemctl start dhcpd.
allow booting;
allow bootp;

subnet 192.168.1.0 netmask 255.255.255.0 {
	option routers 192.168.1.3;
	option subnet-mask 255.255.255.0;
	option broadcast-address 192.168.1.255;
}

group {
	host routerboard {
		hardware ethernet XX:XX:XX:XX:XX:XX;
		next-server 192.168.1.3;
		fixed-address 192.168.1.2;
		filename "openwrt-ath79-mikrotik-mikrotik_routerboard-493g-initramfs-kernel.bin";
	}
}
  • On the router:
    1. At boot menu, use e to erase the existing OS firmware.
    2. Instruct the boot firmware to boot from the network (select o, e, and x). In order to boot the router over the network, it might be necessary to reset the Linux computer’s IP address (because the IP address might have been lost after the link momentarily went down). After the router boots, it might be necessary to wait while the router configures its network interfaces and generates its SSH keys; you might also need to deactivate the firewall’s router to permit SSH connections over its WAN interface.
    3. After booting, run passwd to set the root password.
    4. The router’s IP address should now be 192.168.1.2. Use scp to copy openwrt-ath79-mikrotik-mikrotik_routerboard-493g-squashfs-sysupgrade.bin to the router.
    5. Run sysupgrade -n openwrt-ath79-mikrotik-mikrotik_routerboard-493g-squashfs-sysupgrade.bin.
    6. Reboot the router, ensuring it boots from its internal flash.
  1. Finalize the router install:
  • Run passwd to set the root password.
  • Create the OpenVPN key material using:
    1. clean-all
    2. build-ca
    3. build-dh
    4. build-key-server example.com
    5. build-key client
  • Copy ca.cert, dh2048.pem, example.com.cert, and example.com.key to /etc/openvpn.
  • Copy ca.cert, dh2048.pem, client.cert, and client.key to the client’s /etc/openvpn.
  1. Configure OpenVPN on each client host.
  • Place the client’s certificate, the client’s private key, and the CA certificate in /etc/openvpn.
  • Option 1: Configuration using NetworkManager
    1. Create a new VPN connection using NetworkManager.
    2. Under AdvancedTLS Authentication:
    3. Set Subject Match to /CN=example.com.
    4. Select Verify peer (server) certificate usage signature and set to Server.
  • Option 2: Direct configuration of OpenVPN
    1. Copy /usr/share/doc/openvpn/contrib/pull-resolv-conf/client.up and client.down to /etc/openvpn.
    2. Set the scripts’ permissions with chmod +x client.up client.down.
    3. /etc/openvpn/example.conf (replace client.cert, client.key, and server.example.com):
dev tun
proto udp
verb 3
ca /etc/openvpn/ca.cert
cert /etc/openvpn/client.cert
key /etc/openvpn/client.key
dh /etc/openvpn/dh2048.pem
persist-tun
persist-key
client
remote-cert-tls server
remote server.example.com 1194
script-security 2
up /etc/openvpn/client.up
down /etc/openvpn/client.down
  4. `ln -s /lib/systemd/system/openvpn@.service /etc/systemd/system/openvpn@example.service`
  5. `systemctl start openvpn@example.service`

My research interests include free and open source software, system security, and network security.