Configure routes

nftables (netfilter) is used to configure the firewall and routes.

Create service definition

Run this on the Router VM
cat <<'EOF' > /etc/systemd/system/nifty-filter.service
[Unit]
Description=Custom router script
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/router.sh
RemainAfterExit=yes
PrivateDevices=true
ProtectSystem=full
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload

Customize your router script

nifty-filter lets you configure your whole router in one shell script, which is written to /usr/local/sbin/router.sh:

Run this on the Router VM
cat <<'EOF' > /usr/local/sbin/router.sh
#!/bin/bash
set -e

## Set logical interface names (physical and virtual):
export PUBLIC_INTERFACES=wan
## You can define arbitrary private interfaces:
## mgmt and lan are standard, but you can add more:
export PRIVATE_INTERFACES=mgmt,lan
#export PRIVATE_INTERFACES=mgmt,lan,work,apps,iot
## Ensure you duplicate all *_LAN variables for each new interface _NAME
## (commented examples for *_WORK, *_APPS, *_IOT will follow)

## Set network interface names (INTERFACE_LOGICAL=actual_interface_name):
export INTERFACE_WAN=wan
export INTERFACE_MGMT=mgmt
export INTERFACE_LAN=lan

## Configure subnets per interface:
export SUBNET_LAN=192.168.10.1/24

## Allow ping etc. from private subnets only:
export ICMP_ACCEPT_WAN=
export ICMP_ACCEPT_MGMT=echo-request,echo-reply,destination-unreachable,time-exceeded
export ICMP_ACCEPT_LAN=echo-request,echo-reply,destination-unreachable,time-exceeded

## Allow different access to TCP ports on the router depending on interface:
export TCP_ACCEPT_WAN=
export TCP_ACCEPT_MGMT=22,80,443
export TCP_ACCEPT_LAN=22,53,80,443

## Allow different access to UDP ports on the router depending on interface:
export UDP_ACCEPT_WAN=
export UDP_ACCEPT_MGMT=
export UDP_ACCEPT_LAN=53,67,68

## Forward connections from private interfaces:
## IN_PORT:FORWARD_ADDRESS:FORWARD_PORT,...
export TCP_FORWARD_MGMT=
export UDP_FORWARD_MGMT=
export TCP_FORWARD_LAN=
export UDP_FORWARD_LAN=

## Forward connections from WAN:
## IN_PORT:FORWARD_ADDRESS:FORWARD_PORT,...
export TCP_FORWARD_WAN=
export UDP_FORWARD_WAN=

## Enable IP forwarding
sysctl -w net.ipv4.ip_forward=1

echo "## Applying router config:"
nifty-filter nftables --validate
nifty-filter nftables | nft -f -
nft list ruleset
echo "## Applied router configuration successfully!"
EOF
chmod +x /usr/local/sbin/router.sh
ln -sf /usr/local/sbin/router.sh ~/router.sh

nifty-filter expects the configuration to be passed via environment variables, which this script sets up:

Name Description
INTERFACE_MGMT The name of the management network (MGMT) interface.
INTERFACE_LAN The name of the local area network (LAN) interface.
INTERFACE_WAN The name of the wide area network (WAN) interface.
SUBNET_LAN The CIDR notation subnet mask for the LAN clients.
ICMP_ACCEPT_LAN The list of allowed ICMP request types to accept from the LAN.
ICMP_ACCEPT_WAN The list of allowed ICMP request types to accept from the WAN.
TCP_ACCEPT_LAN The list of TCP ports on the router to allow access from the LAN clients.
TCP_ACCEPT_WAN The list of TCP ports on the router to allow access from the WAN clients.
UDP_ACCEPT_LAN The list of UDP ports on the router to allow access from the LAN clients.
UDP_ACCEPT_WAN The list of UDP ports on the router to allow access from the WAN clients.
TCP_FORWARD_LAN The list of TCP forwarding routes to allow from the LAN.
TCP_FORWARD_WAN The list of TCP forwarding routes to allow from the WAN.
UDP_FORWARD_LAN The list of UDP forwarding routes to allow from the LAN.
UDP_FORWARD_WAN The list of UDP forwarding routes to allow from the WAN.

Enable the router service

Run this on the Router VM
systemctl enable nifty-filter
systemctl restart nifty-filter

Test LAN clients with static IP address

Test IP Masquerade (optional)

At this early stage without even DHCP or DNS setup yet, you still may want to verify that IP masquerade is already working. You can set up another machine connected to the physical LAN interface of the VM and configure that machine with a static IP address of 192.168.10.2 and gateway of 192.168.10.1. You should now be able to ping any IP address on the internet (e.g. ping 1.1.1.1) through the gateway router. These steps will be covered in more detail later in the chapter named Configure LAN clients after having finished the router config.