Firewall in EdgeRouter

Lars Jönsson 2021-03-07

Information about the applied firewall in EdgeRouter X.

Overview

The firewall is based on iptables in Linux. The EdgeRouter X has a framework around iptables that comes from Vyatta. The framework simplifies the usage of iptables, but of course also limits what can be done. Here is some info from the VyOS Platform Blog:

In 2011 Ubiquiti Networks launched their EdgeMax line of products. EdgeOS™ is the essential part of the product line and is a fork of Vyatta Core 6.3 that exclusively runs on Cavium backed hardware produced by Ubiquiti Networks (EdgeRouter Lite, PoE, Pro) Since then they migrated to Debian 7 and replaced quagga with proprietary ZebOS™

Iptables

Iptables consists of multiple chains, like PREROUTING, FORWARD etc. Each chain has multiple tables, like nat, filter etc. The chains are connected according to the following figure:

iptables

Packets that are just forwarded from one network interface to another, goes through the chains PREROUTING, FORWARD and POSTROUTING. Packets destined to any Linux process, passes PREROUTING and INPUT. Packets originating from a Linux process passes OUTPUT and POSTROUTING.

Iptables in EdgeRouter X

The Firewall/NAT settings in the EdgeRouter GUI affects the iptables. The four tabs Port Forwarding, Firewall Polices, NAT and Firewall/NAT Groups updates different parts of the chains and tables.

er-gui

The EdgeRouter add many chains that use used to simplify for the GUI to add its rules to iptables. The name of the chains include specific keywords. Most of them are self-explanatory, but some are not:

Each ruleset in the Firewall Polices tab will be added as its own chain in iptables. The rulset is connected to an interface with a specific direction. When the direction is in, an entry for that interface will be added to the VYATTA_FW_IN_HOOK chain, with the ruleset chain as target. Direction out will be added to the VYATTA_FW_OUT_HOOK chain and local to the VYATTA_FW_LOCAL_HOOK chain. The rulset can have multiple interfaces connected to it and then each interface will added as its own entry in one of the "hooks" depending on the direction.

iptables-special-rules

The port forwarding rules setup in the Port Forwarding tab, will end up in the UBNT_PFOR_DNAT_HOOK, UBNT_PFOR_DNAT_RULES, UBNT_PFOR_FW_HOOK and UBNT_PFOR_FW_RULES chains.

Adding source and destination NAT rules in the NAT tab will end up in some of the _SNAT_ and _DNAT_ chains.

Groups added in the Firewall/NAT Groups tab will become IP sets which are described in the IP set chapter.

Content of tables

PREROUTING chain

prerouting-chain

Raw table

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target                     prot opt in     out     source               destination
  35M   12G VYATTA_CT_PREROUTING_HOOK  all  --  any    any     anywhere             anywhere
  35M   12G NAT_CONNTRACK              all  --  any    any     anywhere             anywhere
    0     0 PFOR_CONNTRACK             all  --  any    any     anywhere             anywhere
  212 30735 FW_CONNTRACK               all  --  any    any     anywhere             anywhere
  175 21895 CT                         all  --  any    any     anywhere             anywhere             NOTRACK

Chain VYATTA_CT_PREROUTING_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination
  35M   12G RETURN     all  --  any    any     anywhere             anywhere

Chain NAT_CONNTRACK (2 references)
 pkts bytes target     prot opt in     out     source               destination
  38M   12G ACCEPT     all  --  any    any     anywhere             anywhere

