diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index f08ef0d0bfa0..bb058c8e8ae6 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -2263,6 +2263,7 @@ int pf_set_syncookies(struct pfioc_nv *); int pf_synflood_check(struct pf_pdesc *); void pf_syncookie_send(struct mbuf *m, int off, struct pf_pdesc *); +bool pf_syncookie_check(struct pf_pdesc *); u_int8_t pf_syncookie_validate(struct pf_pdesc *); struct mbuf * pf_syncookie_recreate_syn(uint8_t, int, struct pf_pdesc *); diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index c0c34fba0409..ca08023ea05d 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -5446,9 +5446,11 @@ pf_test_state_tcp(struct pf_kstate **state, int direction, struct pfi_kkif *kif, if ((action = pf_synproxy(pd, state, reason)) != PF_PASS) return (action); - if (((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) && - dst->state >= TCPS_FIN_WAIT_2 && - src->state >= TCPS_FIN_WAIT_2) { + if (dst->state >= TCPS_FIN_WAIT_2 && + src->state >= TCPS_FIN_WAIT_2 && + (((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) || + ((th->th_flags & (TH_SYN|TH_ACK|TH_RST)) == TH_ACK && + pf_syncookie_check(pd) && pd->dir == PF_IN))) { if (V_pf_status.debug >= PF_DEBUG_MISC) { printf("pf: state reuse "); pf_print_state(*state); diff --git a/sys/netpfil/pf/pf_syncookies.c b/sys/netpfil/pf/pf_syncookies.c index 0c9b5a459301..db232579d595 100644 --- a/sys/netpfil/pf/pf_syncookies.c +++ b/sys/netpfil/pf/pf_syncookies.c @@ -301,8 +301,8 @@ pf_syncookie_send(struct mbuf *m, int off, struct pf_pdesc *pd) 1); } -uint8_t -pf_syncookie_validate(struct pf_pdesc *pd) +bool +pf_syncookie_check(struct pf_pdesc *pd) { uint32_t hash, ack, seq; union pf_syncookie cookie; @@ -315,14 +315,29 @@ pf_syncookie_validate(struct pf_pdesc *pd) cookie.cookie = (ack & 0xff) ^ (ack >> 24); /* we don't know oddeven before setting the cookie (union) */ - if (atomic_load_64(&V_pf_status.syncookies_inflight[cookie.flags.oddeven]) + if (atomic_load_64(&V_pf_status.syncookies_inflight[cookie.flags.oddeven]) == 0) - return (0); + return (0); hash = pf_syncookie_mac(pd, cookie, seq); if ((ack & ~0xff) != (hash & ~0xff)) + return (false); + + return (true); +} + +uint8_t +pf_syncookie_validate(struct pf_pdesc *pd) +{ + uint32_t ack; + union pf_syncookie cookie; + + if (! pf_syncookie_check(pd)) return (0); + ack = ntohl(pd->hdr.tcp.th_ack) - 1; + cookie.cookie = (ack & 0xff) ^ (ack >> 24); + counter_u64_add(V_pf_status.lcounters[KLCNT_SYNCOOKIES_VALID], 1); atomic_add_64(&V_pf_status.syncookies_inflight[cookie.flags.oddeven], -1);