diff options
author | Kajetan Staszkiewicz <ks@FreeBSD.org> | 2025-02-07 11:40:09 +0000 |
---|---|---|
committer | Kajetan Staszkiewicz <ks@FreeBSD.org> | 2025-02-13 14:59:12 +0000 |
commit | 07e070ef086997590cd6d9d47908885c12947bd2 (patch) | |
tree | 280e9348bb8714ef281b49a6bbf8ff8b9a8c3208 /lib | |
parent | b61fbbed73ea3bf0c84589b56cca160c46a3739d (diff) |
pf: Add support for multiple source node types
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 some 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 separately.
- 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 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.
Reviewed by: kp
Approved by: kp (mentor)
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D39880
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libpfctl/libpfctl.c | 5 | ||||
-rw-r--r-- | lib/libpfctl/libpfctl.h | 3 |
2 files changed, 8 insertions, 0 deletions
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index fe63c91c1174..e93c79758428 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -1665,6 +1665,9 @@ static struct snl_attr_parser ap_getrule[] = { { .type = PF_RT_NAF, .off = _OUT(r.naf), .cb = snl_attr_get_uint8 }, { .type = PF_RT_RPOOL_RT, .off = _OUT(r.route), .arg = &pool_parser, .cb = snl_attr_get_nested }, { .type = PF_RT_RCV_IFNOT, .off = _OUT(r.rcvifnot),.cb = snl_attr_get_bool }, + { .type = PF_RT_SRC_NODES_LIMIT, .off = _OUT(r.src_nodes_type[PF_SN_LIMIT]), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_SRC_NODES_NAT, .off = _OUT(r.src_nodes_type[PF_SN_NAT]), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_SRC_NODES_ROUTE, .off = _OUT(r.src_nodes_type[PF_SN_ROUTE]), .cb = snl_attr_get_uint64 }, }; #undef _OUT SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, snl_f_p_empty, ap_getrule); @@ -1910,6 +1913,7 @@ static struct snl_attr_parser ap_state[] = { { .type = PF_ST_DNRPIPE, .off = _OUT(dnrpipe), .cb = snl_attr_get_uint16 }, { .type = PF_ST_RT, .off = _OUT(rt), .cb = snl_attr_get_uint8 }, { .type = PF_ST_RT_IFNAME, .off = _OUT(rt_ifname), .cb = snl_attr_store_ifname }, + { .type = PF_ST_SRC_NODE_FLAGS, .off = _OUT(src_node_flags), .cb = snl_attr_get_uint8 }, }; #undef _IN #undef _OUT @@ -3018,6 +3022,7 @@ static struct snl_attr_parser ap_srcnode[] = { { .type = PF_SN_EXPIRE, .off = _OUT(expire), .cb = snl_attr_get_uint64 }, { .type = PF_SN_CONNECTION_RATE, .off = _OUT(conn_rate), .arg = &pfctl_threshold_parser, .cb = snl_attr_get_nested }, { .type = PF_SN_NAF, .off = _OUT(naf), .cb = snl_attr_get_uint8 }, + { .type = PF_SN_NODE_TYPE, .off = _OUT(type), .cb = snl_attr_get_uint8 }, }; #undef _OUT SNL_DECLARE_PARSER(srcnode_parser, struct genlmsghdr, snl_f_p_empty, ap_srcnode); diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index e1af4b5e97ff..1108b0ffc693 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -216,6 +216,7 @@ struct pfctl_rule { uint64_t states_cur; uint64_t states_tot; uint64_t src_nodes; + uint64_t src_nodes_type[PF_SN_MAX]; uint16_t return_icmp; uint16_t return_icmp6; @@ -373,6 +374,7 @@ struct pfctl_state { uint8_t set_prio[2]; uint8_t rt; char rt_ifname[IFNAMSIZ]; + uint8_t src_node_flags; }; TAILQ_HEAD(pfctl_statelist, pfctl_state); @@ -415,6 +417,7 @@ struct pfctl_src_node { uint64_t creation; uint64_t expire; struct pfctl_threshold conn_rate; + pf_sn_types_t type; }; #define PF_DEVICE "/dev/pf" |