Iptables efficiency, order of execution
Sometimes questions pop up on various network lists about execution order of rules.
Such questions are usually dealt with per example, but I sometimes ponder about general guidelines, or try to logically derive my own.
For my own systems, I really don't have to care that much; it's a different story for customers. Alas, currently I do not administer a larger heavily loaded setup, so experiments are a bit tricky to verify.
Likewise, I'm interested in execution order for various types of firewalling, i.e., do we have a large number of clients but few lowtraffic servers, or high-volume servers and few clients..
Scheme for a general setup:
Define variables, including PATH and path to iptables/modprobe.. Load required modules
Dectivate ICMP and forwarding
Setup /proc stuff
Set default policies to DROP
Delete and flush chains + nat PRE/POSTROUTING
Define general logging rules
Define ICMP rules Define TCP rules Define UDP rules
Drop common unwanted (priv.ranges..), spoofed, portscans Activate ICMP
Activate implementation-specifics:
Prerouting/mangle for TOS etc.. Prerouting/DNAT from external to DMZ/internal segments Input to the box itself
Forward from external to internal segments Forward form internal segments to external Postrouting/SNAT from internal segments to external Outgoing rules (unless ALLOW any outgoing traffic)
Log weird packets not caught elsewhere (for investigation)
Activate forwarding
But where to place things like Taylor's counting rules? (resent thread "How to stop the flood?")
I don't know enough about the performance penalty of having maybe quite a number of such counting rules.
Counting should be very few mashineinstructions each, though.
Signature · 2 lines
Kind regards, Mogens Valentin
Quoted 4 lines · Mogens Valentin
Sometimes questions pop up on various network lists about execution order of rules.
Such questions are usually dealt with per example, but I sometimes ponder about general guidelines, or try to logically derive my own.
Gnerally I like to put the rule(s) that will match the highest percentage of the time towards the top followed by the next highest percent matched rules on down the list to the least likely to match at the botom. The idea behind this is to have the most common packets match rules at the top (start) of the list so they have to traverse as few rules as possible.
If you are going to have a LARGE block of IPs that you are going to match on, namely each IP in a class (C)
256 / 4
64 / 4
16 / 4
4 / 4
(Dough! Ctrl+Enter != Ctrl+End)
Quoted 4 lines · Mogens Valentin
Sometimes questions pop up on various network lists about execution order of rules.
Such questions are usually dealt with per example, but I sometimes ponder about general guidelines, or try to logically derive my own.
Generally I like to put the rule(s) that will match the highest percentage of the time at / towards the top of the list followed by the next highest percent matched rules on down the list to the less / least likely to match at the bottom. The idea behind this is to have the most common packets match rules at the top (start) of the list so they have to traverse as few rules as possible.
If you are going to have a LARGE block of IPs that you are going to match on, namely each IP in a class B I would divide the logic up in to multiple smaller segments in sub chains. Namely I would break the rules up such that there would be a MAXIMUM of 34 rules to process for the entire 65536 IP network. This may seem like a lot of work to just break the rules up to make it more efficient for matching, but keep in mind that each rule that you have to match against will take time to process. So when you are talking about needing to process 65536 different IPs that would be a LOT of rules where as you could get to the EXACT RULE you wanted out of 65536 rules in just 34 rules. I would call that really good efficiency. Conversely you could use the same methodology to match on just a class C or all the class Cs in a class B in a MAXIMUM of 16 rules to get down to the IP or class C networ k. Below is a (partial) hypothetical script: (There are more points below too.)
iptables -t filter -A FORWARD -j 16_0
# 16_0 192.168.0.0/16
iptables -t filter -A 16_0 -s 192.168.0.0/18 -j 18_0 iptables -t filter -A 16_0 -s 192.168.64.0/18 -j 18_64 iptables -t filter -A 16_0 -s 192.168.128.0/18 -j 18_128 iptables -t filter -A 16_0 -s 192.168.192.0/18 -j 18_192 # 18_0 192.168.0.0/18
iptables -t filter -A 18_0 -s 192.168.0.0/20 -j 20_0 iptables -t filter -A 18_0 -s 192.168.16.0/20 -j 20_16 iptables -t filter -A 18_0 -s 192.168.32.0/20 -j 20_32 iptables -t filter -A 18_0 -s 192.168.48.0/20 -j 20_48 ### <snip>
# 20_0 192.168.0.0/20
iptables -t filter -A 20_0 -s 192.168.0.0/22 -j 22_0 iptables -t filter -A 20_0 -s 192.168.4.0/22 -j 22_4 iptables -t filter -A 20_0 -s 192.168.8.0/22 -j 22_8 iptables -t filter -A 20_0 -s 192.168.12.0/22 -j 22_12 ### <snip>
# 22_0 192.168.0.0/22
iptables -t filter -A 22_0 -s 192.168.0.0/24 -j 24_0 iptables -t filter -A 22_0 -s 192.168.1.0/24 -j 24_1 iptables -t filter -A 22_0 -s 192.168.2.0/24 -j 24_2 iptables -t filter -A 22_0 -s 192.168.3.0/24 -j 24_3 ### <snip>
# 24_0 192.168.0.0/24
iptables -t filter -A 24_0 -s 192.168.0.0/26 -j 26_0 iptables -t filter -A 24_0 -s 192.168.0.64/26 -j 26_64 iptables -t filter -A 24_0 -s 192.168.0.128/26 -j 26_128 iptables -t filter -A 24_0 -s 192.168.0.192/26 -j 26_192 # 26_0 192.168.0.0/26
iptables -t filter -A 26_0 -s 192.168.0.0/28 -j 28_0 iptables -t filter -A 26_0 -s 192.168.0.16/28 -j 28_16 iptables -t filter -A 26_0 -s 192.168.0.32/28 -j 28_32 iptables -t filter -A 26_0 -s 192.168.0.48/28 -j 28_48 ### <snip>
# 28_0 192.168.0.0/28
iptables -t filter -A 28_0 -s 192.168.0.0/30 -j 30_0 iptables -t filter -A 28_0 -s 192.168.0.4/30 -j 30_4 iptables -t filter -A 28_0 -s 192.168.0.8/30 -j 30_8 iptables -t filter -A 28_0 -s 192.168.0.12/30 -j 30_12 ### <snip>
# 30_0 192.168.0.0/30
iptables -t filter -A 30_0 -s 192.168.0.0/32 -j 32_0 iptables -t filter -A 30_0 -s 192.168.0.1/32 -j 32_1 iptables -t filter -A 30_0 -s 192.168.0.2/32 -j 32_2 iptables -t filter -A 30_0 -s 192.168.0.3/32 -j 32_3 ### <snip>
# 32_0 192.168.0.0/32
# You would put any rules that were specific to 192.168.0.0 here.
# 32_1 192.168.0.1/32
# You would put any rules that were specific to 192.168.0.1 here.
# 32_1 192.168.0.2/32
# You would put any rules that were specific to 192.168.0.2 here.
# 32_1 192.168.0.3/32
# You would put any rules that were specific to 192.168.0.3 here.
You should probably start with fairly simple rules at the start of your firewall as they will process faster. Put your more complex match rules in as specific areas as possible so that as few packets need to traverse them as possible.
Below are some rules ideas that I generally use that are not specifically performance related but more just general good ideas in firewalls.
If you want to have rules that check and REJECT specific types of source IP addresses, namely bogons, create a chain that will do it for you. Do the same with your destination IP addresses. This way you could call this chain from any other chain and be sure that your source and / or destination IP addresses are valid.
I personally tend to think that client programs should talk out ephemeral ports and talk to privileged or ephemeral ports and that privileged ports should talk to ephemeral ports and never directly privileged ports. Translation low ports can talk to hi ports only. High ports can talk to low or high ports.
You should really rely on some sort of stateful packet matching, be it the basic state match extension or the conntrack match extension.
For your basic NAT firewall / router you really don't need any inbound ports, save possibly for SSH for remote management.
Decide if you will DROP or REJECT inbound (from the net) packets that you did not solicit and stick with this policy through out your firewall.
Grant. . . .