For every state pf creates up to two source nodes: a limiting one `struct pf_kstate -> src_node` and a NAT one `struct pf_kstate -> nat_src_node`. The limiting source node is tracking information needed for limits using `max-src-states` and `max-src-nodes` and the NAT source node is tracking NAT rules only.
On closer inspection three issues emerge:
- For route-to rules the redirection decision is stored in the limiting source node. Thus `sticky-address` and source limiting can't be used separatelystruct pf_kstate -> src_node and a NAT one struct pf_kstate -> nat_src_node.
- Global source tracking, as promised in the man page, is totally absent from the code. Pfctl is capable of setting flags `PFRULE_SRCTRACK` (enable source tracking) and `PFRULE_RULESRCTRACK` (make source tracking per rule). The kernel code checks `PFRULE_SRCTRACK` but ignores `PFRULE_RULESRCTRACK`. That would make all source tracking always global but the code is written in a way that makes source tracking work per-rule only.The limiting source node is tracking information needed for limits using
- Once OpenBSD syntax is imported, we might need even more SNs per rule. It should be possible to have limits, nat and route-to decisions in a single rulemax-src-states and max-src-nodes and the NAT source node is tracking NAT
rules only.
This patch is based on OpenBSD approach where source nodes have a type and each state has a list of source nodes instead of just two pointers.
The patch also fixes multiple regarding source nodesOn closer inspection some issues emerge:
- Source nodes are not created anymore with zeroed address to be filled in later. The lock is held throughout the whole process of SN search, creation and LB decision.For route-to rules the redirection decision is stored in the limiting source
- Existence of SNs created during ruleset evaluation is checked when creating a state, node. in case the SNs have been killedThus sticky-address and source limiting can't be used separately.
- Killing specified SNs has been merged with killing all SNs- Global source tracking, as promised in the man page, which also solves locking issues in `pf_clear_srcnodes()`.is totally absent from
- A minimal `struct pf_test_ctx` has been created, to be used more in the future, the code. like in OpenBSD.Pfctl is capable of setting flags PFRULE_SRCTRACK (enable source
- The approach to make global tracking work is to attach global source nodes to the default rule. This functionality seems broken in OpenBSD too. I've checked their code history, tracking) and PFRULE_RULESRCTRACK (make source tracking per rule). there was a `global` flag to `pf_insert_src_node()` at some point but it was removed.The kernel
- Off-by-one errors for limits. code checks PFRULE_SRCTRACK but ignores PFRULE_RULESRCTRACK. That makes
source tracking work per-rule only.
This patch is based on OpenBSD approach where source nodes have a type and each
state has an array of source node pointers indexed by source node type
instead of just two pointers. The conditions for limiting are applied
only to source nodes of PF_SN_LIMIT type. For global limit tracking
source nodes are attached to the default rule.
Sponsored by: InnoGames GmbH