From owner-dev-commits-src-branches@freebsd.org Tue Feb 23 11:50:40 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id E3838540160; Tue, 23 Feb 2021 11:50:40 +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 4DlHS05t6Qz4rvS; Tue, 23 Feb 2021 11:50:40 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 A5E5618D09; Tue, 23 Feb 2021 11:50:40 +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 11NBoedY054587; Tue, 23 Feb 2021 11:50:40 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 11NBoe3Z054586; Tue, 23 Feb 2021 11:50:40 GMT (envelope-from git) Date: Tue, 23 Feb 2021 11:50:40 GMT Message-Id: <202102231150.11NBoe3Z054586@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: 04535d6a572a - stable/13 - pf tests: Test unicast reverse path forwarding check 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/13 X-Git-Reftype: branch X-Git-Commit: 04535d6a572ac63b448a5def4525947bd00d9f8a Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Feb 2021 11:50:41 -0000 The branch stable/13 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=04535d6a572ac63b448a5def4525947bd00d9f8a commit 04535d6a572ac63b448a5def4525947bd00d9f8a Author: Kristof Provost AuthorDate: 2021-02-15 21:16:36 +0000 Commit: Kristof Provost CommitDate: 2021-02-23 11:46:25 +0000 pf tests: Test unicast reverse path forwarding check Ensure that pf's urpf-failed keyword works as expected. PR: 253479 MFC after: 1 week Reviewed by: melifaro@ Differential Revision: https://reviews.freebsd.org/D28694 (cherry picked from commit 6b52139eb8e8eda0ea263b24735556194f918642) --- tests/sys/netpfil/common/pft_ping.py | 52 ++++++++++++++++++++++++++++ tests/sys/netpfil/pf/pass_block.sh | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/tests/sys/netpfil/common/pft_ping.py b/tests/sys/netpfil/common/pft_ping.py index 812250803309..957123e4f6f8 100644 --- a/tests/sys/netpfil/common/pft_ping.py +++ b/tests/sys/netpfil/common/pft_ping.py @@ -115,6 +115,35 @@ def check_ping6_request(args, packet): return True +def check_ping_reply(args, packet): + return check_ping4_reply(args, packet) + +def check_ping4_reply(args, packet): + """ + Check that this is a reply to the ping request we sent + """ + dst_ip = args.to[0] + + ip = packet.getlayer(sp.IP) + if not ip: + return False + if ip.src != dst_ip: + return False + + icmp = packet.getlayer(sp.ICMP) + if not icmp: + return False + if sp.icmptypes[icmp.type] != 'echo-reply': + return False + + raw = packet.getlayer(sp.Raw) + if not raw: + return False + if raw.load != PAYLOAD_MAGIC: + return False + + return True + def ping(send_if, dst_ip, args): ether = sp.Ether() ip = sp.IP(dst=dst_ip) @@ -124,6 +153,9 @@ def ping(send_if, dst_ip, args): if args.send_tos: ip.tos = int(args.send_tos[0]) + if args.fromaddr: + ip.src = args.fromaddr[0] + req = ether / ip / icmp / raw sp.sendp(req, iface=send_if, verbose=False) @@ -132,6 +164,9 @@ def ping6(send_if, dst_ip, args): ip6 = sp.IPv6(dst=dst_ip) icmp = sp.ICMPv6EchoRequest(data=sp.raw(PAYLOAD_MAGIC)) + if args.fromaddr: + ip.src = args.fromaddr[0] + req = ether / ip6 / icmp sp.sendp(req, iface=send_if, verbose=False) @@ -189,6 +224,8 @@ def main(): required=True, help='The interface through which the packet(s) will be sent') parser.add_argument('--recvif', nargs=1, + help='The interface on which to expect the ICMP echo request') + parser.add_argument('--replyif', nargs=1, help='The interface on which to expect the ICMP echo response') parser.add_argument('--checkdup', nargs=1, help='The interface on which to expect the duplicated ICMP packets') @@ -197,6 +234,8 @@ def main(): parser.add_argument('--to', nargs=1, required=True, help='The destination IP address for the ICMP echo request') + parser.add_argument('--fromaddr', nargs=1, + help='The source IP address for the ICMP echo request') # TCP options parser.add_argument('--tcpsyn', action='store_true', @@ -225,6 +264,11 @@ def main(): sniffer = Sniffer(args, checkfn) + replysniffer = None + if not args.replyif is None: + checkfn=check_ping_reply + replysniffer = Sniffer(args, checkfn, recvif=args.replyif[0]) + dupsniffer = None if args.checkdup is not None: dupsniffer = Sniffer(args, check_dup, recvif=args.checkdup[0]) @@ -250,5 +294,13 @@ def main(): else: sys.exit(1) + if replysniffer: + replysniffer.join() + + if replysniffer.foundCorrectPacket: + sys.exit(0) + else: + sys.exit(1) + if __name__ == '__main__': main() diff --git a/tests/sys/netpfil/pf/pass_block.sh b/tests/sys/netpfil/pf/pass_block.sh index 139adb43bddd..589b89891729 100644 --- a/tests/sys/netpfil/pf/pass_block.sh +++ b/tests/sys/netpfil/pf/pass_block.sh @@ -27,6 +27,8 @@ . $(atf_get_srcdir)/utils.subr +common_dir=$(atf_get_srcdir)/../common + atf_test_case "v4" "cleanup" v4_head() { @@ -189,10 +191,75 @@ nested_inline_cleanup() pft_cleanup } +atf_test_case "urpf" "cleanup" +urpf_head() +{ + atf_set descr "Test unicast reverse path forwarding check" + atf_set require.user root + atf_set require.progs scapy +} + +urpf_body() +{ + pft_init + + epair_one=$(vnet_mkepair) + epair_two=$(vnet_mkepair) + + vnet_mkjail alcatraz ${epair_one}b ${epair_two}b + + ifconfig ${epair_one}a 192.0.2.2/24 up + ifconfig ${epair_two}a 198.51.100.2/24 up + + jexec alcatraz ifconfig ${epair_one}b 192.0.2.1/24 up + jexec alcatraz ifconfig ${epair_two}b 198.51.100.1/24 up + jexec alcatraz sysctl net.inet.ip.forwarding=1 + + # Sanity checks + atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 + atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.1 + atf_check -s exit:0 ${common_dir}/pft_ping.py \ + --sendif ${epair_one}a \ + --to 192.0.2.1 \ + --fromaddr 198.51.100.2 \ + --replyif ${epair_two}a + atf_check -s exit:0 ${common_dir}/pft_ping.py \ + --sendif ${epair_two}a \ + --to 198.51.100.1 \ + --fromaddr 192.0.2.2 \ + --replyif ${epair_one}a + + pft_set_rules alcatraz \ + "block quick from urpf-failed" + jexec alcatraz pfctl -e + + # Correct source still works + atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 + atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.1 + + # Unexpected source interface is blocked + atf_check -s exit:1 ${common_dir}/pft_ping.py \ + --sendif ${epair_one}a \ + --to 192.0.2.1 \ + --fromaddr 198.51.100.2 \ + --replyif ${epair_two}a + atf_check -s exit:1 ${common_dir}/pft_ping.py \ + --sendif ${epair_two}a \ + --to 198.51.100.1 \ + --fromaddr 192.0.2.2 \ + --replyif ${epair_one}a +} + +urpf_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "v4" atf_add_test_case "v6" atf_add_test_case "noalias" atf_add_test_case "nested_inline" + atf_add_test_case "urpf" }