From nobody Sat Jan 28 01:39:21 2023 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4P3cYj6rvMz3bq1d; Sat, 28 Jan 2023 01:39:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4P3cYj67wdz3nLY; Sat, 28 Jan 2023 01:39:21 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1674869961; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=fSlufBwxsuKabZ3LJ7+ezW56RzxNuxdP2qFz7mEyk14=; b=n3A5IzkCIwyBgH6FGWupaWTM1sFIoxQtU4WYzyancMa+ojO9yTiQyrc7jo8kfqEf3GoW2u klhaoXAARb/q9tvlYQ7+bb5/4CGx3JqohG2bfDaEklVvlK0UgtjaIbqyy3UbFr3TJHvXq3 0UnJ21IpETClZfhHrjSUVd3aV3KiGzcAQeZzKyt3gnurL+e+xTQGfFSAUYlMKgyhPqwmt3 A4k53q5AcklqlINFLcVtdLKSrWgJuqZpnDXVw9mpEW3qENpbjNXUtnnRcUfabFzoihl6qA rKjncv1KnupKIHBDkK0Kir6To66C5mNKEYIZtp17gVjfFBYAc4jQXXMEhVvuMw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1674869961; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=fSlufBwxsuKabZ3LJ7+ezW56RzxNuxdP2qFz7mEyk14=; b=iYLCXuiCmyfF+N8/vqTUsdvh2Z/1NOMMF0my86a4SW/trHdZJkmUODxy9AInEmP3v2OdrK vlHQkpbNJF2IafbQ7ssHqhtm1z0YiFL7MxTgU51C/E5NVNRlF7Jb+920wMpqh6Q19/H4jf IGgjx7S24az8wio3I9sFm4eIEIuXEZJP0dmSq6eS/5hSptY4M78ZWWs6aOyEoq/CmufcGh C+rmR1vXodO2eARB3ti+L/hT2no4cINcmqkZkA3kq032xbbmX38SrDyzPq2V8C3N0fDEVj F9PKP4cRF8Qkr9u68eeCRFRnEtOp4cnuqMKdCSQfHFbdO88skKVGhLC3xwMuwg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1674869961; a=rsa-sha256; cv=none; b=dp3mI/U9d8JZnWJHCmDhMwk1Je13hVcEOco1reoJHlFTz/846xGMUkXRTjmrdobGU0SG12 WtLOD71CEaNajgbQ+/ZLBLOLKGPWfD5A18Dg2RtVF9mPZQr6jlTqkFi3qbot1QkFLdBwXT i4989Zgjv3HxltTW+RJwILE2kqEke4eefuJ8hptZ94U/B0JdggSFdX6qbofm+5ftvNQ0LF 1QZnJpq4b0XkkjYvV8hznh9pkjyFaCc1p7kCny2FZyCjlTw7wIAkD5+PIN72yyqyivxns3 lSKp5U0S9YAylqdyGMWJxTeNDF16P9P8lIT9w2nvhwzCToChwqy8/Uc5H9NCyQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4P3cYj5G0kzWgF; Sat, 28 Jan 2023 01:39:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 30S1dLHJ056051; Sat, 28 Jan 2023 01:39:21 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 30S1dLPi056049; Sat, 28 Jan 2023 01:39:21 GMT (envelope-from git) Date: Sat, 28 Jan 2023 01:39:21 GMT Message-Id: <202301280139.30S1dLPi056049@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kristof Provost Subject: git: 8f22dbcf0f0a - stable/12 - pf: fix syncookies in conjunction with tcp fast port reuse List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/stable/12 X-Git-Reftype: branch X-Git-Commit: 8f22dbcf0f0a34bec704c63393d5245168f4f8ea Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/12 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=8f22dbcf0f0a34bec704c63393d5245168f4f8ea commit 8f22dbcf0f0a34bec704c63393d5245168f4f8ea Author: Kristof Provost AuthorDate: 2022-12-31 14:59:10 +0000 Commit: Kristof Provost CommitDate: 2023-01-27 03:17:06 +0000 pf: fix syncookies in conjunction with tcp fast port reuse Basic scenario: we have a closed connection (In TCPS_FIN_WAIT_2), and get a new connection (i.e. SYN) re-using the tuple. Without syncookies we look at the SYN, and completely unlink the old, closed state on the SYN. With syncookies we send a generated SYN|ACK back, and drop the SYN, never looking at the state table. So when the ACK (i.e. the third step in the three way handshake for connection setup) turns up, we’ve not actually removed the old state, so we find it, and don’t do the syncookie dance, or allow the new connection to get set up. Explicitly check for this in pf_test_state_tcp(). If we find a state in TCPS_FIN_WAIT_2 and the syncookie is valid we delete the existing state so we can set up the new state. Note that when we verify the syncookie in pf_test_state_tcp() we don't decrement the number of half-open connections to avoid an incorrect double decrement. MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D37919 (cherry picked from commit 9c041b450d5e604c3e35b5799b60a2c53795feef) --- sys/net/pfvar.h | 1 + sys/netpfil/pf/pf.c | 8 +++++--- sys/netpfil/pf/pf_syncookies.c | 23 +++++++++++++++++++---- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 8b2be56d86b4..8f09b590d2c9 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -2109,6 +2109,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 0a6928e3d4eb..fbc6c9640f43 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -4990,9 +4990,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 de0f27926a41..a37d846a0f2e 100644 --- a/sys/netpfil/pf/pf_syncookies.c +++ b/sys/netpfil/pf/pf_syncookies.c @@ -300,8 +300,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; @@ -314,14 +314,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);