pf: allow states to be killed by their pre-NAT address

If a connection is NAT-ed we could previously only terminate it by its
ID or the post-NAT IP address. Allow users to specify they want look for
the state by its pre-NAT address. Usage: `pfctl -k nat -k <address>`.

See also:	https://redmine.pfsense.org/issues/11556
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D42312
This commit is contained in:
Kristof Provost 2023-10-20 07:37:46 +02:00
parent ef067b5799
commit 4f33755051
7 changed files with 24 additions and 7 deletions

View file

@ -1468,6 +1468,7 @@ _pfctl_clear_states(int dev, const struct pfctl_kill *kill,
nvlist_add_string(nvl, "ifname", kill->ifname);
nvlist_add_string(nvl, "label", kill->label);
nvlist_add_bool(nvl, "kill_match", kill->kill_match);
nvlist_add_bool(nvl, "nat", kill->nat);
if ((ret = pfctl_do_ioctl(dev, ioctlval, 1024, &nvl)) != 0)
return (ret);

View file

@ -310,6 +310,7 @@ struct pfctl_kill {
char ifname[IFNAMSIZ];
char label[PF_RULE_LABEL_SIZE];
bool kill_match;
bool nat;
};
struct pfctl_state_peer {

View file

@ -24,7 +24,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd February 22, 2021
.Dd October 20, 2023
.Dt PFCTL 8
.Os
.Sh NAME
@ -43,7 +43,7 @@
.Op Fl K Ar host | network
.Xo
.Oo Fl k
.Ar host | network | label | id | gateway
.Ar host | network | label | id | gateway | nat
.Oc Xc
.Op Fl o Ar level
.Op Fl p Ar device
@ -256,15 +256,16 @@ option may be specified, which will kill all the source tracking
entries from the first host/network to the second.
.It Xo
.Fl k
.Ar host | network | label | id | gateway
.Ar host | network | label | id | gateway | nat
.Xc
Kill all of the state entries matching the specified
.Ar host ,
.Ar network ,
.Ar label ,
.Ar id ,
.Ar gateway,
or
.Ar gateway.
.Ar nat.
.Pp
For example, to kill all of the state entries originating from
.Dq host :
@ -332,6 +333,10 @@ To kill all states using a gateway in 192.168.0.0/24:
.Pp
.Dl # pfctl -k gateway -k 192.168.0.0/24
.Pp
States can also be killed based on their pre-NAT address:
.Pp
.Dl # pfctl -k nat -k 192.168.0.1
.Pp
.It Fl M
Kill matching states in the opposite direction (on other interfaces) when
killing states.

View file

@ -725,6 +725,12 @@ pfctl_net_kill_states(int dev, const char *iface, int opts)
sizeof(kill.ifname)) >= sizeof(kill.ifname))
errx(1, "invalid interface: %s", iface);
if (state_killers == 2 && (strcmp(state_kill[0], "nat") == 0)) {
kill.nat = true;
state_kill[0] = state_kill[1];
state_killers = 1;
}
pfctl_addrprefix(state_kill[0], &kill.src.addr.v.a.mask);
if (opts & PF_OPT_KILLMATCH)

View file

@ -1770,6 +1770,7 @@ struct pf_kstate_kill {
char psk_label[PF_RULE_LABEL_SIZE];
u_int psk_killed;
bool psk_kill_match;
bool psk_nat;
};
#endif

View file

@ -2249,7 +2249,7 @@ pf_killstates_row(struct pf_kstate_kill *psk, struct pf_idhash *ih)
/* For floating states look at the original kif. */
kif = s->kif == V_pfi_all ? s->orig_kif : s->kif;
sk = s->key[PF_SK_WIRE];
sk = s->key[psk->psk_nat ? PF_SK_STACK : PF_SK_WIRE];
if (s->direction == PF_OUT) {
srcaddr = &sk->addr[1];
dstaddr = &sk->addr[0];
@ -2308,10 +2308,10 @@ pf_killstates_row(struct pf_kstate_kill *psk, struct pf_idhash *ih)
if (s->direction == PF_OUT) {
dir = PF_IN;
idx = PF_SK_STACK;
idx = psk->psk_nat ? PF_SK_WIRE : PF_SK_STACK;
} else {
dir = PF_OUT;
idx = PF_SK_WIRE;
idx = psk->psk_nat ? PF_SK_STACK : PF_SK_WIRE;
}
match_key.af = s->key[idx]->af;

View file

@ -873,6 +873,9 @@ pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl,
sizeof(kill->psk_label)));
PFNV_CHK(pf_nvbool(nvl, "kill_match", &kill->psk_kill_match));
if (nvlist_exists_bool(nvl, "nat"))
PFNV_CHK(pf_nvbool(nvl, "nat", &kill->psk_nat));
errout:
return (error);
}