Firewall scheduled blocks doesn’t break existing sessions

Started by Splodge, May 15, 2025, 04:10:58 PM

Previous topic - Next topic
Hi,

I'm running latest BE and have had an issue for a while that I have only just got around to posting about :)

When I use firewall schedule to block traffic to a certain VLAN, I can see new sessions are being blocked fine, but any existing sessions remain open.
How can I automatically force terminate any existing sessions with the firewall rule, so block traffic on that VLAN is instant, not waiting for an open session to close?

Given the help tip for a related setting (https://docs.opnsense.org/manual/firewall_settings.html#schedule-states), I would think that the rules need to be authored in a way that they allow during the schedule.
An allow at all times with a block on the opposite schedule might not cut it, which looks like what you've done.

It would make sense from an implementation perspective. Set a timer at the end of the schedule, delete all state related to the rule.

The other way does not work, especially because the allow and block aren't related.
When a block becomes active, you'd have to go through all states are re-evaluate against the new effective rules. Yuck!

Thanks for your help with this. I ended up deleting all firewall rules and starting afresh but it still didnt work as expected.
Foe example, a Teams voice call would continue through the firewall if established before the corresponding allow rule was disabled...

Digging a bit, it seems to be a "feature" in the underlying FreeBSD firewall itself, see https://github.com/opnsense/core/issues/3166

It looks like the only workaround is to create a custom cron job to reset the sessions after the firewall rule has been changed.

You can only use pass rules with schedules for this.
OPNsense knows each connection, which was allowed by the pass rule and can remove the respective states after expiration.

But a block rule doesn't create any state. Hence no state are deleted, when it takes effect.

Originally I was using block but on my second round of testing it was a pass rule, and it didnt break existing Teams call.

One single rule for the interface that was Pass based on schedule.

If this pass rule was either disabled manually on the GUI or disabled via schedule, any new connections would be blocked (as watching the live log) but the existing connection through opnSense to the MS Teams mothership remained in place, and the Teams call continued.

To be sure, Firewall: Settings: Advanced: Schedule States is unchecked?

Yep, default was unchecked, but to be sure I tried it with both checked and unchecked - same behaviour.

https://forum.opnsense.org/index.php?topic=10740.msg49334

...quite a bit rude to kill all states when kiddy internet time expires, but at least it works reliable here. For years. In the meantime no need any more, but the rules and the cron jobs are still there... :-D
kind regards
chemlud
____
"The price of reliability is the pursuit of the utmost simplicity."
C.A.R. Hoare

felix eichhorns premium katzenfutter mit der extraportion energie

A router is not a switch - A router is not a switch - A router is not a switch - A rou....

Resetting global state to achieve specific state "expiration" is an ugly workaround.
It's obvious that there's built-in functionality that's supposed to address the problem.

Quote from: Splodge on May 16, 2025, 03:55:42 PMThanks for your help with this. I ended up deleting all firewall rules and starting afresh but it still didnt work as expected.
Foe example, a Teams voice call would continue through the firewall if established before the corresponding allow rule was disabled...
Did you have a chance to verify that the state created for that voice call was linked to the expected rule (with expiration)?
When you test, I'd make sure that the state is created AFTER the rule/schedule are applied.
For that matter, you might want to avoid any changes to rules after you start the call, at least to begin with.

Quote from: Splodge on May 16, 2025, 03:55:42 PMDigging a bit, it seems to be a "feature" in the underlying FreeBSD firewall itself, see https://github.com/opnsense/core/issues/3166

It looks like the only workaround is to create a custom cron job to reset the sessions after the firewall rule has been changed.
Unrelated. Going back to my first comment, I'm not surprised that this issue was closed as by design (to avoid re-evaluating the entire state table on every updates to FW rules).
That's why putting the schedule on block rules does NOT work.

With the schedule attached to an allow rule (and since state is linked to the rule that allowed its creation), expiring related state can be efficient.

Thanks for the pointers here; I've fixed this but if I'm honest I'm not totally sure why!

I managed to reproduce the issue on my home DEC750, by starting a download of a large ISO from Ubuntu and watching it when the blocking was supposed to start. Using the hint from EricPerl, I checked the actual rule allowing the traffic to remain flowing and it was the allow everything out the gateway (forcegw) one. New connections were getting blocked by the scheduled Pass rule as expected.
By checking "Disable force gateway" in the firewall advanced settings, scheduled traffic blocking (by disabling the pass rule on a schedule) worked as expected.

The forcegw rule seemed to be associated with the PPPoE ISP tunnel (Fibre ONT to igb0, carrying PPPoE over VLAN) and I don't fully understand what this forcegw rule is supposed to achieve, but checking the disable box fixed the issue and everything else seems to work fine...

Thanks all :)

Although working now, been looking around some more with this blocking issue; really can't work out why forcegw would affect in this way.
I'm not totally comfortable with leaving it be - think it's time to nuke the config and start again with a factory default config. Luckily only a few VLAN and PPPoE to setup, so not too much hassle...

BTW, ForceGW is not PPPoE specific. I have that rule and I don't use PPPoE.
It's probably one of the most obscure settings. I'm not entirely sure what it does...

Anyway, I can't connect the dots here.
Your rules with schedules are enforced as 'in' rules on LAN facing interfaces, right?
While most of the traffic during a download will be from the server back to the client, I'd expect the client to have to ACK/participate.
The latter can't happen if the 'in' state was killed.
The corresponding 'out' state on the WAN side might survive for a while (not sure if the server will close after it no longer receives acks from the client or if it will expire for inactivity later on). That's not that different from the client being removed from the network...
I don't even believe the replies from the server make it back all the way to the client after the 'in' state disappears.

When you found that 'out' state, there was an IP:port in the NAT column.
Probably one line higher, there was an 'in' state with that IP:port as source and the same destination (the server).
That 'in' state should point to the scheduled rule.
Ideally, you'd locate this before the rule expires so you can check that at least the 'in' state disappears later.

I do not know if the corresponding 'out' state is expected to be torn down immediately as well.

Yes, the rules are on the interface 'in'.

When looking at the states & sessions (after the schedule has expired and the Pass rule not effective) filtered to the single IP address on the device of the scheduled VLAN, there is no 'in' rule active, only the out rule.
BUT despite there being no IN rules associated with that VLAN / IP Address, traffic still flows.

The config on this device is a couple of years old now - we got the DEC750s with BE licences late 2023, so there have been many firmware updates since then.
As it's a fairly simple config, I'm just going to nuke, reinstall the BE firmware and reconfigure later today...

Not chasing and tearing down the out state (after NAT) corresponding to the in state might be fine, as long as the expected functionality is achieved (which appears to not be case).

The fact that the download proceeds surprises me.
As mentioned earlier, the client is regularly acknowledging the fragments of the received download (which it probably should no longer receive in the first place, also because of the absence of the in state).
But at a minimum, the client ACKs should end up with state violation (visible in live view with default deny logging enabled), thus should be dropped. And the server should stop sending data to an unresponsive client.