Let's talk firewall rule order ...

Started by Patrick M. Hausen, January 29, 2026, 10:05:39 PM

Previous topic - Next topic
January 29, 2026, 10:05:39 PM Last Edit: January 29, 2026, 10:17:09 PM by Patrick M. Hausen
OK, I just noticed a thing after upgrading to 26.1 and using the new rule interface. I suspect the issue was present in previous versions in the same manner, I just did not notice it.

So rule order watched from the highest level is:

Floating > Interface group > Interface

This is well documented and has not changed ever I could remember. And I use it more or less extensively to get a maintainable structure and a low number of rules.

Floating:



I really do think that blocking ICMP echo is silly, that it's the most important debug tool of all in IP, so I generally allow it, even when other traffic across the same interfaces is forbidden.

Interface groups:

I have one interface group "Internal" which is all my interfaces but WAN and the one to the DSL modems's management interface. I have another group named "Restricted" which is the same as "Internal" but without LAN. These are the interfaces for which I block any "cross talk". LAN after floating and groups applied has a final "allow all" rule just like the default setup.

These are the rules for the "Restricted" group:



This allows essential services to the respective firewall interface plus Internet access to arbitrary services but no access to any other local network. If you look closely you recognise that this set of rules does not yet prohibit e.g. SMTP out to the Internet. It's only "allow" rules, so the first three simply do not match and then the last two still allow DNS, NTP and SMTP outbound.

But I take care of that in the "Internal" group:



Since my LAN is generally "allow all" but I still want to restrict DNS, NTP and SMTP, the block rules for these go into the "Internal" group. Remember, that contains all "Restricted" interfaces plus LAN.

Result:

This works. I just verified by disabling all "Internal" rules - SMTP from a host on a restricted interface to the Internet is open. Enable again - SMTP blocked.

Fine.

My question is: why?

Why are the group rules for the "Internal" group applied before the rules for the "Restricted" group? As is obviously the case? And how can I guarantee a certain order of certain groups, because I want block before allow? Is it the metric system ... er ... alphabetical sorting?

Kind regards,
Patrick
Deciso DEC750
People who think they know everything are a great annoyance to those of us who do. (Isaac Asimov)

January 29, 2026, 10:14:21 PM #1 Last Edit: January 29, 2026, 11:13:06 PM by meyergru
Made me laugh, Patrick, because I have exactly the same distinction between "internal" and "restricted" (this one even with the same name).

As for your question: Look under Firewall: Groups, the interface group have an assigned "sequence" which I believe to determine the order.

Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 800 up, Bufferbloat A+

January 29, 2026, 10:17:52 PM #2 Last Edit: January 29, 2026, 11:24:22 PM by Patrick M. Hausen
Quote from: meyergru on January 29, 2026, 10:14:21 PMLook under Firewall: Groups, the interface group have an assigned "sequence" which I believe to determine the order.

I never noticed this exists. Bummer! Thanks!

They are both set to 0 - so it's alphabetical or order of creation or whatever, but at least now I know how to force a specific order.

EDIT:

I could not find that in the docs - lowest number wins. All automatic groups (IPsec, OpenVPN, WireGuard) are set to 10 by default, all user created ones to 0.

If I set "Internal" to 1 and "Restricted" to 2, outbound SMTP is still blocked, if I change "Internal" to 3, it's allowed.

*phew* What a rabbit hole :-)
Deciso DEC750
People who think they know everything are a great annoyance to those of us who do. (Isaac Asimov)

Quote from: Patrick M. Hausen on January 29, 2026, 10:17:52 PM*phew* What a rabbit hole :-)

I wonder what percentage of people can still follow what we are talking about here... ;-)

Yet, I had only the typical "Block RESTRICTED to local networks" and "Allow any to internet" rules in the RESTRICTED group, which I switched out for explicit interface rules at some point. Unless you have a large number of VLANs, it seemed more explicit that way to me.
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 800 up, Bufferbloat A+

Indeed the sequence order in the groups sets the order of those group rules when inherited into an Interface.

And you are right its not mentioned in docs just slightly hinted in
https://docs.opnsense.org/manual/how-tos/security-zones.html#setup-interface-groups

I have several groups created, cause I look at them as policies, and policies are inherited into Interfaces (I look at them as Zones). So when you do groups its necessarily to consider the sequence order because of

Quotegroups use 300000
This means 300000 + the sequence number in groups

https://docs.opnsense.org/manual/how-tos/security-zones.html#setup-interface-groups

At least that was my interpretation when doing the design.

Regards,
S.
Networking is love. You may hate it, but in the end, you always come back to it.

OPNSense HW
APU2D2 - deceased
N5105 - i226-V | Patriot 2x8G 3200 DDR4 | L 790 512G - VM HA(SOON)
N100   - i226-V | Crucial 16G  4800 DDR5 | S 980 500G - PROD

In my  setup I combining interface groups as security zones (similar Internal/Restricted model) with a multi‑layer DNS stack (dnscrypt‑proxy on localhost, Unbound as validating resolver and AdGuard Home on a separate VLAN), and we've just added Q‑Feeds domain/IP feeds on top.


Being able to control the group rule order via the sequence field is exactly what we need to keep the "global block policies" applied before the more permissive per‑zone rules without exploding the number of interface rules.

Since the sequence field essentially controls policy precedence between interface groups, it might be worth surfacing this more clearly in the UI and docs.
For example, a short note or tooltip like "lower sequence = evaluated earlier (group rules are ordered by 300000 + sequence)" under Firewall → Groups would make it much easier for people using policy‑style groups (Internal/Restricted, IoT/Guest, etc.) to design their rulesets intentionally instead of discovering the behaviour by trial and error.