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`