Review: Is this firewall filter order good?

Due to the fact that I have many different devices I started segmenting my network into distinct separate networks.

Now after several issues of orders I think I’ve build an order I can live with but which doesn’t necessary mean that’s also somewhat secure or even good and would therefore ask for improvement on the filter rules.

For clarification: I have 4 networks: TrustedDevices, Smarthome, MediaZone and Guests. Guests is not part of the firewall rules because my wireless AP has client isolation (is this correct, or should I still put ip filtering for that network because I am missing some OSI Layer with that?). My WAN is connected to ether1 (pinging my router from WAN should not be possible)

/ip firewall filter
add action=accept chain=input comment="defconf: accept established,related" connection-state=established,related
add action=drop chain=input comment="defconf: drop all from WAN" in-interface=ether1 log-prefix="DROP WAN"
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" connection-state=established,related
add action=accept chain=forward comment="defconf: accept established,related" connection-state=established,related
add action=accept chain=input comment="Accept ICMP to router from all devices. Even WAN (if not below 'drop all from WAN')" protocol=icmp
add action=drop chain=forward comment="Prevent Media reaching smarthome" in-interface=MediaZone out-interface=Smarthome
add action=drop chain=forward comment="Prevent Smarthome reaching Trusted" in-interface=Smarthome out-interface=TrustedDevices
add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid
add action=drop chain=forward comment="defconf:  drop all from WAN not DSTNATed" connection-nat-state=!dstnat connection-state=new in-interface=ether1

Beside the network isolation I also reordered the other rules so that the most valid one come first without breaking the logic of the filtering.

Any advise on that setup would be great.
I am aware that it would be safer to drop everything first and then configure the accept rules but for some reason I feel not yet ready to lock myself out more often than I already did :confused:

Rules are processed in order and when some matches, further ones are skipped (except when there’s action=log, or in mangle with passthrough=yes). You probably have at least some idea about that.

So when you look at these, you see that the second one is useless, because it can’t accept anything from WAN (it was already dropped by first rule) and specifically accepting icmp from other interfaces is not needed, because it would be accepted by chain’s default action anyway:

add action=drop chain=input comment="defconf: drop all from WAN" in-interface=ether1 log-prefix="DROP WAN"
add action=accept chain=input comment="Accept ICMP to router from all devices. Even WAN (if not below 'drop all from WAN')" protocol=icmp
<no other chain=input rule follows, default action for everything else is allow>

Regarding chain=forward, if you read your rules from top, you’ll see that traffic from your networks (if they each have one interface):

  • TrustedDevices - can go everywhere
  • Smarthome - can go everywhere except TrustedDevices
  • MediaZone - can go everywhere except Smarthome
  • Guests - can go everywhere, at least according to firewall (I’m not sure what exactly you configured on AP, so just try it to be sure, connect device to Guests and try to access other networks)
  • WAN - (incoming connections) can’t go anywhere, unless you forward port to somewhere
  • <any other new interface, e.g. VPN> - can go everywhere

If you would be interested in blocking everything by default and only add exceptions for allowed stuff, but you’re a little affraid (it’s actually good thinking :slight_smile:), there’s an easy fix for that. Instead of blocking stuff unconditionally right away, log it first and watch what happens:

/ip firewall filter
add action=log chain=forward log-prefix=DROP

If you see something that should not be dropped, add accept rule for it before. If you see something that should be dropped and it’s polluting your logs, add a temporary drop rule for it before the last logging rule to get it out of the way. When you’re happy with the result, remove temporary block rules (if you added any) and logging one and add the real thing:

/ip firewall filter
add chain=forward action=drop

Or if you want it to make it easier to find mistakes, I use reject and if something doesn’t work, the reason will quickly show in ping or traceroute:

/ip firewall filter
add action=reject chain=forward reject-with=icmp-admin-prohibited

If you’re connecting to router from directly connected network, you don’t have to be affraid of chain=forward, that can’t lock you out. But chain=input can, be careful with that one.

Sob, thank you for your detailed explanation!
I think the ICMP was a defconf rule to be able to ping router from WAN if I remember right. Since I really don’t want that, I’ve moved it down.

I could actually change it to forward and disable it. So when I troubleshoot I could enable ICMP on everything to be able to diagnose issues. Would that make sense? Would probably also make sense to log it then.

I will also consider your hints on default dropping but logging first approach :slight_smile:

I pointed out icmp rule just to make sure that you undestand the processing order.

I myself keep icmp enabled, because it makes my life easier. It allows me to easily check if the router is alive, anytime and from anywhere. Some people like to disable icmp, because it makes them feel more secure, but IMHO the bad guys don’t care and scan addresses not responding to pings anyway. I’m lazy, so I usually enable all icmp, but you can enable only selected types. I’ve seen some list somowhere what’s important, don’t remember where, but I’m sure you’ll find something if you want.

How do you test your drop rules if ICMP is always enabled? I used that as a measure of verification.

There are other things, any service listening on tcp port (there’s always some) can be quicky tested with nmap, or even with simple “telnet ” and you see immediatelly if it connects or not.