From 92d4152295bc670b80352b5fbe102565de99a4eb Mon Sep 17 00:00:00 2001 From: Kajetan Staszkiewicz Date: Mon, 21 Aug 2023 08:01:29 +0200 Subject: [PATCH] pf: enable the syncookie feature for IPv6 When syncookie support was added to pf the relevant work was only done in pf_test(), not pf_test6(). Do this now. MFC after: 1 week Reviewed by: kp Sponsored by: InnoGames GmbH Differential Revision: https://reviews.freebsd.org/D41502 --- sys/netpfil/pf/pf.c | 51 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index c2b9ee21d04..c80553ba017 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -8108,6 +8108,15 @@ pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb pd.p_len = pd.tot_len - off - (pd.hdr.tcp.th_off << 2); pd.sport = &pd.hdr.tcp.th_sport; pd.dport = &pd.hdr.tcp.th_dport; + + /* Respond to SYN with a syncookie. */ + if ((pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK|TH_RST)) == TH_SYN && + pd.dir == PF_IN && pf_synflood_check(&pd)) { + pf_syncookie_send(m, off, &pd); + action = PF_DROP; + break; + } + action = pf_normalize_tcp(kif, m, 0, off, h, &pd); if (action == PF_DROP) goto done; @@ -8117,9 +8126,45 @@ pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb V_pfsync_update_state_ptr(s); r = s->rule.ptr; a = s->anchor.ptr; - } else if (s == NULL) - action = pf_test_rule(&r, &s, kif, m, off, &pd, - &a, &ruleset, inp); + } else if (s == NULL) { + /* Validate remote SYN|ACK, re-create original SYN if + * valid. */ + if ((pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK|TH_RST)) == + TH_ACK && pf_syncookie_validate(&pd) && + pd.dir == PF_IN) { + struct mbuf *msyn; + + msyn = pf_syncookie_recreate_syn(h->ip6_hlim, + off, &pd); + if (msyn == NULL) { + action = PF_DROP; + break; + } + + action = pf_test6(dir, pflags, ifp, &msyn, inp, + &pd.act); + m_freem(msyn); + if (action != PF_PASS) + break; + + action = pf_test_state_tcp(&s, kif, m, off, h, + &pd, &reason); + if (action != PF_PASS || s == NULL) { + action = PF_DROP; + break; + } + + s->src.seqhi = ntohl(pd.hdr.tcp.th_ack) - 1; + s->src.seqlo = ntohl(pd.hdr.tcp.th_seq) - 1; + pf_set_protostate(s, PF_PEER_SRC, PF_TCPS_PROXY_DST); + + action = pf_synproxy(&pd, &s, &reason); + break; + } else { + action = pf_test_rule(&r, &s, kif, m, off, &pd, + &a, &ruleset, inp); + } + } break; }