xref: /freebsd/tests/sys/netpfil/pf/syncookie.sh (revision c7046f76)
1# $FreeBSD$
2#
3# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4#
5# Copyright (c) 2021 Modirum MDPay
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27
28. $(atf_get_srcdir)/utils.subr
29
30common_dir=$(atf_get_srcdir)/../common
31
32atf_test_case "basic" "cleanup"
33basic_head()
34{
35	atf_set descr 'Basic syncookie test'
36	atf_set require.user root
37}
38
39basic_body()
40{
41	pft_init
42
43	epair=$(vnet_mkepair)
44
45	vnet_mkjail alcatraz ${epair}b
46	jexec alcatraz ifconfig ${epair}b 192.0.2.1/24 up
47	jexec alcatraz /usr/sbin/inetd -p inetd-alcatraz.pid \
48	    $(atf_get_srcdir)/echo_inetd.conf
49
50	ifconfig ${epair}a 192.0.2.2/24 up
51
52	jexec alcatraz pfctl -e
53	pft_set_rules alcatraz \
54		"set syncookies always" \
55		"pass in" \
56		"pass out"
57
58	# Sanity check
59	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
60
61	reply=$(echo foo | nc -N -w 5 192.0.2.1 7)
62	if [ "${reply}" != "foo" ];
63	then
64		atf_fail "Failed to connect to syncookie protected echo daemon"
65	fi
66}
67
68basic_cleanup()
69{
70	rm -f inetd-alcatraz.pid
71	pft_cleanup
72}
73
74atf_test_case "forward" "cleanup"
75forward_head()
76{
77	atf_set descr 'Syncookies for forwarded hosts'
78	atf_set require.user root
79}
80
81forward_body()
82{
83	pft_init
84
85	epair_in=$(vnet_mkepair)
86	epair_out=$(vnet_mkepair)
87
88	vnet_mkjail fwd ${epair_in}b ${epair_out}a
89	vnet_mkjail srv ${epair_out}b
90
91	jexec fwd ifconfig ${epair_in}b 192.0.2.1/24 up
92	jexec fwd ifconfig ${epair_out}a 198.51.100.1/24 up
93	jexec fwd sysctl net.inet.ip.forwarding=1
94
95	jexec srv ifconfig ${epair_out}b 198.51.100.2/24 up
96	jexec srv route add default 198.51.100.1
97	jexec srv /usr/sbin/inetd -p inetd-alcatraz.pid \
98	    $(atf_get_srcdir)/echo_inetd.conf
99
100	ifconfig ${epair_in}a 192.0.2.2/24 up
101	route add -net 198.51.100.0/24 192.0.2.1
102
103	jexec fwd pfctl -e
104	pft_set_rules fwd \
105		"set syncookies always" \
106		"pass in" \
107		"pass out"
108
109	# Sanity check
110	atf_check -s exit:0 -o ignore ping -c 1 198.51.100.2
111
112	reply=$(echo foo | nc -N -w 5 198.51.100.2 7)
113	if [ "${reply}" != "foo" ];
114	then
115		atf_fail "Failed to connect to syncookie protected echo daemon"
116	fi
117}
118
119forward_cleanup()
120{
121	rm -f inetd-alcatraz.pid
122	pft_cleanup
123}
124
125atf_test_case "nostate" "cleanup"
126nostate_head()
127{
128	atf_set descr 'Ensure that we do not create until SYN|ACK'
129	atf_set require.user root
130	atf_set require.progs scapy
131}
132
133nostate_body()
134{
135	pft_init
136
137	epair=$(vnet_mkepair)
138	ifconfig ${epair}a 192.0.2.2/24 up
139
140	vnet_mkjail alcatraz ${epair}b
141	jexec alcatraz ifconfig ${epair}b 192.0.2.1/24 up
142
143	jexec alcatraz pfctl -e
144	pft_set_rules alcatraz \
145		"set syncookies always" \
146		"pass in" \
147		"pass out"
148
149	# Sanity check
150	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
151
152	# Now syn flood to create many states
153	${common_dir}/pft_synflood.py \
154		--sendif ${epair}a \
155		--to 192.0.2.2 \
156		--count 20
157
158	states=$(jexec alcatraz pfctl -ss | grep tcp)
159	if [ -n "$states" ];
160	then
161		echo "$states"
162		atf_fail "Found unexpected state"
163	fi
164}
165
166nostate_cleanup()
167{
168	pft_cleanup
169}
170
171atf_test_case "adaptive" "cleanup"
172adaptive_head()
173{
174	atf_set descr 'Adaptive mode test'
175	atf_set require.user root
176	atf_set require.progs scapy
177}
178
179adaptive_body()
180{
181	pft_init
182
183	epair=$(vnet_mkepair)
184	ifconfig ${epair}a 192.0.2.2/24 up
185
186	vnet_mkjail alcatraz ${epair}b
187	jexec alcatraz ifconfig ${epair}b 192.0.2.1/24 up
188
189	jexec alcatraz pfctl -e
190	pft_set_rules alcatraz \
191		"set limit states 100" \
192		"set syncookies adaptive (start 10%%, end 5%%)" \
193		"pass in" \
194		"pass out"
195
196	# Sanity check
197	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
198
199	# Now syn flood to create many states
200	${common_dir}/pft_synflood.py \
201		--sendif ${epair}a \
202		--to 192.0.2.2 \
203		--count 100
204
205	# Adaptive mode should kick in and stop us from creating more than
206	# about 10 states
207	states=$(jexec alcatraz pfctl -ss | grep tcp | wc -l)
208	if [ "$states" -gt 20 ];
209	then
210		echo "$states"
211		atf_fail "Found unexpected states"
212	fi
213}
214
215adaptive_cleanup()
216{
217	pft_cleanup
218}
219
220atf_test_case "limits" "cleanup"
221limits_head()
222{
223	atf_set descr 'Ensure limit calculation works for low or high state limits'
224	atf_set require.user root
225}
226
227limits_body()
228{
229	pft_init
230
231	vnet_mkjail alcatraz
232
233	jexec alcatraz pfctl -e
234	pft_set_rules alcatraz \
235		"set limit states 1" \
236		"set syncookies adaptive (start 10%%, end 5%%)" \
237		"pass in" \
238		"pass out"
239
240	pft_set_rules alcatraz \
241		"set limit states 326000000" \
242		"set syncookies adaptive (start 10%%, end 5%%)" \
243		"pass in" \
244		"pass out"
245}
246
247limits_cleanup()
248{
249	pft_cleanup
250}
251
252atf_init_test_cases()
253{
254	atf_add_test_case "basic"
255	atf_add_test_case "forward"
256	atf_add_test_case "nostate"
257	atf_add_test_case "adaptive"
258	atf_add_test_case "limits"
259}
260