Minimalistic zero-trust firewall rules

More than obviously I had it in for the user bumoloo I replied to, the reply and the reference are clear, it wasn't for you.

Nice!
I want suggest to allow port forwarding:
add action=accept chain=forward comment="Allow NAT Port Forwarding" connection-state=new connection-nat-state=dstnat in-interface-list=WAN

was not better to use connection-state=new in
add action=accept chain=forward comment="Forward: accept LAN traffic" connection-state=new in-interface-list=LAN ?

After the two rules:

The only possible connection-state left are new and untracked. But OP has decided to never use RAW rules (that was OP's reason to omit untracked from the "established,related" rule). So, past those two rules, the only possible state left is new and it's redundant to add the connection-state=new to the rest of the rules.

That was also the reason why in the most up-to-date defconf rules, connection-state=new was removed from "defconf: drop all from WAN not DSTNATed".

The rule was bundled, in that it served dual purposes but was incomplete as it didnt limit outgoing LAN traffic. Much better to limit L3 LAN traffic explicitly to internet, break out the port forwarding rule BUT ONLY if required, otherwise remove it. Add any other rules needed like admin to all vlans, vlan to a shared printer etc.

To add what already others commented:

  1. It's important to keep in mind that rules are evaluated in order from top to bottom. Which explains part of the ordering. In particular case of connection-state=invalid, if this rule was not among the first ones, some other rules might allow such packet to pass.
  2. And as to why "only the second": performance reasons. If there isn't fasttrack active, then each packet will pass through firewall filter rules until it triggers action (whichever that might be). In realistically optimistic case, vast majority of packets passing firewall will be parts of established connections (or related to them) so a rule allowing such packets will match most of packets. Having such rule the first makes processing of most packets the least.
    If the "invalid" rule was the first one, then it would be evaluated for each and every packet ... also for tge "established,related" packets. And we know tgat connection state is only one, so it can't be both invalid and established (or related), making pkacing invalid rule as second after established one a completely safe setup.

If one wanted to place the "invalid" rule at the end (or even omit it because one woukd have explicit drop all rule as the last one), then one would have to set "connection-state=new" (or and other connectiin-state if appropriate) on each and every filter rule. Omitting this setting would make firewall unsafe immediately as it would open hole to pass invalid packets.

Interesting… thank you!
In my case I have forward rules in firewall Filter to allow VLANs to WAN and VLAN X to VLAN Y, all of them use connection-state=new , time ago connection-state=new was suggested in Using RouterOS to VLAN your network to save CPU cycles, but this was also discussed in a post by @sindy the magic of connection-state=new.

If I’m not mistaken, when action=no-track is not used in Raw, connection-state=new is useless because connection-state=established,related connections are already allowed by the first rule (or second considering fast-track). The remaining connections would be new.

Now, considering two different cases but in Mangle, marking connection and setting priority, would you use connection-state=new?

/ip firewall mangle add action=mark-connection chain=input connection-mark=no-mark in-interface=VLAN-X new-connection-mark=VLAN-X passthrough=yes

/ip firewall mangle add action=set-priority chain=postrouting new-priority=from-dscp-high-3-bits out-interface=VLAN-X passthrough=yes

In general, connection state is new, is Rarely if ever needed in firewall rules.
However in mangle rules, it can be used in niche caches to distinguish traffic that has already been processed. I cannot think of examples of the top of my head, but I have seen it done.
No track in these cases may not be sufficient to delineate traffic and thus use of new connection is of value.

1 Like

In the mangle table, normally there are no early rules that catch the established/related connection state like in the filter table. Here using connection-state=new can be useful for mark-connection type rules.

  • In case your mark-connection rules are able to cover all connections, which means you can be sure that once the mangle table has been processed, all connections have some kind of connection-mark associated or have all packets skipped early by action=accept rules, then connection-mark=new is not necessary, because usually you would also have the connection-mark=no-mark condition in those action=mark-connection rules. Once the connection state is no longer new then the connections should all have some kind of mark (or are accepted early). So having connection-state=new would be redundant when connection-mark=no-mark is already present in the same rule.

  • But in case your mangles mark-connection and accept rules cannot cover all connections (there are connections that match none of the rules and as a result will not have connection-mark ever, and will also not be accepted early), then it's preferable to also include connection-state=new in the mark-connection rules.

  • For rules that have to act on every packets, like mark-routing, mark-packet, or set-priority rules, then of course connection-state=new will not be included. Same with change-mss rules because they might have to act on the first return packet too.

But at the moment the way the firewall processes the conditions is not yet optimal. As you can see from the benchmark in this thread:

MikroTik currently does not perform optimizations where "cheaper" conditions (such as connection-state=new) are evaluated first, so that more expensive condition evaluation (such as address list matching) can be skipped early. As a result, including connection-state=new doesn't bring the expected speedup yet.

But future RouterOS versions might implement such improvements.

1 Like

Not really. As per documentation, possible connection states are new, invalid, established, related, or untracked. So after the first rule, which "consumes" packets with connection state either "established" or "related", the rest of packets will be either invalid, untracked or new. So it still makes sense to do something about invalid and untracked packets before assuming that you're only dealing with new packets. And it does make sense to have a rule dealing with untracked packets ... because it's only too easy to add a mangle rule which causes some packets to skip connection tracking ... and those would then evaluate the rules without connection-tracking property set ... which might or might not make sense.

1 Like