Order of firewall rules processing on hardware level / performance

After looking at documents *1 *2 *3 how RouterOS processes packets I’m still wondering from a performance perspective what the best way is to setup your firewall rules.

The main question I have is;

  • Are packets processed throught the firewall policies based on the ID’s or based on the chain (input/output/forward) and then (or not) the ID?

The reason i’m wondering about this is whether or not I should put the established rules on top or to put the block rules on top. In theorie when I think about it normally most traffic is based on establisched connetions, thus putting it on top. However, in case of a DDos you might want to re-think think this and putting a drop chain on top. Also from what I have seen *4 , wheter or not you would put a firewall rule of dropping mallformed packets on top.

The question as stated above remains wheter it’s based on ID or on chain.

Any thoughts on this or tips/ links on this toppic?

*1 http://wiki.mikrotik.com/wiki/Manual:Packet_Flow
*2 http://wiki.mikrotik.com/wiki/Manual:IP/Firewall/Filter
*3 http://wiki.mikrotik.com/wiki/Securing_New_RouterOs_Route
*4 https://youtu.be/7stWTeD9hw8?t=238

Packets flow through things in a pretty complicated way if you think of everything all at once (see the current packet flow diagram v6)…

http://wiki.mikrotik.com/wiki/Manual:Packet_Flow_v6

Anyhow, given this flow, you can see there are lots of different ways packets go through the mikrotik.

The main ones for basic use are filter forward and srcnat.

I have two main goals in my firewall chain designs (besides the desired effect):
1- minimum number of rules to check per packet.
2- rules are as simple and straightforward as possible.
2a. - use as few match criteria as possible. The more criteria, the more likely the rule won’t match / ignore packets in all situations.

Other things to keep in mind - checking 5 src IP addresses by using 5 rules with src-address is going to be much less efficient than using an address list. Those are designed for fast searches just like the routing table is.

Not all checks are created equal - a rule which looks at the protocol doesn’t have much to check - one binary number from the packet does or does not equal the binary number you specified. fast. regex search through the contents of the packet payload = slow.

The big concept for a lot of people: the input/output chains are for packets to/from the Mikrotik itself, regardless of address or interface. If you are on ether1 with 192.168.1.12, and you ping 192.168.2.1 which is the Mikrotik’s IP on ether2, the packet does NOT go through forward and then input - just directly to input.

Ok - for efficiency and the questions you asked about “which rule first?”

I put drop rules for src-address-list / dst-address-list = blacklist as the very first rule.
The very second rule is allow established,related connection states.
I decided that this is best because if I DO see a security threat taking place, and add the guilty IP to blacklist, then I don’t want him to get 5 more password guesses before sshd closes the socket. I want him gone now. If the blacklist comes after established, then existing links will stay functional. Ip address lookups are fast, even for a large list, so I decided to make this one extra check on every packet.

After these two rules, anything you specify is only going to get checked once per new connection. (a scan or syn flood would go nuts on these still, though, but that’s why there is a blacklist). Given that, you don’t need to put state=new in any rule. It’s impossible to get here w/o the state being new or invalid. If invalid bothers you, drop those before moving on.
I typically put interface-specific rules where possible - the policy is based on “things in this direction” regardless of the IP, it’s a quick check, and it keeps you from having to remember to go change everything from 192.168.88.x to 192.168.99.x when you decide to renumber for some reason or other.

Another thing to use interfaces to switch on is custom chains - if a packet comes in on interface GUEST, then jump to chain guest. one check if it’s not guest, X number of checks if it is. If you only have one GUEST rule, and you really value efficiency, then just keep the one rule in the main forward chain, but I find that in addition to being efficient, seperate chains are READABLE and EASIER TO TROUBLESHOOT.

So in short - if your rule chain is essentially: give the finger to bad guys, accept whatever you asked for, then check the rest for things you actually want to allow, throw away the rest - then this should be quite efficient.

Here is my entire firewall config for my home router:

