xref: /freebsd/tests/sys/netpfil/pf/anchor.sh (revision 99560fe98c76371d7f0807c2088c78790ca9f943)
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
29atf_test_case "pr183198" "cleanup"
30pr183198_head()
31{
32	atf_set descr 'Test tables referenced by rules in anchors'
33	atf_set require.user root
34}
35
36pr183198_body()
37{
38	pft_init
39
40	epair=$(vnet_mkepair)
41	vnet_mkjail alcatraz ${epair}b
42	jexec alcatraz pfctl -e
43
44	# Forward with pf enabled
45	pft_set_rules alcatraz  \
46		"table <test> { 10.0.0.1, 10.0.0.2, 10.0.0.3 }" \
47		"block in" \
48		"anchor \"epair\" on ${epair}b { \n\
49			pass in from <test> \n\
50		}"
51
52	atf_check -s exit:0 -o ignore jexec alcatraz pfctl -sr -a '*'
53	atf_check -s exit:0 -o ignore jexec alcatraz pfctl -t test -T show
54}
55
56pr183198_cleanup()
57{
58	pft_cleanup
59}
60
61atf_test_case "pr279225" "cleanup"
62pr279225_head()
63{
64	atf_set descr "Test that we can retrieve longer anchor names, PR 279225"
65	atf_set require.user root
66}
67
68pr279225_body()
69{
70	pft_init
71
72	vnet_mkjail alcatraz
73
74	pft_set_rules alcatraz \
75		"nat-anchor \"appjail-nat/jail/*\" all" \
76		"rdr-anchor \"appjail-rdr/*\" all" \
77		"anchor \"appjail/jail/*\" all"
78
79	atf_check -s exit:0 -o match:"nat-anchor \"appjail-nat/jail/\*\" all \{" \
80		jexec alcatraz pfctl -sn -a "*"
81	atf_check -s exit:0 -o match:"rdr-anchor \"appjail-rdr/\*\" all \{" \
82		jexec alcatraz pfctl -sn -a "*"
83	atf_check -s exit:0 -o match:"anchor \"appjail/jail/\*\" all \{" \
84		jexec alcatraz pfctl -sr -a "*"
85}
86
87pr279225_cleanup()
88{
89	pft_cleanup
90}
91
92atf_test_case "nested_anchor" "cleanup"
93nested_anchor_head()
94{
95	atf_set descr 'Test setting and retrieving nested anchors'
96	atf_set require.user root
97}
98
99nested_anchor_body()
100{
101	pft_init
102
103	epair=$(vnet_mkepair)
104	vnet_mkjail alcatraz ${epair}a
105
106	pft_set_rules alcatraz \
107		"anchor \"foo\" { \n\
108			anchor \"bar\" { \n\
109				pass on ${epair}a \n\
110			} \n\
111		}"
112
113	atf_check -s exit:0 -o inline:"anchor \"foo\" all {
114  anchor \"bar\" all {
115    pass on ${epair}a all flags S/SA keep state
116  }
117}
118" jexec alcatraz pfctl -sr -a "*"
119}
120
121nested_anchor_cleanup()
122{
123	pft_cleanup
124}
125
126atf_test_case "deeply_nested" "cleanup"
127deeply_nested_head()
128{
129	atf_set descr 'Test setting and retrieving deeply nested anchors'
130	atf_set require.user root
131}
132
133deeply_nested_body()
134{
135	pft_init
136
137	epair=$(vnet_mkepair)
138	vnet_mkjail alcatraz ${epair}a
139
140	pft_set_rules alcatraz \
141		"anchor \"foo\" { \n\
142			anchor \"bar\" { \n\
143				anchor \"foobar\" { \n\
144					pass on ${epair}a \n\
145				} \n\
146				anchor \"quux\" { \n\
147					pass on ${epair}a \n\
148				} \n\
149			} \n\
150			anchor \"baz\" { \n\
151				pass on ${epair}a \n\
152			} \n\
153			anchor \"qux\" { \n\
154				pass on ${epair}a \n\
155			} \n\
156		}"
157
158	atf_check -s exit:0 -o \
159	    inline:"  foo\n  foo/bar\n  foo/bar/foobar\n  foo/bar/quux\n  foo/baz\n  foo/qux\n" \
160	    jexec alcatraz pfctl -sA
161
162	atf_check -s exit:0 -o inline:"  foo/bar/foobar\n  foo/bar/quux\n" \
163	    jexec alcatraz pfctl -a foo/bar -sA
164}
165
166deeply_nested_cleanup()
167{
168	pft_cleanup
169}
170
171atf_test_case "wildcard" "cleanup"
172wildcard_head()
173{
174	atf_set descr 'Test wildcard anchors for functionality'
175	atf_set require.user root
176}
177
178wildcard_body()
179{
180	pft_init
181
182	epair=$(vnet_mkepair)
183	vnet_mkjail alcatraz ${epair}a
184
185	ifconfig ${epair}b 192.0.2.2/24 up
186	jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up
187
188	# Sanity check
189	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
190
191	jexec alcatraz pfctl -e
192	pft_set_rules alcatraz \
193		"block" \
194		"anchor \"foo/*\""
195
196	atf_check -s exit:2 -o ignore ping -c 1 192.0.2.1
197
198	echo "pass" | jexec alcatraz pfctl -g -f - -a "foo/bar"
199
200	jexec alcatraz pfctl -sr -a "*"
201	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
202}
203
204wildcard_cleanup()
205{
206	pft_cleanup
207}
208
209atf_test_case "nested_label" "cleanup"
210nested_label_head()
211{
212	atf_set descr "Test recursive listing of labels"
213	atf_set require.user root
214}
215
216nested_label_body()
217{
218	pft_init
219
220	vnet_mkjail alcatraz
221
222	pft_set_rules alcatraz \
223		"anchor \"foo\" { \n\
224			pass in quick proto icmp label \"passicmp\"\n\
225			anchor \"bar\" { \n\
226				pass in proto tcp label \"passtcp\"\n\
227			} \n\
228		}" \
229		"pass quick from any to any label \"anytoany\""
230
231	atf_check -s exit:0 \
232	    -o inline:"passicmp 0 0 0 0 0 0 0 0
233passtcp 0 0 0 0 0 0 0 0
234anytoany 0 0 0 0 0 0 0 0
235" jexec alcatraz pfctl -sl -a*
236}
237
238nested_label_cleanup()
239{
240	pft_cleanup
241}
242
243atf_test_case "quick" "cleanup"
244quick_head()
245{
246	atf_set descr "Test handling of quick on anchors"
247	atf_set require.user root
248}
249
250quick_body()
251{
252	pft_init
253
254	epair=$(vnet_mkepair)
255	vnet_mkjail alcatraz ${epair}a
256
257	ifconfig ${epair}b 192.0.2.2/24 up
258	jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up
259
260	# Sanity check
261	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
262
263	jexec alcatraz pfctl -e
264	pft_set_rules alcatraz \
265	    "anchor quick {\n\
266	        pass\n\
267	    }" \
268	    "block"
269
270	# We can still ping because the anchor is 'quick'
271	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
272	jexec alcatraz pfctl -sr -v
273	jexec alcatraz pfctl -ss -v
274}
275
276quick_cleanup()
277{
278	pft_cleanup
279}
280
281atf_test_case "quick_nested" "cleanup"
282quick_nested_head()
283{
284	atf_set descr 'Verify that a nested anchor does not clear quick'
285	atf_set require.user root
286}
287
288quick_nested_body()
289{
290	pft_init
291
292	epair=$(vnet_mkepair)
293	vnet_mkjail alcatraz ${epair}a
294
295	ifconfig ${epair}b 192.0.2.2/24 up
296	jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up
297
298	# Sanity check
299	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
300
301	jexec alcatraz pfctl -e
302	pft_set_rules alcatraz \
303	    "anchor quick {\n\
304	        pass\n\
305	        anchor {\n\
306	            block proto tcp\n\
307	        }\n\
308	    }" \
309	    "block"
310	ping -c 1 192.0.2.1
311
312	jexec alcatraz pfctl -sr -v
313	jexec alcatraz pfctl -ss -v
314
315	# We can still ping because the anchor is 'quick'
316	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
317	jexec alcatraz pfctl -sr -v
318	jexec alcatraz pfctl -ss -v
319}
320
321quick_nested_cleanup()
322{
323	pft_cleanup
324}
325
326atf_test_case "counter" "cleanup"
327counter_head()
328{
329	atf_set descr 'Test counters on anchors'
330	atf_set require.user root
331}
332
333counter_body()
334{
335	pft_init
336
337	epair=$(vnet_mkepair)
338	vnet_mkjail alcatraz ${epair}a
339
340	ifconfig ${epair}b 192.0.2.2/24 up
341	jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up
342
343	# Sanity check
344	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
345
346	jexec alcatraz pfctl -e
347	pft_set_rules alcatraz \
348	    "anchor \"foo\" {\n\
349	        pass\n\
350	    }"
351
352	# Generate traffic
353	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
354	atf_check -s exit:0 -e ignore \
355	    -o match:'[ Evaluations: 1         Packets: 2         Bytes: 168         States: 1     ]' \
356	    jexec alcatraz pfctl -sr -vv
357}
358
359counter_cleanup()
360{
361	pft_cleanup
362}
363
364atf_test_case "nat" "cleanup"
365nat_head()
366{
367	atf_set descr 'Test nested nat anchors'
368	atf_set require.user root
369}
370
371nat_body()
372{
373	pft_init
374
375	epair=$(vnet_mkepair)
376	vnet_mkjail alcatraz ${epair}a
377
378	ifconfig ${epair}b 192.0.2.2/24 up
379	jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up
380
381	# Sanity check
382	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
383
384	jexec alcatraz pfctl -e
385	pft_set_rules alcatraz \
386	    "nat-anchor \"foo/*\"" \
387	    "pass"
388
389	echo "nat log on ${epair}a inet from 192.0.2.0/24 to any port = 53 -> 192.0.2.1" \
390	    | jexec alcatraz pfctl -a "foo/bar" -g -f -
391	echo "rdr on ${epair}a proto tcp to port echo -> 127.0.0.1 port echo" \
392	    | jexec alcatraz pfctl -a "foo/baz" -g -f -
393
394	jexec alcatraz pfctl -sn -a "*"
395	jexec alcatraz pfctl -sn -a "foo/bar"
396	jexec alcatraz pfctl -sn -a "foo/baz"
397
398	atf_check -s exit:0 -o match:"nat log on ${epair}a inet from 192.0.2.0/24 to any port = domain -> 192.0.2.1" \
399	    jexec alcatraz pfctl -sn -a "*"
400	atf_check -s exit:0 -o match:"rdr on ${epair}a inet proto tcp from any to any port = echo -> 127.0.0.1 port 7" \
401	    jexec alcatraz pfctl -sn -a "*"
402}
403
404nat_cleanup()
405{
406	pft_cleanup
407}
408
409atf_test_case "include" "cleanup"
410include_head()
411{
412	atf_set descr 'Test including inside anchors'
413	atf_set require.user root
414}
415
416include_body()
417{
418	pft_init
419
420	wd=`pwd`
421
422	epair=$(vnet_mkepair)
423	vnet_mkjail alcatraz ${epair}a
424
425	ifconfig ${epair}b 192.0.2.2/24 up
426	jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up
427
428	# Sanity check
429	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
430
431	echo "pass" > ${wd}/extra.conf
432	jexec alcatraz pfctl -e
433	pft_set_rules alcatraz \
434	    "block" \
435	    "anchor \"foo\" {\n\
436	        include \"${wd}/extra.conf\"\n\
437	    }"
438
439	jexec alcatraz pfctl -sr
440
441	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
442}
443
444include_cleanup()
445{
446	pft_cleanup
447}
448
449atf_test_case "quick" "cleanup"
450quick_head()
451{
452	atf_set descr 'Test quick on anchors'
453	atf_set require.user root
454}
455
456quick_body()
457{
458	pft_init
459
460	epair=$(vnet_mkepair)
461	vnet_mkjail alcatraz ${epair}a
462
463	ifconfig ${epair}b 192.0.2.2/24 up
464	jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up
465
466	# Sanity check
467	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
468
469	jexec alcatraz pfctl -e
470	pft_set_rules alcatraz \
471	    "anchor quick {\n\
472	        pass\n\
473	    }" \
474	    "block"
475
476	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
477	jexec alcatraz pfctl -sr -vv -a "*"
478}
479
480quick_cleanup()
481{
482	pft_cleanup
483}
484
485atf_test_case "recursive_flush" "cleanup"
486recursive_flush_head()
487{
488	atf_set descr 'Test recursive flushing of rules'
489	atf_set require.user root
490}
491
492recursive_flush_body()
493{
494	pft_init
495
496	epair=$(vnet_mkepair)
497	vnet_mkjail alcatraz ${epair}a
498
499	ifconfig ${epair}b 192.0.2.2/24 up
500	jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up
501
502	# Sanity check
503	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
504
505	jexec alcatraz pfctl -e
506	pft_set_rules alcatraz \
507	    "block" \
508	    "anchor \"foo\" {\n\
509	        pass\n\
510	    }"
511
512	# We can ping thanks to the pass rule in foo
513	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
514
515	# Only reset the main rules. I.e. not a recursive flush
516	pft_set_rules alcatraz \
517	    "block" \
518	    "anchor \"foo\""
519
520	# "foo" still has the pass rule, so this works
521	jexec alcatraz pfctl -a "*" -sr
522	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
523
524	# Now do a recursive flush
525	atf_check -s exit:0 -e ignore -o ignore \
526	    jexec alcatraz pfctl -a "*" -Fr
527	pft_set_rules alcatraz \
528	    "block" \
529	    "anchor \"foo\""
530
531	# So this fails
532	jexec alcatraz pfctl -a "*" -sr
533	atf_check -s exit:2 -o ignore ping -c 1 192.0.2.1
534}
535
536recursive_flush_cleanup()
537{
538	pft_cleanup
539}
540
541atf_init_test_cases()
542{
543	atf_add_test_case "pr183198"
544	atf_add_test_case "pr279225"
545	atf_add_test_case "nested_anchor"
546	atf_add_test_case "deeply_nested"
547	atf_add_test_case "wildcard"
548	atf_add_test_case "nested_label"
549	atf_add_test_case "quick"
550	atf_add_test_case "quick_nested"
551	atf_add_test_case "counter"
552	atf_add_test_case "nat"
553	atf_add_test_case "include"
554	atf_add_test_case "quick"
555	atf_add_test_case "recursive_flush"
556}
557