From nobody Mon Jan 29 13:52:42 2024 X-Original-To: dev-commits-src-main@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 4TNqVz2JVwz58lN6; Mon, 29 Jan 2024 13:52:43 +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 4TNqVz0nKmz4MLd; Mon, 29 Jan 2024 13:52:43 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1706536363; 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=nL+IORLsEmj27omocAzjzvbbtsXRK/tRk+Ib+u+J+64=; b=ZgckFfnOguqH8Oooo8M54RRDM1LInJalh4q3gZrpLeB8GlPq2691cgRMy5dsVvaTrZ7HM+ yGQRn46g4EgHWt7o1vt9kGxfY8UBNDv+UT1FAKYb44eLUJA+OZEp5ux55+ttGZNIGVOyzx zYySVVMLbGcIuq7guykktRfR9LRBW1YYGWqDtYJV5CE1m876mDGOh+GvTPsNKjeQ2h4Mbb wYq4hOSV4Z3fEWi6JBKtNr7c3k8hWEhIqG/Cwe6QM3k+LIQr8637wUZQR5qmFjcfQVbKKx kdw+S3itcxt+9iHl2ohfRwtbZuXpoBvwHOkdZj408r4WqDr/ZyArKV8DlI3l8Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1706536363; 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=nL+IORLsEmj27omocAzjzvbbtsXRK/tRk+Ib+u+J+64=; b=Im6P8SuZdHnLl489ovfQ58Vndcwk4zXXQiAwRE66zr0atFSniVc04bSUxNiffnjh4w2QLR 0x3ZwTmZwAXvabUKOjHqtTmAapkYv2wxetbXBjlv+VJQVG1WAQ0fwRVZo6DNt+XI8GxZAl wNV4v1RnRZxIpoIAcEaN9UT+hy5RCIfT9O1a5ovoP8I2LyoNQA5VAT443/lVkMskT08Bqi s9DWP8rEDNcRHNmp+uPfIh2eyWUN+DizAvpPgccRNdb02Xh+eqwIO9B9Vyr4Nx3DguHw+Q zTV9/ICxHc0iwYtMVPqU5z/F+N31NwAGLtK3WB1lx29uqSk2EGDinH/vAD06HQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1706536363; a=rsa-sha256; cv=none; b=XxebXl2VxepmHODCZ787rNt6hdb5B86aveXG2RayVhDk03YxCtScYJaj2ciAYV56Uv53a0 6vbOF5HSMF0OG/SeDapU+73sTPboXNLvI9Pucpg/IJ5Q3lOwxPVC3X3iO/Sli/D7J9oGDt B2X/qJq36eZJyBt4G1wiVNkSoyQNhdnA9Y2Yt2UxX/zJFVBVaYi18SyJhAw9SEncs5SQWD POf/SiO9t4mAGh+n47fgOQcYIIbD/Gp+TCo/No7OqYBYrKPiZRHBAwhBOBtk7TLulTfKAU I+jAu1+C95knDAoO6pvCMnDMPKFb4lrz9X9hovB5X72TGpio+Oaftws1BaCidQ== 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 4TNqVy701Xztdy; Mon, 29 Jan 2024 13:52:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 40TDqgWA033627; Mon, 29 Jan 2024 13:52:42 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 40TDqgSi033624; Mon, 29 Jan 2024 13:52:42 GMT (envelope-from git) Date: Mon, 29 Jan 2024 13:52:42 GMT Message-Id: <202401291352.40TDqgSi033624@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: 31828075e456 - main - pf: bind route-to states to their route-to interface List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@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/main X-Git-Reftype: branch X-Git-Commit: 31828075e456c042cabd47ff4eb127c5c19f16e0 Auto-Submitted: auto-generated The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=31828075e456c042cabd47ff4eb127c5c19f16e0 commit 31828075e456c042cabd47ff4eb127c5c19f16e0 Author: Kristof Provost AuthorDate: 2024-01-25 10:16:49 +0000 Commit: Kristof Provost CommitDate: 2024-01-29 13:10:26 +0000 pf: bind route-to states to their route-to interface When we route-to the state should be bound to the route-to interface, not the default route interface. However, we should only do so for outbound traffic, because inbound traffic should bind on the arriving interface, not the one we eventually transmit on. Explicitly check for this in BOUND_IFACE(). We must also extend pf_find_state(), because subsequent packets within the established state will attempt to match the original interface, not the route-to interface. Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D43589 --- sys/netpfil/pf/pf.c | 27 +++++++++++++++++++++---- tests/sys/netpfil/pf/route_to.sh | 43 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 2dc6d02d330a..36ff0eac16ad 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -412,8 +412,27 @@ VNET_DEFINE(struct pf_limit, pf_limits[PF_LIMIT_MAX]); return (PF_PASS); \ } while (0) -#define BOUND_IFACE(r, k) \ - ((r)->rule_flag & PFRULE_IFBOUND) ? (k) : V_pfi_all +static struct pfi_kkif * +BOUND_IFACE(struct pf_krule *r, struct pfi_kkif *k, struct pf_pdesc *pd) +{ + /* Floating unless otherwise specified. */ + if (! (r->rule_flag & PFRULE_IFBOUND)) + return (V_pfi_all); + + /* Don't overrule the interface for states created on incoming packets. */ + if (pd->dir == PF_IN) + return (k); + + /* No route-to, so don't overrrule. */ + if (r->rt != PF_ROUTETO) + return (k); + + if (r->rpool.cur == NULL) + return (k); + + /* Bind to the route-to interface. */ + return (r->rpool.cur->kif); +} #define STATE_INC_COUNTERS(s) \ do { \ @@ -1600,7 +1619,7 @@ pf_find_state(struct pfi_kkif *kif, struct pf_state_key_cmp *key, u_int dir) /* List is sorted, if-bound states before floating ones. */ TAILQ_FOREACH(s, &sk->states[idx], key_list[idx]) - if (s->kif == V_pfi_all || s->kif == kif) { + if (s->kif == V_pfi_all || s->kif == kif || s->orig_kif == kif) { PF_STATE_LOCK(s); PF_HASHROW_UNLOCK(kh); if (__predict_false(s->timeout >= PFTM_MAX)) { @@ -4999,7 +5018,7 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a, __func__, nr, sk, nk)); /* Swap sk/nk for PF_OUT. */ - if (pf_state_insert(BOUND_IFACE(r, kif), kif, + if (pf_state_insert(BOUND_IFACE(r, kif, pd), kif, (pd->dir == PF_IN) ? sk : nk, (pd->dir == PF_IN) ? nk : sk, s)) { REASON_SET(&reason, PFRES_STATEINS); diff --git a/tests/sys/netpfil/pf/route_to.sh b/tests/sys/netpfil/pf/route_to.sh index d8cfb1b22d8b..7e8310bceb30 100644 --- a/tests/sys/netpfil/pf/route_to.sh +++ b/tests/sys/netpfil/pf/route_to.sh @@ -365,6 +365,48 @@ dummynet_cleanup() pft_cleanup } +atf_test_case "ifbound" "cleanup" +ifbound_head() +{ + atf_set descr 'Test that route-to states bind the expected interface' + atf_set require.user root +} + +ifbound_body() +{ + pft_init + + j="route_to:ifbound" + + epair_one=$(vnet_mkepair) + epair_two=$(vnet_mkepair) + ifconfig ${epair_one}b up + + vnet_mkjail ${j}2 ${epair_two}b + jexec ${j}2 ifconfig ${epair_two}b inet 198.51.100.2/24 up + jexec ${j}2 ifconfig ${epair_two}b inet alias 203.0.113.1/24 + jexec ${j}2 route add default 198.51.100.1 + + vnet_mkjail $j ${epair_one}a ${epair_two}a + jexec $j ifconfig ${epair_one}a 192.0.2.1/24 up + jexec $j ifconfig ${epair_two}a 198.51.100.1/24 up + jexec $j route add default 192.0.2.2 + + jexec $j pfctl -e + pft_set_rules $j \ + "set state-policy if-bound" \ + "block" \ + "pass out route-to (${epair_two}a 198.51.100.2)" + + atf_check -s exit:0 -o ignore \ + jexec $j ping -c 3 203.0.113.1 +} + +ifbound_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "v4" @@ -373,4 +415,5 @@ atf_init_test_cases() atf_add_test_case "multiwanlocal" atf_add_test_case "icmp_nat" atf_add_test_case "dummynet" + atf_add_test_case "ifbound" }