mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-06 16:40:47 +00:00
pf: allow pflow to be activated per rule
Only generate ipfix/netflow reports (through pflow) for the rules where this is enabled. Reports can also be enabled globally through 'set state-default pflow'. Obtained from: OpenBSD Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D43108
This commit is contained in:
parent
5dea523bd2
commit
baf9b6d042
|
@ -172,7 +172,8 @@ enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
|
|||
PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
|
||||
PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
|
||||
PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
|
||||
PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY, };
|
||||
PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY,
|
||||
PF_STATE_OPT_PFLOW };
|
||||
|
||||
enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
|
||||
|
||||
|
@ -512,7 +513,7 @@ int parseport(char *, struct range *r, int);
|
|||
%token DNPIPE DNQUEUE RIDENTIFIER
|
||||
%token LOAD RULESET_OPTIMIZATION PRIO
|
||||
%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
|
||||
%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY
|
||||
%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW
|
||||
%token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS
|
||||
%token DIVERTTO DIVERTREPLY BRIDGE_TO
|
||||
%token <v.string> STRING
|
||||
|
@ -2615,6 +2616,14 @@ pfrule : action dir logquick interface route af proto fromto
|
|||
}
|
||||
r.rule_flag |= PFRULE_STATESLOPPY;
|
||||
break;
|
||||
case PF_STATE_OPT_PFLOW:
|
||||
if (r.rule_flag & PFRULE_PFLOW) {
|
||||
yyerror("state pflow option: "
|
||||
"multiple definitions");
|
||||
YYERROR;
|
||||
}
|
||||
r.rule_flag |= PFRULE_PFLOW;
|
||||
break;
|
||||
case PF_STATE_OPT_TIMEOUT:
|
||||
if (o->data.timeout.number ==
|
||||
PFTM_ADAPTIVE_START ||
|
||||
|
@ -4368,6 +4377,14 @@ state_opt_item : MAXIMUM NUMBER {
|
|||
$$->next = NULL;
|
||||
$$->tail = $$;
|
||||
}
|
||||
| PFLOW {
|
||||
$$ = calloc(1, sizeof(struct node_state_opt));
|
||||
if ($$ == NULL)
|
||||
err(1, "state_opt_item: calloc");
|
||||
$$->type = PF_STATE_OPT_PFLOW;
|
||||
$$->next = NULL;
|
||||
$$->tail = $$;
|
||||
}
|
||||
| STRING NUMBER {
|
||||
int i;
|
||||
|
||||
|
@ -6318,6 +6335,7 @@ lookup(char *s)
|
|||
{ "out", OUT},
|
||||
{ "overload", OVERLOAD},
|
||||
{ "pass", PASS},
|
||||
{ "pflow", PFLOW},
|
||||
{ "port", PORT},
|
||||
{ "prio", PRIO},
|
||||
{ "priority", PRIORITY},
|
||||
|
|
|
@ -376,6 +376,8 @@ print_state(struct pfctl_state *s, int opts)
|
|||
printf(", sloppy");
|
||||
if (s->state_flags & PFSTATE_NOSYNC)
|
||||
printf(", no-sync");
|
||||
if (s->state_flags & PFSTATE_PFLOW)
|
||||
printf(", pflow");
|
||||
if (s->state_flags & PFSTATE_ACK)
|
||||
printf(", psync-ack");
|
||||
if (s->state_flags & PFSTATE_NODF)
|
||||
|
|
|
@ -1051,6 +1051,8 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
|
|||
opts = 1;
|
||||
if (r->rule_flag & PFRULE_STATESLOPPY)
|
||||
opts = 1;
|
||||
if (r->rule_flag & PFRULE_PFLOW)
|
||||
opts = 1;
|
||||
for (i = 0; !opts && i < PFTM_MAX; ++i)
|
||||
if (r->timeout[i])
|
||||
opts = 1;
|
||||
|
@ -1123,6 +1125,12 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
|
|||
printf("sloppy");
|
||||
opts = 0;
|
||||
}
|
||||
if (r->rule_flag & PFRULE_PFLOW) {
|
||||
if (!opts)
|
||||
printf(", ");
|
||||
printf("pflow");
|
||||
opts = 0;
|
||||
}
|
||||
for (i = 0; i < PFTM_MAX; ++i)
|
||||
if (r->timeout[i]) {
|
||||
int j;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd November 17, 2023
|
||||
.Dd December 6, 2023
|
||||
.Dt PF.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -2429,6 +2429,10 @@ easier.
|
|||
This is intended to be used in situations where one does not see all
|
||||
packets of a connection, e.g. in asymmetric routing situations.
|
||||
Cannot be used with modulate or synproxy state.
|
||||
.It Ar pflow
|
||||
States created by this rule are exported on the
|
||||
.Xr pflow 4
|
||||
interface.
|
||||
.El
|
||||
.Pp
|
||||
Multiple options can be specified, separated by commas:
|
||||
|
@ -3345,7 +3349,7 @@ state-opt = ( "max" number | "no-sync" | timeout | "sloppy" |
|
|||
"max-src-conn" number |
|
||||
"max-src-conn-rate" number "/" number |
|
||||
"overload" "\*(Lt" string "\*(Gt" [ "flush" ] |
|
||||
"if-bound" | "floating" )
|
||||
"if-bound" | "floating" | "pflow" )
|
||||
|
||||
fragmentation = [ "fragment reassemble" ]
|
||||
|
||||
|
@ -3406,6 +3410,7 @@ Service name database.
|
|||
.Xr ip 4 ,
|
||||
.Xr ip6 4 ,
|
||||
.Xr pf 4 ,
|
||||
.Xr pflow 4 ,
|
||||
.Xr pfsync 4 ,
|
||||
.Xr tcp 4 ,
|
||||
.Xr sctp 4 ,
|
||||
|
|
|
@ -326,7 +326,6 @@ enum pflow_set_type_t {
|
|||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
int export_pflow(struct pf_kstate *);
|
||||
int pflow_sysctl(int *, u_int, void *, size_t *, void *, size_t);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
|
|
@ -1186,6 +1186,7 @@ typedef void pfsync_delete_state_t(struct pf_kstate *);
|
|||
typedef void pfsync_clear_states_t(u_int32_t, const char *);
|
||||
typedef int pfsync_defer_t(struct pf_kstate *, struct mbuf *);
|
||||
typedef void pfsync_detach_ifnet_t(struct ifnet *);
|
||||
typedef void pflow_export_state_t(const struct pf_kstate *);
|
||||
|
||||
VNET_DECLARE(pfsync_state_import_t *, pfsync_state_import_ptr);
|
||||
#define V_pfsync_state_import_ptr VNET(pfsync_state_import_ptr)
|
||||
|
@ -1199,6 +1200,8 @@ VNET_DECLARE(pfsync_clear_states_t *, pfsync_clear_states_ptr);
|
|||
#define V_pfsync_clear_states_ptr VNET(pfsync_clear_states_ptr)
|
||||
VNET_DECLARE(pfsync_defer_t *, pfsync_defer_ptr);
|
||||
#define V_pfsync_defer_ptr VNET(pfsync_defer_ptr)
|
||||
VNET_DECLARE(pflow_export_state_t *, pflow_export_state_ptr);
|
||||
#define V_pflow_export_state_ptr VNET(pflow_export_state_ptr)
|
||||
extern pfsync_detach_ifnet_t *pfsync_detach_ifnet_ptr;
|
||||
|
||||
void pfsync_state_export(union pfsync_state_union *,
|
||||
|
|
|
@ -1397,6 +1397,9 @@ pf_detach_state(struct pf_kstate *s)
|
|||
|
||||
pf_sctp_multihome_detach_addr(s);
|
||||
|
||||
if ((s->state_flags & PFSTATE_PFLOW) && V_pflow_export_state_ptr)
|
||||
V_pflow_export_state_ptr(s);
|
||||
|
||||
if (sks != NULL) {
|
||||
kh = &V_pf_keyhash[pf_hashkey(sks)];
|
||||
PF_HASHROW_LOCK(kh);
|
||||
|
@ -4872,6 +4875,8 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
|
|||
s->state_flags |= PFSTATE_SLOPPY;
|
||||
if (pd->flags & PFDESC_TCP_NORM) /* Set by old-style scrub rules */
|
||||
s->state_flags |= PFSTATE_SCRUB_TCP;
|
||||
if (r->rule_flag & PFRULE_PFLOW)
|
||||
s->state_flags |= PFSTATE_PFLOW;
|
||||
|
||||
s->act.log = pd->act.log & PF_LOG_ALL;
|
||||
s->sync_state = PFSYNC_S_NONE;
|
||||
|
|
|
@ -614,6 +614,7 @@ struct pf_rule {
|
|||
#define PFRULE_SET_TOS 0x00002000
|
||||
#define PFRULE_IFBOUND 0x00010000 /* if-bound */
|
||||
#define PFRULE_STATESLOPPY 0x00020000 /* sloppy state tracking */
|
||||
#define PFRULE_PFLOW 0x00040000
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define PFRULE_REFS 0x0080 /* rule has references */
|
||||
|
@ -626,7 +627,7 @@ struct pf_rule {
|
|||
/* pf_state->state_flags, pf_rule_actions->flags, pf_krule->scrub_flags */
|
||||
#define PFSTATE_ALLOWOPTS 0x0001
|
||||
#define PFSTATE_SLOPPY 0x0002
|
||||
/* was PFSTATE_PFLOW 0x0004 */
|
||||
#define PFSTATE_PFLOW 0x0004
|
||||
#define PFSTATE_NOSYNC 0x0008
|
||||
#define PFSTATE_ACK 0x0010
|
||||
#define PFSTATE_NODF 0x0020
|
||||
|
|
|
@ -304,6 +304,7 @@ VNET_DEFINE(pfsync_update_state_t *, pfsync_update_state_ptr);
|
|||
VNET_DEFINE(pfsync_delete_state_t *, pfsync_delete_state_ptr);
|
||||
VNET_DEFINE(pfsync_clear_states_t *, pfsync_clear_states_ptr);
|
||||
VNET_DEFINE(pfsync_defer_t *, pfsync_defer_ptr);
|
||||
VNET_DEFINE(pflow_export_state_t *, pflow_export_state_ptr);
|
||||
pfsync_detach_ifnet_t *pfsync_detach_ifnet_ptr;
|
||||
|
||||
/* pflog */
|
||||
|
|
|
@ -87,18 +87,19 @@ static void pflow_timeout(void *);
|
|||
static void pflow_timeout6(void *);
|
||||
static void pflow_timeout_tmpl(void *);
|
||||
static void copy_flow_data(struct pflow_flow *, struct pflow_flow *,
|
||||
struct pf_kstate *, struct pf_state_key *, int, int);
|
||||
const struct pf_kstate *, struct pf_state_key *, int, int);
|
||||
static void copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *,
|
||||
struct pflow_ipfix_flow4 *, struct pf_kstate *, struct pf_state_key *,
|
||||
struct pflow_ipfix_flow4 *, const struct pf_kstate *, struct pf_state_key *,
|
||||
struct pflow_softc *, int, int);
|
||||
static void copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *,
|
||||
struct pflow_ipfix_flow6 *, struct pf_kstate *, struct pf_state_key *,
|
||||
struct pflow_ipfix_flow6 *, const struct pf_kstate *, struct pf_state_key *,
|
||||
struct pflow_softc *, int, int);
|
||||
static int pflow_pack_flow(struct pf_kstate *, struct pf_state_key *,
|
||||
static int pflow_pack_flow(const struct pf_kstate *, struct pf_state_key *,
|
||||
struct pflow_softc *);
|
||||
static int pflow_pack_flow_ipfix(struct pf_kstate *, struct pf_state_key *,
|
||||
static int pflow_pack_flow_ipfix(const struct pf_kstate *, struct pf_state_key *,
|
||||
struct pflow_softc *);
|
||||
static int export_pflow_if(struct pf_kstate*, struct pf_state_key *,
|
||||
static void export_pflow(const struct pf_kstate *);
|
||||
static int export_pflow_if(const struct pf_kstate*, struct pf_state_key *,
|
||||
struct pflow_softc *);
|
||||
static int copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc);
|
||||
static int copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow,
|
||||
|
@ -323,6 +324,8 @@ pflow_create(int unit)
|
|||
CK_LIST_INSERT_HEAD(&V_pflowif_list, pflowif, sc_next);
|
||||
mtx_unlock(&V_pflowif_list_mtx);
|
||||
|
||||
V_pflow_export_state_ptr = export_pflow;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -352,6 +355,8 @@ pflow_destroy(int unit, bool drain)
|
|||
return (ENOENT);
|
||||
}
|
||||
CK_LIST_REMOVE(sc, sc_next);
|
||||
if (CK_LIST_EMPTY(&V_pflowif_list))
|
||||
V_pflow_export_state_ptr = NULL;
|
||||
mtx_unlock(&V_pflowif_list_mtx);
|
||||
|
||||
sc->sc_dying = 1;
|
||||
|
@ -511,7 +516,7 @@ pflow_get_mbuf(struct pflow_softc *sc, u_int16_t set_id)
|
|||
|
||||
static void
|
||||
copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2,
|
||||
struct pf_kstate *st, struct pf_state_key *sk, int src, int dst)
|
||||
const struct pf_kstate *st, struct pf_state_key *sk, int src, int dst)
|
||||
{
|
||||
flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr;
|
||||
flow1->src_port = flow2->dest_port = sk->port[src];
|
||||
|
@ -548,7 +553,7 @@ copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2,
|
|||
|
||||
static void
|
||||
copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *flow1,
|
||||
struct pflow_ipfix_flow4 *flow2, struct pf_kstate *st,
|
||||
struct pflow_ipfix_flow4 *flow2, const struct pf_kstate *st,
|
||||
struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst)
|
||||
{
|
||||
flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr;
|
||||
|
@ -585,7 +590,7 @@ copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *flow1,
|
|||
|
||||
static void
|
||||
copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *flow1,
|
||||
struct pflow_ipfix_flow6 *flow2, struct pf_kstate *st,
|
||||
struct pflow_ipfix_flow6 *flow2, const struct pf_kstate *st,
|
||||
struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst)
|
||||
{
|
||||
bcopy(&sk->addr[src].v6, &flow1->src_ip, sizeof(flow1->src_ip));
|
||||
|
@ -622,8 +627,8 @@ copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *flow1,
|
|||
flow1->tos = flow2->tos = st->rule.ptr->tos;
|
||||
}
|
||||
|
||||
int
|
||||
export_pflow(struct pf_kstate *st)
|
||||
static void
|
||||
export_pflow(const struct pf_kstate *st)
|
||||
{
|
||||
struct pflow_softc *sc = NULL;
|
||||
struct pf_state_key *sk;
|
||||
|
@ -648,12 +653,10 @@ export_pflow(struct pf_kstate *st)
|
|||
}
|
||||
PFLOW_UNLOCK(sc);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
export_pflow_if(struct pf_kstate *st, struct pf_state_key *sk,
|
||||
export_pflow_if(const struct pf_kstate *st, struct pf_state_key *sk,
|
||||
struct pflow_softc *sc)
|
||||
{
|
||||
struct pf_kstate pfs_copy;
|
||||
|
@ -787,7 +790,7 @@ copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, struct pflow_softc *sc)
|
|||
}
|
||||
|
||||
static int
|
||||
pflow_pack_flow(struct pf_kstate *st, struct pf_state_key *sk,
|
||||
pflow_pack_flow(const struct pf_kstate *st, struct pf_state_key *sk,
|
||||
struct pflow_softc *sc)
|
||||
{
|
||||
struct pflow_flow flow1;
|
||||
|
@ -812,7 +815,7 @@ pflow_pack_flow(struct pf_kstate *st, struct pf_state_key *sk,
|
|||
}
|
||||
|
||||
static int
|
||||
pflow_pack_flow_ipfix(struct pf_kstate *st, struct pf_state_key *sk,
|
||||
pflow_pack_flow_ipfix(const struct pf_kstate *st, struct pf_state_key *sk,
|
||||
struct pflow_softc *sc)
|
||||
{
|
||||
struct pflow_ipfix_flow4 flow4_1, flow4_2;
|
||||
|
|
Loading…
Reference in a new issue