Rocking iptables like a DJ

Setting up a WAN device

Now here’s an example using dynamic configuration when the router sets up a connection to the outer world by using a WAN link on eth2 interface may it be be either a cable modem or a PPP connection. Let’s assume a cable modem which gets it’s public IP by DHCP negotiation and only the subnet on eth0 should be able to connect to the internet. This time we use event hooks from /etc/network/interfaces file eg:

iface eth2 inet dhcp
  pre-up ipturntables.sh -4 ALLOW_DHCP_CLIENT eth2
  post-up ipturntables.sh -4 \
    FORWARD_SUBNET_PROTECTIVE 192.168.1.0/24 eth2 \
    POSTROUTING_MASQUERADE 192.168.1.0/24 eth2

ALLOW_DHCP_CLIENT

First we need to allow DHCP traffic but instead of allowing a whole subnet or IP we just allow DHCP packets in the pre-up event of eth2 interface to be able to get an public IP from the provider before eth2 is brought up.

Chain USER-IN (1 references)
 pkts bytes target     prot opt in     out  source          destination         
  ...   ... ACCEPT     all  --  eth0   *    192.168.1.0/24  0.0.0.0/0            /* ALLOW_SUBNETS_0x50e549399da8 */
  ...   ... ACCEPT     all  --  eth0   *    0.0.0.0/0       0.0.0.0/0            PKTTYPE = broadcast /* ALLOW_SUBNETS_0x50e549199da8 (broadcast) */
  ...   ... ACCEPT     all  --  eth0   *    0.0.0.0/0       169.254.0.0/16       /* ALLOW_LINK_LOCAL on 0x50e549199da8 */
  ...   ... ACCEPT     udp  --  eth0   *    0.0.0.0/0       224.0.0.251          udp dpt:5353 /* ALLOW_SERVICE_DISCOVERY on 0x50e549199da8 (multicast mDNS) */
  ...   ... ACCEPT     udp  --  eth0   *    0.0.0.0/0       239.255.255.250      udp dpt:1900 /* ALLOW_SERVICE_DISCOVERY on 0x50e549199da8 (multicast UPnP) */
  ...   ... ACCEPT     udp  --  eth2   *    0.0.0.0         255.255.255.255      udp spt:68 dpt:67 /* ALLOW_DHCP_CLIENT_on_0x000e0c6e43fc */
  ...   ... ACCEPT     udp  --  eth2   *    0.0.0.0/0       0.0.0.0/0            udp spt:67 dpt:68 /* ALLOW_DHCP_CLIENT_on_0x000e0c6e43fc (dhcp/bootp) */

On the USER-IN chain we have two new rules below which allow DHCP packets on the eth2 interface. For allowing the subnet (192.168.1.0/16) on eth0 interface access to the WAN interface we need to forward packets from there but using FORWARD_SUBNET without any protective measure would be dangerous so we need a forward which filters the critical stuff like malicous packets from the up stream.

FORWARD_SUBNET_PROTECTIVE

For that ipturntables.sh offers the FORWARD_SUBNET_PROTECTIVE call which protects the subnet in the same way the router protects itself on the INPUT and OUTPUT chains but since this needs some complex rule logic which would clutter the USER-IN chain therefore ipturntables.sh rather allocates two new chains to be able to have custom rules when setup differs for each subnet otherwise allowing eg. a specific port would allow it for any subnet if these would use the same static chains which is not always desired. Here’s an example:

Chain A274D8BD-IN (1 references)
 pkts bytes target      prot opt in     out  source      destination
  ...   ... ICMP        icmp --  *      *    0.0.0.0/0   0.0.0.0/0
  ...   ... BLOCK       all  --  *      *    0.0.0.0/0   0.0.0.0/0    state INVALID
  ...   ... ANTI-FLOOD  tcp  --  *      *    0.0.0.0/0   0.0.0.0/0    tcp flags:0x17/0x02
  ...   ... ANTI-FLOOD  tcp  --  *      *    0.0.0.0/0   0.0.0.0/0    tcp flags:0x17/0x04
  ...   ... ACCEPT      all  --  *      *    0.0.0.0/0   0.0.0.0/0    state RELATED,ESTABLISHED

Chain A274D8BD-OUT (1 references)
 pkts bytes target     prot opt in     out   source      destination
  ...   ... ACCEPT     all  --  *      *     0.0.0.0/0   0.0.0.0/0    state RELATED,ESTABLISHED
  ...   ... ACCEPT     all  --  *      *     0.0.0.0/0   0.0.0.0/0    state NEW
  ...   ... ACCEPT     tcp  --  *      *     0.0.0.0/0   0.0.0.0/0    tcp multiport dports 80,443

One chain for forwarding inbound and one for outbound traffic. These are called in the FORWARD chain:

Chain FORWARD (policy DROP 19 packets, 2100 bytes)
 pkts bytes target        prot opt in     out     source          destination         
  ...   ... A274D8BD-OUT  all  --  eth0   eth2    192.168.1.0/24  0.0.0.0/0         /* FORWARD_SUBNET_PROTECTIVE_eth0_C0A8010018_eth2 */
  ...   ... A274D8BD-IN   all  --  eth2   eth0    0.0.0.0/0       192.168.1.0/24    /* FORWARD_SUBNET_PROTECTIVE_eth0_C0A8010018_eth2 */
  ...   ... LOG           all  --  *      *       0.0.0.0/0       0.0.0.0/0         limit: avg 8/min burst 16 LOG flags 0 level 4 prefix "[FW4-DROP] "

Notice that the subnet on eth1 (which is chained behind the subnet on eth0) would still be blocked by the firewall when packets are sent to leave through the WAN interface as that would need another explicit forwarding rule to be allowed.

ipturntables_forward_subnet_protective

Figure E: A WAN connection forwarding a subnet.

POSTROUTING_MASQUERADE

So since now we have a connection to the outer world and an appropriate forward rule for the subnet on eth0 we just need to masquerade our IPs (192.168.1.0/24) to appear with the IP of the WAN interface for a working router setup at least for IPv4 protocols. Now let’s have closer look at the last call of the post-up event hook of the WAN interface:

iface eth2 inet dhcp
  ...
  post-up ipturntables.sh -4 \
    FORWARD_SUBNET_PROTECTIVE 192.168.1.0/24 eth2 \
    POSTROUTING_MASQUERADE 192.168.1.0/24 eth2

Where exactly that is done with the POSTROUTING_MASQUERADE call. It rewrites the source address of any host IP of the subnet from eth0 when leaving through the WAN interface on the eth2 interface. This differs from IPv6 setups where NAT is avoided by design but wether source IP addresses of a subnet are NAT‘ed or not the FORWARD_SUBNET_PROTECTIVE call can be used in the same way for IPv6 subnets even without NAT as the nature of a stateful firewall of allowing new outbound traffic but only allowing related or established traffic in, protects the hosts behind the router the same way regardless of the source IP address being mangled or not!