2 # SPDX-License-Identifier: BSD-2-Clause
4 # Copyright (c) 2021 Modirum MDPay
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
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.
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
27 . $(atf_get_srcdir)/utils.subr
29 common_dir=$(atf_get_srcdir)/../common
35 jexec $jail pfctl -si -v | grep -A 2 '^Syncookies' | grep active \
36 | awk '{ print($2); }'
39 atf_test_case "basic" "cleanup"
42 atf_set descr 'Basic syncookie test'
43 atf_set require.user root
52 vnet_mkjail alcatraz ${epair}b
53 jexec alcatraz ifconfig ${epair}b 192.0.2.1/24 up
54 jexec alcatraz /usr/sbin/inetd -p inetd-alcatraz.pid \
55 $(atf_get_srcdir)/echo_inetd.conf
57 ifconfig ${epair}a 192.0.2.2/24 up
59 jexec alcatraz pfctl -e
60 pft_set_rules alcatraz \
61 "set syncookies always" \
66 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
68 reply=$(echo foo | nc -N -w 5 192.0.2.1 7)
69 if [ "${reply}" != "foo" ];
71 atf_fail "Failed to connect to syncookie protected echo daemon"
74 # Check that status shows syncookies as being active
75 active=$(syncookie_state alcatraz)
76 if [ "$active" != "active" ];
78 atf_fail "syncookies not active"
84 rm -f inetd-alcatraz.pid
88 atf_test_case "basic_v6" "cleanup"
91 atf_set descr 'Basic syncookie IPv6 test'
92 atf_set require.user root
101 vnet_mkjail alcatraz ${epair}b
102 jexec alcatraz ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
103 jexec alcatraz /usr/sbin/inetd -p inetd-alcatraz.pid \
104 $(atf_get_srcdir)/echo_inetd.conf
106 ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
108 jexec alcatraz pfctl -e
109 pft_set_rules alcatraz \
110 "set syncookies always" \
115 atf_check -s exit:0 -o ignore ping6 -c 1 2001:db8::1
117 reply=$(echo foo | nc -N -w 5 2001:db8::1 7)
118 if [ "${reply}" != "foo" ];
120 atf_fail "Failed to connect to syncookie protected echo daemon"
123 # Check that status shows syncookies as being active
124 active=$(syncookie_state alcatraz)
125 if [ "$active" != "active" ];
127 atf_fail "syncookies not active"
133 rm -f inetd-alcatraz.pid
137 atf_test_case "forward" "cleanup"
140 atf_set descr 'Syncookies for forwarded hosts'
141 atf_set require.user root
148 epair_in=$(vnet_mkepair)
149 epair_out=$(vnet_mkepair)
151 vnet_mkjail fwd ${epair_in}b ${epair_out}a
152 vnet_mkjail srv ${epair_out}b
154 jexec fwd ifconfig ${epair_in}b 192.0.2.1/24 up
155 jexec fwd ifconfig ${epair_out}a 198.51.100.1/24 up
156 jexec fwd sysctl net.inet.ip.forwarding=1
158 jexec srv ifconfig ${epair_out}b 198.51.100.2/24 up
159 jexec srv route add default 198.51.100.1
160 jexec srv /usr/sbin/inetd -p inetd-alcatraz.pid \
161 $(atf_get_srcdir)/echo_inetd.conf
163 ifconfig ${epair_in}a 192.0.2.2/24 up
164 route add -net 198.51.100.0/24 192.0.2.1
168 "set syncookies always" \
173 atf_check -s exit:0 -o ignore ping -c 1 198.51.100.2
175 reply=$(echo foo | nc -N -w 5 198.51.100.2 7)
176 if [ "${reply}" != "foo" ];
178 atf_fail "Failed to connect to syncookie protected echo daemon"
184 rm -f inetd-alcatraz.pid
188 atf_test_case "forward_v6" "cleanup"
191 atf_set descr 'Syncookies for forwarded hosts'
192 atf_set require.user root
199 epair_in=$(vnet_mkepair)
200 epair_out=$(vnet_mkepair)
202 vnet_mkjail fwd ${epair_in}b ${epair_out}a
203 vnet_mkjail srv ${epair_out}b
205 jexec fwd ifconfig ${epair_in}b inet6 2001:db8::1/64 up no_dad
206 jexec fwd ifconfig ${epair_out}a inet6 2001:db8:1::1/64 up no_dad
207 jexec fwd sysctl net.inet6.ip6.forwarding=1
209 jexec srv ifconfig ${epair_out}b inet6 2001:db8:1::2/64 up no_dad
210 jexec srv route -6 add default 2001:db8:1::1
211 jexec srv /usr/sbin/inetd -p inetd-alcatraz.pid \
212 $(atf_get_srcdir)/echo_inetd.conf
214 ifconfig ${epair_in}a inet6 2001:db8::2/64 up no_dad
215 route -6 add -net 2001:db8:1::/64 2001:db8::1
219 "set syncookies always" \
224 atf_check -s exit:0 -o ignore ping6 -c 1 2001:db8:1::2
226 reply=$(echo foo | nc -N -w 5 2001:db8:1::2 7)
227 if [ "${reply}" != "foo" ];
229 atf_fail "Failed to connect to syncookie protected echo daemon"
235 rm -f inetd-alcatraz.pid
239 atf_test_case "nostate" "cleanup"
242 atf_set descr 'Ensure that we do not create until SYN|ACK'
243 atf_set require.user root
244 atf_set require.progs scapy
251 epair=$(vnet_mkepair)
252 ifconfig ${epair}a 192.0.2.2/24 up
254 vnet_mkjail alcatraz ${epair}b
255 jexec alcatraz ifconfig ${epair}b 192.0.2.1/24 up
257 jexec alcatraz pfctl -e
258 pft_set_rules alcatraz \
259 "set syncookies always" \
264 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
266 # Now syn flood to create many states
267 ${common_dir}/pft_synflood.py \
272 states=$(jexec alcatraz pfctl -ss | grep tcp)
276 atf_fail "Found unexpected state"
285 atf_test_case "nostate_v6" "cleanup"
288 atf_set descr 'Ensure that we do not create until SYN|ACK'
289 atf_set require.user root
290 atf_set require.progs scapy
297 epair=$(vnet_mkepair)
298 ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
300 vnet_mkjail alcatraz ${epair}b
301 jexec alcatraz ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
303 jexec alcatraz pfctl -e
304 pft_set_rules alcatraz \
305 "set syncookies always" \
310 atf_check -s exit:0 -o ignore ping6 -c 1 2001:db8::1
312 # Now syn flood to create many states
313 ${common_dir}/pft_synflood.py \
319 states=$(jexec alcatraz pfctl -ss | grep tcp)
323 atf_fail "Found unexpected state"
332 atf_test_case "adaptive" "cleanup"
335 atf_set descr 'Adaptive mode test'
336 atf_set require.user root
337 atf_set require.progs scapy
344 epair=$(vnet_mkepair)
345 ifconfig ${epair}a 192.0.2.2/24 up
347 vnet_mkjail alcatraz ${epair}b
348 jexec alcatraz ifconfig ${epair}b 192.0.2.1/24 up
350 jexec alcatraz pfctl -e
351 pft_set_rules alcatraz \
352 "set limit states 100" \
353 "set syncookies adaptive (start 10%%, end 5%%)" \
358 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
360 # Check that status shows syncookies as being inactive
361 active=$(syncookie_state alcatraz)
362 if [ "$active" != "inactive" ];
364 atf_fail "syncookies active when they should not be"
367 # Now syn flood to create many states
368 ${common_dir}/pft_synflood.py \
373 # Check that status shows syncookies as being active
374 active=$(syncookie_state alcatraz)
375 if [ "$active" != "active" ];
377 atf_fail "syncookies not active"
380 # Adaptive mode should kick in and stop us from creating more than
382 states=$(jexec alcatraz pfctl -ss | grep tcp | wc -l)
383 if [ "$states" -gt 20 ];
386 atf_fail "Found unexpected states"
395 atf_test_case "limits" "cleanup"
398 atf_set descr 'Ensure limit calculation works for low or high state limits'
399 atf_set require.user root
408 jexec alcatraz pfctl -e
409 pft_set_rules alcatraz \
410 "set limit states 1" \
411 "set syncookies adaptive (start 10%%, end 5%%)" \
415 pft_set_rules alcatraz \
416 "set limit states 326000000" \
417 "set syncookies adaptive (start 10%%, end 5%%)" \
427 atf_test_case "port_reuse" "cleanup"
430 atf_set descr 'Test rapid port re-use'
431 atf_set require.user root
438 epair=$(vnet_mkepair)
440 vnet_mkjail alcatraz ${epair}b
442 jexec alcatraz ifconfig ${epair}b 192.0.2.1/24 up
443 jexec alcatraz /usr/sbin/inetd -p ${HOME}/inetd-alcatraz.pid \
444 $(atf_get_srcdir)/echo_inetd.conf
446 ifconfig ${epair}a 192.0.2.2/24 up
448 jexec alcatraz pfctl -e
449 jexec alcatraz pfctl -x loud
450 pft_set_rules alcatraz \
451 "set syncookies always" \
456 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
458 reply=$(echo foo | nc -p 1234 -N -w 5 192.0.2.1 7)
459 if [ "${reply}" != "foo" ];
461 atf_fail "Failed to connect to syncookie protected echo daemon"
464 # We can't re-use the source IP/port combo quickly enough, so we're
465 # going to play a really dirty trick, and move our interface to a new
466 # jail, and do it from there.
467 ifconfig ${epair}a vnet singsing
468 jexec singsing ifconfig ${epair}a 192.0.2.2/24 up
469 atf_check -s exit:0 -o ignore jexec singsing ping -c 1 192.0.2.1
471 reply=$(echo bar | jexec singsing nc -p 1234 -N -w 5 192.0.2.1 7)
472 if [ "${reply}" != "bar" ];
474 atf_fail "Failed to connect to syncookie protected echo daemon (2)"
483 atf_init_test_cases()
485 atf_add_test_case "basic"
486 atf_add_test_case "basic_v6"
487 atf_add_test_case "forward"
488 atf_add_test_case "forward_v6"
489 atf_add_test_case "nostate"
490 atf_add_test_case "nostate_v6"
491 atf_add_test_case "adaptive"
492 atf_add_test_case "limits"
493 atf_add_test_case "port_reuse"