Iptables – When using iptables firewall rules, why assert NEW state on all allowed ports

iptables

I often see iptables configured to allow all pakets to RELATED connections, and the specific service ports to NEW connections.

What is the reason for stating NEW? If an connection is not NEW, it is RELATED I guess, so the specific port rule will execute neither. So why to explicitely define the service ports with NEW and not just protocoll and port number?

Best Answer

The rules in a netfilter firewall (iptables) are checked sequentially and the fate of the packet (ACCEPT, DROP, REJECT etc.) is determined on a first-match basis.

By making the firewall statefull and the first rule the typical -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT the vast majority of legitimate traffic to your server is accepted after passing only that single rule. That traffic doesn't need to traverse any other rules.

Depending the size of your rule base that can mean a significant difference in your firewall performance.

The only traffic that the firewall now needs to validate are the explicitly new connections.

I.e. compare a firewall for a public webserver with access for a handful webmasters from their workstations:

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp -m multiport --dports 80,443 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -m iprange --src-range 10.9.8.7-10.9.8.10 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited

Roughly 99% of legitimate packets will belong to established connections, only hitting the first rule. Of the packets not matching that rule, the majority should be new connections to your website, the multiport module can grant access to either HTTP or HTTPS in a single rule. The webmasters log in from a number of workstations with fixed addresses using ssh and sftp and everything else is rejected.

A firewall where the rules are ordered logically by the TCP port:

-A INPUT -p tcp  -m tcp --dport 22  --source 10.9.8.7 -j ACCEPT
-A INPUT -p tcp  -m tcp --dport 22  --source 10.9.8.8 -j ACCEPT
-A INPUT -p tcp  -m tcp --dport 22  --source 10.9.8.9 -j ACCEPT
-A INPUT -p tcp  -m tcp --dport 22  --source 10.9.8.10 -j ACCEPT
-A INPUT -p tcp  -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp  -m tcp --dport 443 -j ACCEPT

Here each and every packet to your HTTP webserver would need to be checked against 5 rules before access is granted. And with more services running on a server that can easily become 50 rules or much more when you for instance would use fail2ban or similar products.