pf tests: NAT exhaustion test

It's been reported that pf doesn't handle running out of available ports
for NAT correctly. It freezes until a state expires and it can find a
free port.
Test for this, by setting up a situation where only two ports are
available for NAT and then attempting to create three connections.

If successful the third connection will fail immediately. In an
incorrect case the connection attempt will freeze, also freezing all
interaction with pf through pfctl and trigger timeout.

PR:		233867
MFC after:	2 weeks
This commit is contained in:
kp 2018-12-12 20:19:18 +00:00
parent 40dbdeaf9d
commit c3c90bab84
2 changed files with 65 additions and 0 deletions

View File

@ -10,6 +10,7 @@ ATF_TESTS_SH+= anchor \
forward \
fragmentation \
names \
nat \
set_tos \
route_to \
synproxy \

64
tests/sys/netpfil/pf/nat.sh Executable file
View File

@ -0,0 +1,64 @@
# $FreeBSD$
. $(atf_get_srcdir)/utils.subr
atf_test_case "exhaust" "cleanup"
exhaust_head()
{
atf_set descr 'Test exhausting the NAT pool'
atf_set require.user root
}
exhaust_body()
{
pft_init
epair_nat=$(pft_mkepair)
epair_echo=$(pft_mkepair)
pft_mkjail nat ${epair_nat}b ${epair_echo}a
pft_mkjail echo ${epair_echo}b
ifconfig ${epair_nat}a 192.0.2.2/24 up
route add -net 198.51.100.0/24 192.0.2.1
jexec nat ifconfig ${epair_nat}b 192.0.2.1/24 up
jexec nat ifconfig ${epair_echo}a 198.51.100.1/24 up
jexec nat sysctl net.inet.ip.forwarding=1
jexec echo ifconfig ${epair_echo}b 198.51.100.2/24 up
jexec echo /usr/sbin/inetd $(atf_get_srcdir)/echo_inetd.conf
# Enable pf!
jexec nat pfctl -e
pft_set_rules nat \
"nat pass on ${epair_echo}a inet from 192.0.2.0/24 to any -> (${epair_echo}a) port 30000:30001 sticky-address"
# Sanity check
atf_check -s exit:0 -o ignore ping -c 3 198.51.100.2
echo "foo" | nc -N 198.51.100.2 7
echo "foo" | nc -N 198.51.100.2 7
# This one will fail, but that's expected
echo "foo" | nc -N 198.51.100.2 7 &
sleep 1
# If the kernel is stuck in pf_get_sport() this will not succeed either.
timeout 2 jexec nat pfctl -sa
if [ $? -eq 124 ]; then
# Timed out
atf_fail "pfctl timeout"
fi
}
exhaust_cleanup()
{
pft_cleanup
}
atf_init_test_cases()
{
atf_add_test_case "exhaust"
}