IPFW net.inet.ip.fw.dyn_keep_states=1: packets just disappear

When a keepstate rule is deleted (e.g. due to update of the rules), normally all the dynamic rules that have been created from it, are also deleted. That means that currently open connections will block and need to disconnect and create a new connection. Not always the desired thing..

So I was helping this by declaring set #30 the garret, and instead of deleting rules, move them all there and make this set inactive. That works fine. Over time the garret bloats, but, well, memory is cheap nowadays.

With IPv6, if you want to use NPTv6, this does not work any longer. If you move the rules to some other set, the NPTv6 instance moves alongside. And it cannot move into a set where there is already one with the same name. And you cannot delete it without deleting the rules referencing it beforehand.
So, the scheme with the garret is no longer useable.
But, there is the sysctl net.inet.ip.fw.dyn_keep_states=1 - and that should do just the same:not delete the dynamic rules when the original keepstate rule gets deleted.
Only, it doesn't. Not exactly.

Truly, the dynamic rules will not get deleted. They will also show a flag "ORPHANED":
Code:
65054     551      42700 (51s) STATE tcp XX.XX.XX.XX 17573 <-> XX.XX.XX.XX 443 :f46r state
0x00060202 ORPHANED,BOTH_SYN, f_ack 0xcc73e09b, r_ack 0x687e7bf6
This dynamic rule carries the line-number of the original stateful rule - here 65054 - so one would expect that the matched packet will continue to be processed right after that rule number. But instead, it just disappear into thin air, without any logging.

It gets clear from the code - this is intentionally so (for whatever reason).
sys/netpfil/pfw/ip_fw_dynamic.c:
* In case when dyn_keep_states is enabled, return
* pointer to deleted rule and f_pos value
* corresponding to penultimate rule.
* When we have enabled V_dyn_keep_states, states
* that become orphaned will get the DYN_REFERENCED
* flag and rule will keep around. So we can return
* it. But since it is not in the rules map, we need
* return such f_pos value, so after the state
* handling if the search will continue, the next rule
* will be the last one - the default rule.
Exactly, the default rule throws away packet without logging.
It seems that just removing that line data->f_pos = V_layer3_chain.n_rules - 2; is enough to make things work as expected again.
 
Back
Top