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`