pf: cope with SCTP port re-use

Some SCTP implementations will abort connections and then later re-use the same
port numbers (i.e. both src and dst) for a new connection, before pf has fully
purged the old connection.

Apply the same hack we already have for similarly misbehaving TCP
implementations and forcibly remove the old state so we can create a new one.

MFC after:	2 weeks
Sponsored by:	Rubicon Communications, LLC ("Netgate")

(cherry picked from commit 82e021443a)
This commit is contained in:
Kristof Provost 2024-08-12 18:18:36 +02:00 committed by Franco Fichtner
parent 6e758a4b37
commit bc5627fc5f
2 changed files with 68 additions and 0 deletions

View file

@ -6122,6 +6122,15 @@ pf_test_state_sctp(struct pf_kstate **state, struct pfi_kkif *kif,
psrc = PF_PEER_DST;
}
if ((src->state >= SCTP_SHUTDOWN_SENT || src->state == SCTP_CLOSED) &&
(dst->state >= SCTP_SHUTDOWN_SENT || dst->state == SCTP_CLOSED) &&
pd->sctp_flags & PFDESC_SCTP_INIT) {
pf_set_protostate(*state, PF_PEER_BOTH, SCTP_CLOSED);
pf_unlink_state(*state);
*state = NULL;
return (PF_DROP);
}
/* Track state. */
if (pd->sctp_flags & PFDESC_SCTP_INIT) {
if (src->state < SCTP_COOKIE_WAIT) {

View file

@ -181,6 +181,64 @@ basic_v6_cleanup()
pft_cleanup
}
atf_test_case "reuse" "cleanup"
reuse_head()
{
atf_set descr 'Test handling dumb clients that reuse source ports'
atf_set require.user root
}
reuse_body()
{
sctp_init
j="sctp:reuse"
epair=$(vnet_mkepair)
vnet_mkjail ${j}a ${epair}a
vnet_mkjail ${j}b ${epair}b
jexec ${j}a ifconfig ${epair}a 192.0.2.1/24 up
jexec ${j}b ifconfig ${epair}b 192.0.2.2/24 up
# Sanity check
atf_check -s exit:0 -o ignore \
jexec ${j}a ping -c 1 192.0.2.2
jexec ${j}a pfctl -e
pft_set_rules ${j}a \
"block" \
"pass in proto sctp to port 1234"
echo "foo" | jexec ${j}a nc --sctp -N -l 1234 &
# Wait for the server to start
sleep 1
out=$(jexec ${j}b nc --sctp -N -w 3 -p 1234 192.0.2.1 1234)
if [ "$out" != "foo" ]; then
atf_fail "SCTP connection failed"
fi
# Now do the same thing again, with the same port numbers
jexec ${j}a pfctl -ss -v
echo "foo" | jexec ${j}a nc --sctp -N -l 1234 &
# Wait for the server to start
sleep 1
out=$(jexec ${j}b nc --sctp -N -w 3 -p 1234 192.0.2.1 1234)
if [ "$out" != "foo" ]; then
atf_fail "SCTP connection failed"
fi
jexec ${j}a pfctl -ss -v
}
reuse_cleanup()
{
pft_cleanup
}
atf_test_case "abort_v4" "cleanup"
abort_v4_head()
{
@ -691,6 +749,7 @@ atf_init_test_cases()
{
atf_add_test_case "basic_v4"
atf_add_test_case "basic_v6"
atf_add_test_case "reuse"
atf_add_test_case "abort_v4"
atf_add_test_case "abort_v6"
atf_add_test_case "nat_v4"