Page MenuHomeFreeBSD

pf tests: Add a test for max-src-conn
ClosedPublic

Authored by vegeta_tuxpowered.net on Thu, Sep 26, 5:06 PM.
Tags
None
Referenced Files
F97502151: D46798.diff
Sun, Sep 29, 6:42 PM
Unknown Object (File)
Sat, Sep 28, 7:49 PM
Unknown Object (File)
Sat, Sep 28, 12:22 PM

Details

Summary

Switch tests using pft_ping.py to inetd. Netcat can only accept a single connection, we need multiple parallel connections to test max-src-conn. Use the discard service and modify pft_ping.py to use proper port number.

Implement functionality of 3-way handshake test in pft_ping.py. Make send_params accessible to sniffer, because answers to SYN+ACK packets should be send with the same parameters as the original SYN packet.

Finally add a test for max-src-conn and overload.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

Simplify the check_tcp_3way functions, there is no need to sniff for our own ACK. Once it's sent out, we can assume the check has passed.

I'm seeing this test fail quite often (though not always) because it can't find the 4204 state. So things appear to be doing what we'd expect, but there's no state. I'm not sure why, because it looks like we only check max_src_conn a state actually exists, so we ought to see it in the state table too. Sometimes that's the case, but not always.

For maximum annoyance that problem seems to go away if I attach a dtrace probe for pf_free_state(), so right now I have no idea what's causing that.
I'm not sure if we want to go dig into what's going on, or just change the test so it accepts either the state no existing or it being CLOSED as fine.

sys/netpfil/pf/src_track.sh
106 ↗(On Diff #143760)

The error message should be about 4204, not 4203.

In D46798#1067230, @kp wrote:

I'm seeing this test fail quite often (though not always) because it can't find the 4204 state. So things appear to be doing what we'd expect, but there's no state. I'm not sure why, because it looks like we only check max_src_conn a state actually exists, so we ought to see it in the state table too. Sometimes that's the case, but not always.

For maximum annoyance that problem seems to go away if I attach a dtrace probe for pf_free_state(), so right now I have no idea what's causing that.
I'm not sure if we want to go dig into what's going on, or just change the test so it accepts either the state no existing or it being CLOSED as fine.

I've run the test in debug mode and added printing of states after each test:

Executing command [ /usr/tests/sys/netpfil/pf/../common/pft_ping.py --sendif epair0a --to 2001:db8:43::2 --replyif epair0a --ping-type=tcp3way --send-sport=4201 --fromaddr 2001:db8:44::1 ]
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4201]       ESTABLISHED:ESTABLISHED
Executing command [ /usr/tests/sys/netpfil/pf/../common/pft_ping.py --sendif epair0a --to 2001:db8:43::2 --replyif epair0a --ping-type=tcp3way --send-sport=4202 --fromaddr 2001:db8:44::1 ]
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4201]       ESTABLISHED:ESTABLISHED
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4202]       ESTABLISHED:ESTABLISHED
Executing command [ /usr/tests/sys/netpfil/pf/../common/pft_ping.py --sendif epair0a --to 2001:db8:43::2 --replyif epair0a --ping-type=tcp3way --send-sport=4203 --fromaddr 2001:db8:44::1 ]
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4201]       ESTABLISHED:ESTABLISHED
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4202]       ESTABLISHED:ESTABLISHED
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4203]       ESTABLISHED:ESTABLISHED
Executing command [ /usr/tests/sys/netpfil/pf/../common/pft_ping.py --sendif epair0a --to 2001:db8:43::2 --replyif epair0a --ping-type=tcp3way --send-sport=4204 --fromaddr 2001:db8:44::1 ]
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4201]       ESTABLISHED:ESTABLISHED
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4202]       ESTABLISHED:ESTABLISHED
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4203]       ESTABLISHED:ESTABLISHED
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4204]       CLOSED:CLOSED
Executing command [ /usr/tests/sys/netpfil/pf/../common/pft_ping.py --sendif epair0a --to 2001:db8:43::2 --replyif epair0a --ping-type=tcp3way --send-sport=4205 --fromaddr 2001:db8:44::2 ]
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4201]       ESTABLISHED:ESTABLISHED
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4202]       ESTABLISHED:ESTABLISHED
all tcp 2001:db8:43::2[9] <- 2001:db8:44::1[4203]       ESTABLISHED:ESTABLISHED
all tcp 2001:db8:43::2[9] <- 2001:db8:44::2[4205]       ESTABLISHED:ESTABLISHED

It can be seen that the CLOSED state is there for a moment. A look at the source code reveals the issue:

  1. pf_src_connlimit() sets the CLOSED state and marks it ready for purging:
	/* Kill this state. */
	state->timeout = PFTM_PURGE;
	pf_set_protostate(state, PF_PEER_BOTH, TCPS_CLOSED);
  1. PFTM_PURGE means that the state will not obey the usual tcp.closing timeout but instead will be purged immediately by pf_purge_thread() -> pf_purge_expired_states().

I don't think we should play with timers to make the test work. I'll adjust it to accept the state purged or closed.

However this brings an important issue: some of tests depend on proper timing. I've seen some other tests randomly failing too, I think mostly the ones related to pfsync. Maybe we need dtrace-based tests which would see if given functions are called, instead of checking their results in userspace, especially if results are deleting something instead of creating it.

Update test for the hitting the max-src-conn rule so that it works both when the state is found CLOSED or when there is no state at all.

Fix wrong cleanup function. Rename the test to …_rule because there will be in future another test for global source tracking.

Update rules to match only on inet6 proto tcp.

This revision was not accepted when it landed; it landed in state Needs Review.Sat, Sep 28, 4:55 PM
This revision was automatically updated to reflect the committed changes.