PF can I change a pf scrub without flushing state?

I have a router that is set to use a 4G connection for its WAN as a failover connection. Now, in order to make this work reliably, I have to use scrub min_ttl 65.

Now, when I do this, traceroute breaks, for obvious reasons. And, from time to time, the router will run traceroute, and I need to have it working.

So, I have tried dynamically reloading the pf scrub so that the min_ttl is removed when it is time to run tcpdump. This works; the router can then successfully use traceroute.

But... the firewall then blocks ALL traffic between the LAN and WAN that are based on existing connections until those connections expire out of the state table. Some connections are sensitive (phone calls for instance) and flushing state would cause those calls to drop.

Now, the goal here is to be able to use traceroute from the router when it is needed while not interrupting traffic between the WAN and the LAN and not facing a circumstance where the carrier throttles us based on ttl values (they shouldn't; our contract with them is explicit about what we are doing, but they do anyway because their monitoring systems are idiotic).

Does anyone know how I might accomplish this? traceroute -I has no effect; the outbound ttl is set to 65 and it doesn't work.
 
I decided to take the path of least resistance, and modified the kernel. Now pf won't modify the ttl of icmp packets. This deals with my problem, though a userspace solution would be more desirable.
 
You can change all rules without losing state. Existing states will keep having the old rules applied to them.

How are you reloading the rules? `pfctl -g -f /etc/pf.conf` or `service pf reload` should both keep existing states. `service pf restart` will flush states.
 
The states were kept, which is why I originally thought it was working correctly. However, those states don't appear to work, though any new state does work.

This is done algorithmically in PHP. Basically, the command used is "/sbin/pfctl -f -" where the contents of the input stream consist of a number of "set skip" statements, a "set ruleset-optimization" statement, a few "set timeout" statements, and the scrub statement.

None of the set statements ever change anything, and the scrub statement changes by either the presence or the absence of the min-ttl statement.
 
Do not work means that traffic passing through the box with an existing state does not match any of the rules in the firewall ruleset, and wind up being blocked by the final default block rule.

I use the "pass/block quick" format so the first match is the one that is selected.

Having the old rules applied to existing states is what I would expect to happen, and that is fine. The whole point of changing this scrub is to remove the min-ttl so that traceroute will work.

Having traffic match no rule (and, apparently, no state - which would bypass the rules check) is a problem. Evidently all the traffic is being dropped because it is not matching any existing state and since these packets assume a connection rather than trying to establish a connection, they wind up being dropped.

One other thing I should note: This is a highly modified FreeBSD 8.4 system. PF has undergone serious changes since 8.4 but those mostly are internal queueing and multi-threading, as far as I can tell. So I don't know if this behavior on FreeBSD12 is different. We are preparing a new release of our system, based on FreeBSD 12 and a complete internal refactoring, but that effort was virtually halted when the pandemic hit; we needed to rework our existing product to deal with the changed environment.

So it is coming but not here yet and right now I am dealing with a PF problem on 8.4.
 
Back
Top