Firewall filter rules - performance impact

Hi,

a question regarding impact on router’s resources/performance while extensively using actions jump and return

Example “If destination matches address list go to allowed actions”

add action=jump chain=forward dst-address-list=pi in-interface-list=!WAN jump-target=srvr out-interface-list=!WAN comment=">>> SRVR" 
add action=accept chain=srvr comment="--- dns tcp" dst-port=53,5053 in-interface-list=LAN protocol=tcp
add action=accept chain=srvr comment="--- dns udp" dst-port=53,5053 in-interface-list=LAN protocol=udp
add action=accept chain=srvr comment="--- mqtt" dst-port=1883,8883 in-interface-list=LAN protocol=tcp src-address-list=MQTT-allowed src-port=""
add action=accept chain=srvr comment="--- ssh" dst-port=22 in-interface-list=trusted protocol=tcp src-address-list=admin
add action=accept chain=srvr comment="--- syslog udp" dst-port=514 in-interface-list=LAN protocol=udp src-address-list=SYSLOG-allowed
add action=accept chain=srvr comment="--- syslog tcp" dst-port=514 in-interface-list=LAN protocol=tcp src-address-list=SYSLOG-allowed
add action=accept chain=srvr comment="--- smb" dst-port=445 in-interface-list=trusted protocol=tcp src-address-list=personalDevices
add action=return chain=srvr in-interface-list=!WAN out-interface-list=!WAN comment="<<< forward" 
add action=drop chain=srvr comment="--- DROPALL ---"

Or even nested deeper:

#condition 1
add action=jump chain=forward dst-address-list=pi in-interface-list=!WAN jump-target=srvr out-interface-list=!WAN comment=">>> SRVR" 

#condition 1.1
add action=jump chain=srvr jump-target=server1 dst-port=53,5053 in-interface-list=interfaceList_1 comment=">>> SERVER1" 
#condition 1.2
add action=jump chain=srvr jump-target=server2 dst-port=53,5053 in-interface-list=interfaceList_1 comment=">>> SERVER2" 

add action=accept chain-server1 comment="DNS for some interfaces accepted on server 1" # under conditions
add action=accept chain-server1 comment="another accepted something" # under different conditions
add action=return chain=server1 comment="<<< SRVR"  
add action=accept chain=server2 comment="something accepted on server 2" # under conditions
add action=accept chain=server2 comment="another accepted something" # under different conditions
add action=return chain=server2 comment="<<< SRVR"  
add action=accept chain=srvr  #common rules for a list... 
add action=return chain=srvr in-interface-list=!WAN out-interface-list=!WAN comment="<<< forward"  
add action=drop chain=srvr comment="--- DROPALL ---"

Going further,
under performance test results on example Mikrotik device page there is a specified configuration “25 ip filter rules”.

How to read this?

Let’s say I have 1000 forward rules on positions 2-999

add action=accept chain=forward src-address=10.0.0.10 in-interface-list=trusted dst-address=10.0.20.31 out-interface-list=!WAN 
add action=accept chain=forward src-address=10.0.0.10 in-interface-list=trusted dst-address=10.0.20.34 out-interface-list=!WAN
add action=accept chain=forward src-address=10.0.0.10 in-interface-list=trusted dst-address=10.0.111.123 out-interface-list=!WAN
add action=accept chain=forward src-address=10.0.0.10 in-interface-list=trusted dst-address=10.0.123.145 out-interface-list=!WAN 
# and so on...

Traffic from 10.0.0.10

  • to 10.0.20.31 will be affected by 1 rule?
  • 10.0.123.145 will be affected by 4 rules?

<=> thus performance is only affected by “number of filters that traffic was tested against before matched”?
<=> thus any amount of filters that are virtually unreachable for traffic (matched before) will not affect performance (as long as there is enough memory they will be occupying while rotting :wink: ) (?)

  • question from original post - how exhausting is jumping without reason?

In many cases its the rules that are inefficient, for example just make a firewall address list of all those individual addresses and then its one forward chain rule.

Yup, got your rule of thumb “when to use address lists” hanging framed above my imaginary desk :wink:

I’ve used somewhat unfortunate example, but it’s just to visualise the point - pinpointing the actual moment in filter’s lifespan when it affects performance.

Does having a filter listed already affect performance, or only the moment when traffic hits it to be tested/matched against?
And what about passthrough filters?

Im not into the theory LOL, I only deal with issues… If you have any doubts buy the 2116 it has plenty of ooomph… :wink:

Rules are matched in order. Each matching costs CPU resources (some are probably cheaper than others, perhaps matching against address list is more expensive than against a single address, but cheaper than multiple matching against single address). Which is the reason to put rules, which match most packets, higher on the list (keeping the order so that security is not compromised).
Creating separate chains can help to reduce average number of rules tried for a packet so this can actually speed up firewall. But matching against “jump” rule costs as well, so one has to make some compromises.

Regarding those “25 filter rules”: only knows exact setup used for tests. It could be that there are exactly 25 filter rules, none matching (so only the matching performance affects test results). But anyway, I’d say that you can assume “average number of rules matched against” and actual packet processing delay will depend on number of matchings performed before a rule is executed.

I’m on the other hand all about theory in this case - once I’m happy with understanding basics I promise to F something up and bring it to you for help :wink:

Makes sense - thank you!

So if matching is the actual “cost center”, then having the “unfortunate example” in mind:

add action=accept chain=forward src-address=10.0.0.10 in-interface-list=trusted dst-address=10.0.20.31 out-interface-list=!WAN 
add action=accept chain=forward src-address=10.0.0.10 in-interface-list=trusted dst-address=10.0.20.34 out-interface-list=!WAN
add action=accept chain=forward src-address=10.0.0.10 in-interface-list=trusted dst-address=10.0.111.123 out-interface-list=!WAN
add action=accept chain=forward src-address=10.0.0.10 in-interface-list=trusted dst-address=10.0.123.145 out-interface-list=!WAN 
# and so on...

it would actually help to first match src-address=10.0.0.10 and jump to custom “destination chain” (added ports for @anav not to say to go for address-list :wink: )

add action=jump to-target=destinations_xyz src-address=10.0.0.10 in-interface-list=trusted out-interface-list=!WAN
add action=accept chain=destinations_xyz dst-port=123 dst-address=10.0.20.31 
add action=accept chain=destinations_xyz dst-port=1234 dst-address=10.0.20.34
add action=accept chain=destinations_xyz dst-port=22 dst-address=10.0.111.123 
add action=accept chain=destinations_xyz dst-port=9876 dst-address=10.0.123.145 
# and so on...
# drop all or return to forward

And passthrough would be as resource hungry as any filter as long as it needs matching…
so summarising:

Not number of filters themselves would account for resource hunger, but their “weight” - amount of parameters to check inside each

As I understand it, that is a very good summary.

Personally I use a number of jumps to some other chain. For example I have four Raspberry Pis that each can be accessed via VNC (with various security). From the Internet each is accessed via a different port. So I have a rule that matches the four ports and jumps to the “VNC” chain where all the other assorted security takes place. So for traffic that is NOT going to VNC on one of the RasPis, the ports do not match so those packets do not match the rule and therefore do not make the jump and skip all the other security rules that apply only to VNC packets.