xref: /freebsd/tests/sys/netpfil/pf/pass_block.sh (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
1#
2# SPDX-License-Identifier: BSD-2-Clause
3#
4# Copyright (c) 2018 Kristof Provost <kp@FreeBSD.org>
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26
27. $(atf_get_srcdir)/utils.subr
28
29common_dir=$(atf_get_srcdir)/../common
30
31atf_test_case "enable_disable" "cleanup"
32enable_disable_head()
33{
34	atf_set descr 'Test enable/disable'
35	atf_set require.user root
36}
37
38enable_disable_body()
39{
40	pft_init
41
42	j="pass_block:enable_disable"
43
44	vnet_mkjail ${j}
45
46	# Disable when disabled fails
47	atf_check -s exit:1 -e ignore \
48	    jexec ${j} pfctl -d
49
50	# Enable succeeds
51	atf_check -s exit:0 -e ignore \
52	    jexec ${j} pfctl -e
53
54	# Enable when enabled fails
55	atf_check -s exit:1 -e ignore \
56	    jexec ${j} pfctl -e
57
58	# Disable succeeds
59	atf_check -s exit:0 -e ignore \
60	    jexec ${j} pfctl -d
61}
62
63enable_disable_cleanup()
64{
65	pft_cleanup
66}
67
68atf_test_case "v4" "cleanup"
69v4_head()
70{
71	atf_set descr 'Basic pass/block test for IPv4'
72	atf_set require.user root
73}
74
75v4_body()
76{
77	pft_init
78
79	epair=$(vnet_mkepair)
80	ifconfig ${epair}a 192.0.2.1/24 up
81
82	# Set up a simple jail with one interface
83	vnet_mkjail alcatraz ${epair}b
84	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
85
86	# Trivial ping to the jail, without pf
87	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
88
89	# pf without policy will let us ping
90	jexec alcatraz pfctl -e
91	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
92
93	# Block everything
94	pft_set_rules alcatraz "block in"
95	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
96
97	# Block everything but ICMP
98	pft_set_rules alcatraz "block in" "pass in proto icmp"
99	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
100}
101
102v4_cleanup()
103{
104	pft_cleanup
105}
106
107atf_test_case "v6" "cleanup"
108v6_head()
109{
110	atf_set descr 'Basic pass/block test for IPv6'
111	atf_set require.user root
112}
113
114v6_body()
115{
116	pft_init
117
118	epair=$(vnet_mkepair)
119	ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad
120
121	# Set up a simple jail with one interface
122	vnet_mkjail alcatraz ${epair}b
123	jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2/64 up no_dad
124
125	# Trivial ping to the jail, without pf
126	atf_check -s exit:0 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2
127
128	# pf without policy will let us ping
129	jexec alcatraz pfctl -e
130	atf_check -s exit:0 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2
131
132	# Block everything
133	pft_set_rules alcatraz "block in"
134	atf_check -s exit:2 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2
135
136	# Block everything but ICMP
137	pft_set_rules alcatraz "block in" "pass in proto icmp6"
138	atf_check -s exit:0 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2
139
140	# Allowing ICMPv4 does not allow ICMPv6
141	pft_set_rules alcatraz "block in" "pass in proto icmp"
142	atf_check -s exit:2 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2
143}
144
145v6_cleanup()
146{
147	pft_cleanup
148}
149
150atf_test_case "noalias" "cleanup"
151noalias_head()
152{
153	atf_set descr 'Test the :0 noalias option'
154	atf_set require.user root
155}
156
157noalias_body()
158{
159	pft_init
160
161	epair=$(vnet_mkepair)
162	ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad
163
164	vnet_mkjail alcatraz ${epair}b
165	jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2/64 up no_dad
166
167	linklocaladdr=$(jexec alcatraz ifconfig ${epair}b inet6 \
168		| grep %${epair}b \
169		| awk '{ print $2; }' \
170		| cut -d % -f 1)
171
172	# Sanity check
173	atf_check -s exit:0 -o ignore ping -6 -c 3 -W 1 2001:db8:42::2
174	atf_check -s exit:0 -o ignore ping -6 -c 3 -W 1 ${linklocaladdr}%${epair}a
175
176	jexec alcatraz pfctl -e
177	pft_set_rules alcatraz "block out inet6 from (${epair}b:0) to any"
178
179	atf_check -s exit:2 -o ignore ping -6 -c 3 -W 1 2001:db8:42::2
180
181	# We should still be able to ping the link-local address
182	atf_check -s exit:0 -o ignore ping -6 -c 3 -W 1 ${linklocaladdr}%${epair}a
183
184	pft_set_rules alcatraz "block out inet6 from (${epair}b) to any"
185
186	# We cannot ping to the link-local address
187	atf_check -s exit:2 -o ignore ping -6 -c 3 -W 1 ${linklocaladdr}%${epair}a
188}
189
190noalias_cleanup()
191{
192	pft_cleanup
193}
194
195atf_test_case "nested_inline" "cleanup"
196nested_inline_head()
197{
198	atf_set descr "Test nested inline anchors, PR196314"
199	atf_set require.user root
200}
201
202nested_inline_body()
203{
204	pft_init
205
206	epair=$(vnet_mkepair)
207	ifconfig ${epair}a inet 192.0.2.1/24 up
208
209	vnet_mkjail alcatraz ${epair}b
210	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
211
212	jexec alcatraz pfctl -e
213	pft_set_rules alcatraz \
214		"block in" \
215		"anchor \"an1\" {" \
216			"pass in quick proto tcp to port time" \
217			"anchor \"an2\" {" \
218				"pass in quick proto icmp" \
219			"}" \
220		"}"
221
222	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
223}
224
225nested_inline_cleanup()
226{
227	pft_cleanup
228}
229
230atf_test_case "urpf" "cleanup"
231urpf_head()
232{
233	atf_set descr "Test unicast reverse path forwarding check"
234	atf_set require.user root
235	atf_set require.progs scapy
236}
237
238urpf_body()
239{
240	pft_init
241
242	epair_one=$(vnet_mkepair)
243	epair_two=$(vnet_mkepair)
244
245	vnet_mkjail alcatraz ${epair_one}b ${epair_two}b
246
247	ifconfig ${epair_one}a 192.0.2.2/24 up
248	ifconfig ${epair_two}a 198.51.100.2/24 up
249
250	jexec alcatraz ifconfig ${epair_one}b 192.0.2.1/24 up
251	jexec alcatraz ifconfig ${epair_two}b 198.51.100.1/24 up
252	jexec alcatraz sysctl net.inet.ip.forwarding=1
253
254	# Sanity checks
255	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1
256	atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.1
257	atf_check -s exit:0 ${common_dir}/pft_ping.py \
258		--sendif ${epair_one}a \
259		--to 192.0.2.1 \
260		--fromaddr 198.51.100.2 \
261		--replyif ${epair_two}a
262	atf_check -s exit:0 ${common_dir}/pft_ping.py \
263		--sendif ${epair_two}a \
264		--to 198.51.100.1 \
265		--fromaddr 192.0.2.2 \
266		--replyif ${epair_one}a
267
268	pft_set_rules alcatraz \
269		"block quick from urpf-failed" \
270		"set skip on lo"
271	jexec alcatraz pfctl -e
272
273	# Correct source still works
274	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1
275	atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.1
276
277	# Unexpected source interface is blocked
278	atf_check -s exit:1 ${common_dir}/pft_ping.py \
279		--sendif ${epair_one}a \
280		--to 192.0.2.1 \
281		--fromaddr 198.51.100.2 \
282		--replyif ${epair_two}a
283	atf_check -s exit:1 ${common_dir}/pft_ping.py \
284		--sendif ${epair_two}a \
285		--to 198.51.100.1 \
286		--fromaddr 192.0.2.2 \
287		--replyif ${epair_one}a
288}
289
290urpf_cleanup()
291{
292	pft_cleanup
293}
294
295atf_test_case "received_on" "cleanup"
296received_on_head()
297{
298	atf_set descr 'Test received-on filtering'
299	atf_set require.user root
300}
301
302received_on_body()
303{
304	pft_init
305
306	epair_one=$(vnet_mkepair)
307	epair_two=$(vnet_mkepair)
308	epair_route=$(vnet_mkepair)
309
310	vnet_mkjail alcatraz ${epair_one}b ${epair_two}b ${epair_route}a
311	vnet_mkjail srv ${epair_route}b
312
313	ifconfig ${epair_one}a 192.0.2.2/24 up
314	ifconfig ${epair_two}a 198.51.100.2/24 up
315	route add 203.0.113.2 192.0.2.1
316	route add 203.0.113.3 198.51.100.1
317
318	jexec alcatraz ifconfig ${epair_one}b 192.0.2.1/24 up
319	jexec alcatraz ifconfig ${epair_two}b 198.51.100.1/24 up
320	jexec alcatraz ifconfig ${epair_route}a 203.0.113.1/24 up
321	jexec alcatraz sysctl net.inet.ip.forwarding=1
322
323	jexec srv ifconfig ${epair_route}b 203.0.113.2/24 up
324	jexec srv ifconfig ${epair_route}b inet alias 203.0.113.3/24 up
325	jexec srv route add default 203.0.113.1
326
327	# Sanity checks
328	atf_check -s exit:0 -o ignore \
329	    ping -c 1 192.0.2.1
330	atf_check -s exit:0 -o ignore \
331	    ping -c 1 198.51.100.1
332	atf_check -s exit:0 -o ignore \
333	    ping -c 1 203.0.113.2
334	atf_check -s exit:0 -o ignore \
335	    ping -c 1 203.0.113.3
336
337	jexec alcatraz pfctl -e
338	pft_set_rules alcatraz \
339	    "block in" \
340	    "pass received-on ${epair_one}b"
341
342	atf_check -s exit:0 -o ignore \
343	    ping -c 1 192.0.2.1
344	atf_check -s exit:2 -o ignore \
345	    ping -c 1 198.51.100.1
346
347	# And ensure we can check the received-on interface after routing
348	atf_check -s exit:0 -o ignore \
349	    ping -c 1 203.0.113.2
350	atf_check -s exit:2 -o ignore \
351	    ping -c 1 203.0.113.3
352
353	# Now try this with a group instead
354	jexec alcatraz ifconfig ${epair_one}b group test
355	pft_set_rules alcatraz \
356	    "block in" \
357	    "pass received-on test"
358
359	atf_check -s exit:0 -o ignore \
360	    ping -c 1 192.0.2.1
361	atf_check -s exit:2 -o ignore \
362	    ping -c 1 198.51.100.1
363
364	# And ensure we can check the received-on interface after routing
365	atf_check -s exit:0 -o ignore \
366	    ping -c 1 203.0.113.2
367	atf_check -s exit:2 -o ignore \
368	    ping -c 1 203.0.113.3
369}
370
371received_on_cleanup()
372{
373	pft_cleanup
374}
375
376atf_test_case "optimize_any" "cleanup"
377optimize_any_head()
378{
379	atf_set descr 'Test known optimizer bug'
380	atf_set require.user root
381}
382
383optimize_any_body()
384{
385	pft_init
386
387	epair=$(vnet_mkepair)
388
389	vnet_mkjail alcatraz ${epair}a
390
391	ifconfig ${epair}b 192.0.2.2/24 up
392
393	jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up
394
395	# Sanity check
396	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1
397
398	jexec alcatraz pfctl -e
399	pft_set_rules alcatraz \
400	    "block" \
401	    "pass in inet from { any, 192.0.2.3 }"
402
403	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1
404}
405
406optimize_any_cleanup()
407{
408	pft_cleanup
409}
410
411atf_init_test_cases()
412{
413	atf_add_test_case "enable_disable"
414	atf_add_test_case "v4"
415	atf_add_test_case "v6"
416	atf_add_test_case "noalias"
417	atf_add_test_case "nested_inline"
418	atf_add_test_case "urpf"
419	atf_add_test_case "received_on"
420	atf_add_test_case "optimize_any"
421}
422