svn commit: r324376 - head/tests/sys/netpfil/pf

Kristof Provost kp at FreeBSD.org
Fri Oct 6 20:51:34 UTC 2017


Author: kp
Date: Fri Oct  6 20:51:32 2017
New Revision: 324376
URL: https://svnweb.freebsd.org/changeset/base/324376

Log:
  pf: Very basic forwarding test
  
  This test illustrates the use of scapy to test pf.
  
  Differential Revision:	https://reviews.freebsd.org/D12581

Added:
  head/tests/sys/netpfil/pf/forward.sh   (contents, props changed)
  head/tests/sys/netpfil/pf/pft_ping.py   (contents, props changed)
Modified:
  head/tests/sys/netpfil/pf/Makefile
  head/tests/sys/netpfil/pf/utils.subr

Modified: head/tests/sys/netpfil/pf/Makefile
==============================================================================
--- head/tests/sys/netpfil/pf/Makefile	Fri Oct  6 20:43:14 2017	(r324375)
+++ head/tests/sys/netpfil/pf/Makefile	Fri Oct  6 20:51:32 2017	(r324376)
@@ -4,8 +4,12 @@ PACKAGE=	tests
 
 TESTSDIR=       ${TESTSBASE}/sys/netpfil/pf
 
-ATF_TESTS_SH+=	pass_block
+ATF_TESTS_SH+=	pass_block \
+		forward
 
-${PACKAGE}FILES+=	utils.subr
+${PACKAGE}FILES+=	utils.subr \
+			pft_ping.py
+
+${PACKAGE}FILESMODE_pft_ping.py=	0555
 
 .include <bsd.test.mk>

Added: head/tests/sys/netpfil/pf/forward.sh
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tests/sys/netpfil/pf/forward.sh	Fri Oct  6 20:51:32 2017	(r324376)
@@ -0,0 +1,67 @@
+# $FreeBSD$
+
+. $(atf_get_srcdir)/utils.subr
+
+atf_test_case "v4" "cleanup"
+v4_head()
+{
+	atf_set descr 'Basic forwarding test'
+	atf_set require.user root
+
+	# We need scapy to be installed for out test scripts to work
+	atf_set require.progs scapy
+}
+
+v4_body()
+{
+	pft_init
+
+	epair_send=$(pft_mkepair)
+	ifconfig ${epair_send}a 192.0.2.1/24 up
+
+	epair_recv=$(pft_mkepair)
+	ifconfig ${epair_recv}a up
+
+	pft_mkjail alcatraz ${epair_send}b ${epair_recv}b
+	jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up
+	jexec alcatraz ifconfig ${epair_recv}b 198.51.100.2/24 up
+	jexec alcatraz sysctl net.inet.ip.forwarding=1
+	jexec alcatraz arp -s 198.51.100.3 00:01:02:03:04:05
+	route add -net 198.51.100.0/24 192.0.2.2
+
+	# Sanity check, can we forward ICMP echo requests without pf?
+	atf_check -s exit:0 $(atf_get_srcdir)/pft_ping.py \
+		--sendif ${epair_send}a \
+		--to 198.51.100.3 \
+		--recvif ${epair_recv}a
+
+	# Forward with pf enabled
+	printf "block in\n" | jexec alcatraz pfctl -ef -
+	atf_check -s exit:1 $(atf_get_srcdir)/pft_ping.py \
+		--sendif ${epair_send}a \
+		--to 198.51.100.3 \
+		--recvif ${epair_recv}a
+
+	printf "block out\n" | jexec alcatraz pfctl -f -
+	atf_check -s exit:1 $(atf_get_srcdir)/pft_ping.py \
+		--sendif ${epair_send}a \
+		--to 198.51.100.3 \
+		--recv ${epair_recv}a
+
+	# Allow ICMP
+	printf "block in\npass in proto icmp\n" | jexec alcatraz pfctl -f -
+	atf_check -s exit:0 $(atf_get_srcdir)/pft_ping.py \
+		--sendif ${epair_send}a \
+		--to 198.51.100.3 \
+		--recvif ${epair_recv}a
+}
+
+v4_cleanup()
+{
+	pft_cleanup
+}
+
+atf_init_test_cases()
+{
+	atf_add_test_case "v4"
+}

Added: head/tests/sys/netpfil/pf/pft_ping.py
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tests/sys/netpfil/pf/pft_ping.py	Fri Oct  6 20:51:32 2017	(r324376)
@@ -0,0 +1,83 @@
+#!/usr/local/bin/python2.7
+
+import argparse
+import scapy.all as sp
+import sys
+import threading
+
+PAYLOAD_MAGIC = 0x42c0ffee
+
+class Sniffer(threading.Thread):
+	def __init__(self, recvif):
+		threading.Thread.__init__(self)
+
+		self._recvif = recvif
+
+		self.start()
+
+	def run(self):
+		self.packets = sp.sniff(iface=self._recvif, timeout=3)
+
+def check_ping_request(packet, dst_ip):
+	"""
+	Verify that the packet matches what we'd have sent
+	"""
+	ip = packet.getlayer(sp.IP)
+	if not ip:
+		return False
+	if ip.dst != dst_ip:
+		return False
+
+	icmp = packet.getlayer(sp.ICMP)
+	if not icmp:
+		return False
+	if sp.icmptypes[icmp.type] != 'echo-request':
+		return False
+
+	raw = packet.getlayer(sp.Raw)
+	if not raw:
+		return False
+	if raw.load != str(PAYLOAD_MAGIC):
+		return False
+
+	return True
+
+def ping(send_if, dst_ip):
+	req = sp.Ether() \
+		/ sp.IP(dst=dst_ip) \
+		/ sp.ICMP(type='echo-request') \
+		/ sp.Raw(PAYLOAD_MAGIC)
+	sp.sendp(req, iface=send_if, verbose=False)
+
+def main():
+	parser = argparse.ArgumentParser("pft_ping.py",
+		description="Ping test tool")
+	parser.add_argument('--sendif', nargs=1,
+		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 response')
+	parser.add_argument('--to', nargs=1,
+		required=True,
+		help='The destination IP address for the ICMP echo request')
+
+	args = parser.parse_args()
+
+	sniffer = None
+	if not args.recvif is None:
+		sniffer = Sniffer(args.recvif[0])
+
+	ping(args.sendif[0], args.to[0])
+
+	if sniffer:
+		sniffer.join()
+
+		for packet in sniffer.packets:
+			if check_ping_request(packet, args.to[0]):
+				sys.exit(0)
+
+		# We did not get the packet we expected
+		sys.exit(1)
+
+if __name__ == '__main__':
+	main()

Modified: head/tests/sys/netpfil/pf/utils.subr
==============================================================================
--- head/tests/sys/netpfil/pf/utils.subr	Fri Oct  6 20:43:14 2017	(r324375)
+++ head/tests/sys/netpfil/pf/utils.subr	Fri Oct  6 20:51:32 2017	(r324376)
@@ -23,8 +23,14 @@ pft_mkepair()
 pft_mkjail()
 {
 	jailname=$1
-	ifname=$2
-	jail -c name=${jailname} persist vnet vnet.interface=${ifname}
+	shift
+
+	vnet_interfaces=
+	for ifname in $@
+	do
+		vnet_interfaces="${vnet_interfaces} vnet.interface=${ifname}"
+	done
+	jail -c name=${jailname} persist vnet ${vnet_interfaces}
 
 	echo $jailname >> created_jails.lst
 }


More information about the svn-src-all mailing list