Which firewall rule?

Identifying firewall rules which are hit by packets more often than not can help with performance at both ends of spectrum. From small scale CPE (Customer Premises Equipment), i.e. Routers to large scale servers which have even more traffic to handle, every packet and every byte counts.

Performance?

I’ve found myself reviewing performance a lot lately and the performance impact of getting the firewall rules right actually is worth looking into. When I first started researching firewall rules on some devices, I expected there to be some performance hit (by badly performing rules), but nothing like what I found. On small scale hardware where only 150 mbps was the high end throughput (using TUN/TAP in my particular case), I found individual rules could contribute as much as a 10-20 mbps drop.

Too many firewall rules

As a repeated task, I would be looking through pages and pages of iptables rules and it’s quite time consuming. So I decided to write a tool that would make that job a little easier. This tool would simply print an ordered list of the packets, bytes and rules in descending order so I could target the rules more easily. I thought I would do this in AWK since I’ve been looking for a good reason to get into it, and this was it!

An unAWKward solution

With this AWK script, I found it incredibly easy to extract, sort the content and print it out. The performance is reasonable too. An example of this running on a router looks like this:

# ./iptables-stats.awk
------------|------------|----------|----------------------------
 Packets    | Bytes      | Table    | Rule
------------|------------|----------|----------------------------
     626622 |  111195672 | raw      | -P OUTPUT ACCEPT
     626621 |  111195568 | filter   | -P OUTPUT ACCEPT
     370149 |   78974024 | filter   | -A INPUT -j INPUT_SPI
     370149 |   78974024 | filter   | -A INPUT -j INPUT_IPSEC
     339559 |   68940104 | raw      | -P PREROUTING ACCEPT
     221314 |   45146866 | filter   | -A INPUT_SPI -m state --state NEW -j ACCEPT
     209322 |   34687200 | raw      | -A OUTPUT -p udp -m udp --dport 1491 -j NOTRACK
     148815 |   33826336 | filter   | -A INPUT_SPI -m state --state RELATED,ESTABLISHED -j ACCEPT
      84611 |   14138055 | raw      | -A PREROUTING -p udp -m udp --sport 1491 -j DROP
      19830 |    3328332 | nat      | -A POSTROUTING -j POST_NAT
      19830 |    3328332 | nat      | -A POSTROUTING -j POST_DMZ
      19830 |    3328332 | nat      | -A POSTROUTING -j POST_PORT_MAP
      19830 |    3328332 | nat      | -A POSTROUTING -j POST_PORT_TRG
      19830 |    3328332 | nat      | -A POSTROUTING -j POST_SNAT
      19830 |    3328332 | nat      | -A POSTROUTING -j POST_IPSEC
      18250 |    1531932 | filter   | -A OUTPUT -o br+ -p icmp -j ACCEPT
      18249 |    3214832 | nat      | -A POSTROUTING -j POST_LOCAL
      17088 |    3079648 | nat      | -P OUTPUT ACCEPT
      15819 |    2988786 | nat      | -A POSTROUTING -j MASQUERADE
      14414 |    1095337 | nat      | -A PRE_LOCAL -j PRE_DNS_PROXY
      14414 |    1095337 | nat      | -A PREROUTING -j PRE_LOCAL
      14414 |    1095337 | nat      | -A PREROUTING -j PRE_PORT_MAP
      14414 |    1095337 | nat      | -A PREROUTING -j PRE_PORT_TRG
      14414 |    1095337 | nat      | -A PREROUTING -j PRE_BOOSTER_REDIRECT
      13135 |    1012028 | nat      | -A PREROUTING -j PRE_DMZ
      13135 |    1012028 | nat      | -A PREROUTING -j PRE_SNAT
      13135 |    1012028 | nat      | -A PREROUTING -j PRE_UPNP
      12133 |     935736 | nat      | -P PREROUTING ACCEPT
      11049 |     615219 | filter   | -A FORWARD -j FWD_LOCK
      11049 |     615219 | filter   | -A FORWARD -j FWD_SNAT
      11049 |     615219 | filter   | -A FORWARD -j FWD_TCPMSS
      11049 |     615219 | filter   | -A FORWARD -j FWD_GENERAL
      11049 |     615219 | filter   | -A FORWARD -j FWD_URL_FILTER
      11049 |     615219 | filter   | -A FORWARD -j FWD_BOOSTER_WHITE_LIST
      11049 |     615219 | filter   | -A FORWARD -j FWD_FON
      10883 |     603373 | filter   | -A FWD_LOCK -i br+ ! -o br+ -j FWD_LOCK_LAN
      10740 |     592713 | filter   | -A FWD_LOCK_LAN -m state --state RELATED,ESTABLISHED -j ACCEPT
       5797 |    1162161 | filter   | -A INPUT ! -i lo -j INPUT_MGNT
       5797 |    1162161 | filter   | -A INPUT ! -i lo -j INPUT_MCAST
       5797 |    1162161 | filter   | -A INPUT ! -i lo -j INPUT_DLDIAGNOSE
       5641 |    1153545 | filter   | -A INPUT ! -i lo -j INPUT_VOIP
       5641 |    1153545 | filter   | -A INPUT ! -i lo -j INPUT_FW
       4708 |    1038826 | filter   | -A INPUT_MGNT -i br+ -j INPUT_MGNT_LAN
       4546 |    1029970 | filter   | -A INPUT_FW -i br+ -p udp -j INPUT_DOS_LAN
       4546 |    1029970 | filter   | -A INPUT_DOS_LAN -p udp -m limit --limit 100/sec --limit-burst 100 -m state --state INVALID,NEW -j RETURN
       1581 |     113500 | nat      | -A POST_NAT -o ppp0 -j POST_NAT_WAN0
       1545 |     107537 | nat      | -P INPUT ACCEPT
       1438 |     102840 | nat      | -A POST_NAT_WAN0 -s 10.0.0.0/8 -o ppp0 -j MASQUERADE
       1279 |      83309 | nat      | -A PRE_DNS_PROXY -s 192.168.1.0/24 ! -d 192.168.1.1/32 -i br0 -p udp -m udp --dport 53 -j DNAT --to-destination 192.168.1.1:53
       1089 |     123335 | filter   | -A INPUT_MGNT_WAN -i ppp0 -j INPUT_MGNT_WAN0
       1089 |     123335 | filter   | -A INPUT_MGNT ! -i br+ -j INPUT_MGNT_WAN
        899 |     112643 | filter   | -A INPUT_FW -i ppp0 -p udp -j INPUT_DOS_WAN0
        833 |     191991 | filter   | -A INPUT_FW -i br+ -p udp -m addrtype --dst-type BROADCAST -j INPUT_FRAGGLE_LAN
        833 |     191991 | filter   | -A INPUT_FRAGGLE_LAN -m limit --limit 10/sec --limit-burst 20 -j RETURN
        166 |      11846 | filter   | -A FWD_LOCK_WAN0 -i ppp0 -o br+ -m state --state RELATED,ESTABLISHED -j ACCEPT
        166 |      11846 | filter   | -A FWD_LOCK -i ppp0 -j FWD_LOCK_WAN0
        160 |       9052 | filter   | -A INPUT_FW -i ppp0 -p icmp -j INPUT_DOS_WAN0
        143 |      10660 | nat      | -A POST_NAT_WAN0 -s 192.168.0.0/16 -o ppp0 -j MASQUERADE
        143 |      10660 | filter   | -A FWD_VPN -j FWD_VPN_TO_LAN
        143 |      10660 | filter   | -A FWD_SPI_WAN0 -i br+ -o ppp0 -m state --state NEW -j ACCEPT
        143 |      10660 | filter   | -A FWD_SPI -o ppp0 -j FWD_SPI_WAN0
        143 |      10660 | filter   | -A FWD_POLICY -i br+ -j FWD_POLICY_IN_LAN
        143 |      10660 | filter   | -A FORWARD -j FWD_SPI
        143 |      10660 | filter   | -A FORWARD -j FWD_FW
        143 |      10660 | filter   | -A FORWARD -j FWD_ALG
        143 |      10660 | filter   | -A FORWARD -j FWD_VPN
        143 |      10660 | filter   | -A FORWARD -j FWD_DMZ
        143 |      10660 | filter   | -A FORWARD -j FWD_UPNP
        143 |      10660 | filter   | -A FORWARD -j FWD_PORT_MAP
        143 |      10660 | filter   | -A FORWARD -j FWD_PORT_TRG
        143 |      10660 | filter   | -A FORWARD -j FWD_POLICY
        136 |       7376 | filter   | -A INPUT_MGNT_LAN -p tcp -m tcp --dport 23 -j ACCEPT
         30 |       1640 | filter   | -A INPUT_FW -i ppp0 -p tcp -j INPUT_DOS_WAN0
         26 |       1560 | filter   | -A FWD_TCPMSS -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
         17 |       1020 | nat      | -A PREROUTING -p tcp -m tcp --dport 80 -j PRE_REDIRECT
         17 |       1020 | nat      | -A PREROUTING -p tcp -m tcp --dport 80 -j PRE_WEB_PROXY
         15 |        804 | filter   | -A INPUT_MGNT_LAN -p tcp -m tcp --dport 80 -j ACCEPT
          7 |        500 | filter   | -A OUTPUT -p icmp -m state --state INVALID -j DROP
          5 |        372 | nat      | -A OUTPUT -o dummy0 -j OUTPUT_DMZ_WAN
          5 |        372 | nat      | -A OUTPUT -o dummy0 -j OUTPUT_PORT_TRG_WAN
          5 |        372 | nat      | -A OUTPUT -o dummy0 -j OUTPUT_PORT_MAP_WAN
          5 |        436 | filter   | -A INPUT_MGNT_LAN -p icmp -j ACCEPT

Where can I get it?

I’ve uploaded this to github for anyone else that might want a tool like this and I am likely to develop this further to allow more interesting ways of identifying what’s going on with your local firewall.

# git clone https://github.com/curlybeast/net-perf-tools.git