Chain PFOR_CONNTRACK (2 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  any    any     anywhere             anywhere

Chain FW_CONNTRACK (2 references)
 pkts bytes target     prot opt in     out     source               destination
   59 15001 ACCEPT     all  --  any    any     anywhere             anywhere

Mangle table

Chain PREROUTING (policy ACCEPT 35M packets, 12G bytes)
 pkts bytes target             prot opt in     out     source               destination
  35M   12G VYATTA_FW_IN_HOOK  all  --  any    any     anywhere             anywhere

Chain VYATTA_FW_IN_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination

NAT table

Chain PREROUTING (policy ACCEPT 77406 packets, 14M bytes)
 pkts bytes target                     prot opt in     out     source               destination
2743K  458M MINIUPNPD                  all  --  any    any     anywhere             anywhere
2743K  458M UBNT_PFOR_DNAT_HOOK        all  --  any    any     anywhere             anywhere
2685K  455M VYATTA_PRE_DNAT_HOOK       all  --  any    any     anywhere             anywhere
2685K  455M UBNT_SUSPEND_DNAT_HOOK     all  --  any    any     anywhere             anywhere
2685K  455M VYATTA_DNAT                all  --  any    any     anywhere             anywhere

Chain MINIUPNPD (1 references)
 pkts bytes target     prot opt in     out     source               destination

Chain UBNT_PFOR_DNAT_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination

Chain VYATTA_PRE_DNAT_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination
2685K  455M RETURN     all  --  any    any     anywhere             anywhere

Chain UBNT_SUSPEND_DNAT_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination

Chain VYATTA_DNAT (1 references)
 pkts bytes target     prot opt in     out     source               destination

FORWARD chain

forward-chain

Mangle table

Chain FORWARD (policy ACCEPT 29M packets, 11G bytes)
 pkts bytes target     prot opt in     out     source               destination

Filter table

Chain FORWARD (policy ACCEPT 755K packets, 311M bytes)
 pkts bytes target              prot opt in     out     source               destination
  29M   11G UBNT_PFOR_FW_HOOK   all  --  any    any     anywhere             anywhere
  28M   11G VYATTA_FW_IN_HOOK   all  --  any    any     anywhere             anywhere
  28M   11G VYATTA_FW_OUT_HOOK  all  --  any    any     anywhere             anywhere

Chain UBNT_PFOR_FW_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination

Chain UBNT_PFOR_FW_RULES (1 references)
 pkts bytes target     prot opt in     out     source               destination

Chain VYATTA_FW_IN_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination

Chain VYATTA_FW_OUT_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination

POSTROUTING chain

postrouting-chain

Mangle table

Chain POSTROUTING (policy ACCEPT 34M packets, 12G bytes)
 pkts bytes target              prot opt in     out     source               destination
  34M   12G VYATTA_FW_OUT_HOOK  all  --  any    any     anywhere             anywhere

Chain VYATTA_FW_OUT_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination

NAT table

Chain POSTROUTING (policy ACCEPT 2481 packets, 146K bytes)
 pkts bytes target                     prot opt in     out     source               destination
1336K  183M UBNT_VPN_IPSEC_SNAT_HOOK   all  --  any    any     anywhere             anywhere
1336K  183M MINIUPNPD-POSTROUTING      all  --  any    any     anywhere             anywhere
1336K  183M UBNT_PFOR_SNAT_HOOK        all  --  any    any     anywhere             anywhere
1324K  182M VYATTA_PRE_SNAT_HOOK       all  --  any    any     anywhere             anywhere
1324K  182M VYATTA_SNAT                all  --  any    any     anywhere             anywhere

Chain UBNT_VPN_IPSEC_SNAT_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination

Chain MINIUPNPD-POSTROUTING (1 references)
 pkts bytes target     prot opt in     out     source               destination

Chain UBNT_PFOR_SNAT_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination

Chain VYATTA_PRE_SNAT_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination
1324K  182M RETURN     all  --  any    any     anywhere             anywhere

Chain VYATTA_SNAT (1 references)
 pkts bytes target      prot opt in    out     source               destination

The NAT Masquerade rule ends up in VYATTA_SNAT.

Chain VYATTA_SNAT (1 references)
 pkts bytes target      prot opt in    out     source               destination
1265K  178M MASQUERADE  all  --  any   eth0    anywhere             anywhere             /* NAT-5010 */

INPUT chain

input-chain

Mangle table

Chain INPUT (policy ACCEPT 5631K packets, 702M bytes)
 pkts bytes target     prot opt in     out     source               destination

NAT table

Chain INPUT (policy ACCEPT 19949 packets, 2464K bytes)
 pkts bytes target     prot opt in     out     source               destination

Filter table

Chain INPUT (policy ACCEPT 115K packets, 15M bytes)
 pkts bytes target                prot opt in     out     source               destination
5632K  702M VYATTA_FW_LOCAL_HOOK  all  --  any    any     anywhere             anywhere

Chain VYATTA_FW_LOCAL_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination

OUTPUT chain

output-chain

Raw table

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target                     prot opt in     out     source               destination
3105K  440M VYATTA_CT_OUTPUT_HOOK      all  --  any    any     anywhere             anywhere
3105K  440M NAT_CONNTRACK              all  --  any    any     anywhere             anywhere
    0     0 PFOR_CONNTRACK             all  --  any    any     anywhere             anywhere
    0     0 FW_CONNTRACK               all  --  any    any     anywhere             anywhere
    0     0 CT                         all  --  any    any     anywhere             anywhere             NOTRACK

Chain VYATTA_CT_OUTPUT_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination
3105K  440M RETURN     all  --  any    any     anywhere             anywhere

Chain NAT_CONNTRACK (2 references)
 pkts bytes target     prot opt in     out     source               destination
  38M   12G ACCEPT     all  --  any    any     anywhere             anywhere

Chain PFOR_CONNTRACK (2 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  any    any     anywhere             anywhere

Chain FW_CONNTRACK (2 references)
 pkts bytes target     prot opt in     out     source               destination
   59 15001 ACCEPT     all  --  any    any     anywhere             anywhere

Mangle table

Chain OUTPUT (policy ACCEPT 3115K packets, 441M bytes)
 pkts bytes target     prot opt in     out     source               destination

NAT table

Chain OUTPUT (policy ACCEPT 13398 packets, 940K bytes)
 pkts bytes target     prot opt in     out     source               destination

Filter table

Chain OUTPUT (policy ACCEPT 109K packets, 14M bytes)
 pkts bytes target     prot opt in     out     source               destination

Standard firewall rules

During initial configuration of the EdgeRouter X, the firewall is configured. The two rulesets WAN_IN and WAN_LOCAL are added.

er-standard

The rules prevents connections to be initiated from the WAN (Internet), but allows inbound traffic to connections initiated from the LAN and the Linux Services. The LAN has full access to the Linux Service. The VLANs in the figure can be ignored. They are used internally by the EdgeRouter to be able to separate subnets. In this case, eth0 is the WAN interface and the LAN subnet is available on interface eth1 through eth4.

NAT Masquerade will also be enabled, during initial configuration, to ensure that all packets sent to the WAN are masqueraded.

er-iptables-rules

When the rulsets are set up in EdgeRouter X, they will be automatically be added to the filter tables of FORWARD and INPUT chains. Enabling of NAT Masquerade will add rules to the nat table of the POSTROUTING chain.

FORWARD/filter

Every rulset the has direction in or out, will end up in the filter table of the FORWARD chain. The firewall ruleset WAN_IN is added to the VYATTA_FW_IN_HOOK chain. The rules protect the LAN.

Chain VYATTA_FW_IN_HOOK (1 references)
 pkts bytes target     prot opt in          out     source               destination
  13M 7076M WAN_IN     all  --  eth0        any     anywhere             anywhere

Chain WAN_IN (1 references)
 pkts bytes target     prot opt in   out    source      destination
  13M 7076M RETURN     all  --  any  any    anywhere    anywhere         /* WAN_IN-10 */ state RELATED,ESTABLISHED
    0     0 DROP       all  --  any  any    anywhere    anywhere         /* WAN_IN-20 */ state INVALID
    0     0 DROP       all  --  any  any    anywhere    anywhere         /* WAN_IN-10000 default-action drop */

INPUT/filter

The rulesets that have direction local, are added to the filter table of the INPUT chain. The firewall ruleset WAN_LOCAL is added to the VYATTA_FW_LOCAL_HOOK chain. The rules protect the Local Process.

Chain VYATTA_FW_LOCAL_HOOK (1 references)
 pkts bytes target       prot opt in         out     source               destination
 816K  111M WAN_LOCAL    all  --  eth0       any     anywhere             anywhere

Chain WAN_LOCAL (1 references)
 pkts bytes target     prot opt in     out     source        destination
 517K   89M RETURN     all  --  any    any     anywhere      anywhere       /* WAN_LOCAL-10 */ state RELATED,ESTABLISHED
 6906  523K DROP       all  --  any    any     anywhere      anywhere       /* WAN_LOCAL-20 */ state INVALID
 292K   22M DROP       all  --  any    any     anywhere      anywhere       /* WAN_LOCAL-10000 default-action drop */

POSTROUTING/nat

The NAT Masquerade rule is added to the VYATTA_SNAT chain. All packets sent on interface eth0 will be masqueraded.

Chain VYATTA_SNAT (1 references)
 pkts bytes target      prot opt in    out     source               destination
1265K  178M MASQUERADE  all  --  any   eth0    anywhere             anywhere             /* NAT-5010 */

IP set

The Linux command line tool ipset is used to set up, maintain and inspect so called IP sets in the Linux kernel. Depending on the type of the set, an IP set may store IP(v4/v6) addresses, (TCP/UDP) port numbers, IP and MAC address pairs, IP address and port number pairs, etc.

Iptables matches and targets referring to sets create references, which protect the given sets in the kernel. A set cannot be destroyed while there is a single reference pointing to it.

IP sets used by iptables

IP sets can be added in the EdgeRouter GUI. In addition, IP sets are generated internally and they named according to the following convention:

TypeProtocol_Interface

Type:      ADDR or NET depending if it a single address or a subnet
Protocol:  v4 for IPv4 adresses
Interface: Name of the interface, i.e. eth0 or switch0.3618

An example of an internally generated IP set:

name:  ADDRv4_eth0
value: Public IPv4 address of the EdgeRouter on the WAN/Internet

Manipulate and view tables

The Linux command iptables is used for manipulating the content of the tables to view the current content.

The content of each table in the chains can be viewed by using:

iptables -v -t <table> -L <chain>

  --verbose -v                  verbose mode
  --table   -t table            table to manipulate (default: `filter')
  --list    -L [chain [rulenum]]
                                List the rules in a chain or all chains

Another command for listing the iptables rules:

iptables -nvL |cut -f -9|column -t| sed 's/^Chain/\n&/g'|sed '/^Chain/ s/[ \t]\{1,\}/ /g'|sed '/^[0-9]/ s/[ \t]\{1,\}/ /10g'

To get the listing in XML format, use:

iptables-save | iptables-xml

Create a script dump-iptables with the following content and run it on the EdgeRouter:

#!/bin/bash

filename="iptables-`hostname`-`date +%Y%m%d-%H%M`.txt"

echo "================================================================================" > $filename
echo " $filename" >> $filename
echo "================================================================================" >> $filename
echo >> $filename
echo "--------------------------------------------------------------------------------" >> $filename
echo " filter" >> $filename
echo "--------------------------------------------------------------------------------" >> $filename
sudo iptables -vL -n -t filter >> $filename
echo >> $filename
echo "--------------------------------------------------------------------------------" >> $filename
echo " nat" >> $filename
echo "--------------------------------------------------------------------------------" >> $filename
sudo iptables -vL -n -t nat >> $filename
echo >> $filename
echo "--------------------------------------------------------------------------------" >> $filename
echo " mangle" >> $filename
echo "--------------------------------------------------------------------------------" >> $filename
sudo iptables -vL -n -t mangle >> $filename
echo >> $filename
echo "--------------------------------------------------------------------------------" >> $filename
echo " raw" >> $filename
echo "--------------------------------------------------------------------------------" >> $filename
sudo iptables -vL -n -t raw >> $filename