/ip firewall address-list
add address=w.x.y.z list=Whitelist
add address=a.b.c.0/23 comment="Work" list=Whitelist
add address=d.e.f.0/23 comment="Customer" list=Whitelist
/ip firewall filter
add chain=input comment="Permit existing connections" connection-state=established,related
add chain=input comment="Allow all ICMP" protocol=icmp
add chain=input comment="Allow whitelisted sources" src-address-list=Whitelist
add action=drop chain=input comment="WAN - default deny" in-interface=ether6
/ip firewall nat
add action=src-nat chain=srcnat comment="Use correct src-ip when talking to DOCSIS modem." \
    dst-address=192.168.100.0/24 out-interface=ether6 to-addresses=192.168.100.2
add action=masquerade chain=srcnat out-interface=ether6 to-addresses=0.0.0.0

I didn’t even bother with a blacklist for my home router - if I’m in it and see something going on, I’ll just block it with a rule - but if I wanted rules that can ‘detect’ port scans or something, then I would need a blacklist.

As you see, I allow ICMP - hiding from ping scans isn’t really going to help at all.


Well, that’s my firewall 101 speech. I hope it’s been helpful.

I would change the ICMP rule to only allow echo request/reply. ICMP has other functions, and can be a vector for intrusions.

Sent from my LG-D850 using Tapatalk

You should also allow MTU exceeded messages, and UDP port unreachable.
At the very least put ICMP filters after the established/related rules - if you just throw out non-ping ICMP, then valuable control messages will get missed. The most important one is path mtu discovery.

I would say that ICMP redirect from other than the default GW would be the main type of ICMP to drop for security reasons.
(note that “ignore icmp redirects” is important enough to get a config option at the system level)

Thank you very much for this 101, it gave me some new insight of how to approach the setup.

I decided that this is best because if I DO see a security threat taking place, and add the guilty IP to blacklist, then I don’t want him to get 5 more password guesses before sshd closes the socket. I want him gone now. If the blacklist comes after established, then existing links will stay functional.

I did not look into the issue like that, as in that when a session is already established your intruder can stay active.

Currently I’m trying to implement it at home, having 3 upstream connections from which 2 have IPv6 aswell. The goal is to replace my juniper firewalls in a datacenter, but having not enough hands on/experience this has to wait for a bit.

/edit
Thinking about it, why would you add an intruder IP to a address-list instead of making a route to a blackhole for it? Excep that the routing table could grow, but that also applies to an adress-list. Dropping at routing level seams to be more efficient.

I don’t know about efficiency, but there’s definitely one other problem with that: You can’t dynamically add to the route rules.

In the firewall, you can detect N connection attempts (or connections with less than N bytes; indicative of failed login attempt) within a time period, and do something when a limit is exceeded. Instead of adding to an address list, you can add a routing mark, and then blackhole based on the mark, but you’re still going through the firewall rules before a block is done. By virtue of reaching the firewall, it seems to me that dropping the packet right there should be more efficient than blocking it at a separate stage. I haven’t made any benchmarks to confirm which is more efficient though.

Not all hacks require two-way communication.
Blackhole routing just stops you from being able to send a packet to the destination. This is fine for blocking connectivity for things like password brute force attempts, web application vulnerabilities, and cases where your PC is unfortunately participating in a bot-net attack on some IP. (you knew you shuoldn’t have opened that email attachment!)

However, UDP doesn’t require two-way communications to do its job. Suppose an attacker knows your private snmp community and sends a spoofed-source packet (from a trusted source) with the correct community, and commands your router to upload its configuration to a TFTP server on their network. (not the source of the SNMP command)
Even if the source address of the SNMP is black-holed, then the packets are still going to reach your router, and your router will still obey the commands and will still send the config to the yet-un-black-holed TFTP address…

“All your base are belong to us.”

If you blacklist the source then the packet will be ignored by the firewall rule.
DNS cache poisoning attacks work in a similar way - the attacker doesn’t get any reply from the server, but attacker can still inject bogus RR’s into a vulnerable server…

So the moral of the story: packet blocking lists are better than black hole routes for security. Black hole routes are useful for mitigating DDoS floods.

A bit off topic, but anyway. I have been running a few days on the Mikrotik. All works well but just reverted as my VPN would not establish with a Juniper Screenos " negotiation failed due to time up".

Still looking into that to get it fixed.
The CPU levels out at 25% load.