|
From: Jiri J. <jja...@re...> - 2013-09-02 16:33:04
|
Hi,
during my recent optimization work on the suite, I've run into problems
with a few netfilter tests, the "blockers" for me being 44 and 45, both
testing TCP RST - on ipv6 and ipv4.
For some unknown reason, both are implemented differently. My suspicion
is that somebody made a typo, but the test worked fine anyway, so the
typo was never discovered.
For the purposes of this email, I'll be referencing line numbers from
commit 89232060b2, file audit-test/netfilter/run.conf and describing
the operation on a RHEL6 machine.
Let's start with test 45 (tnum 46). It uses explicitly specified
port=4000 (line 1820) to connect via nc (line 955). This operation
has to return RST from port 4000 in order to be logged (lines 827-828).
However since port 4000 is normally used by xinetd to spawn
lblnet_tst_server, the test SIGKILLs xinetd (line 402) beforehand.
This makes port 4000 free (closed), which generates TCP RST as reply
when something (netcat) tries to connect to it.
In theory, test 44 (tnum 45) could be similar. It, however, isn't.
Despite the description mentioning port 4000, it uses port=$tst_port1
(line 1806), which is defined as 4100 (line 26). It then connects
via nc to that port, which succeeds ('recv' server operation is set up),
and, one second later (-w 1), closes the connection via FIN.
No RST is generated, yet the test PASSes. How is this possible?
The answer lies within the setup itself. Netfilter rules are set up
on port 4000 (lines 820-821), but on "dport", not "sport". This means
that we would need *something* to send RST to port 4000, which is a lot
more weird operation to do, and not an easy one.
Furthermore, xinetd is not killed, line 402 specifies only tnum 46,
not 45, which means port 4000 is still open, with listening xinetd,
one more reason why RST shouldn't happen, but it somehow does.
The final piece to the puzzle is the initial lblnet_tst_server setup.
Test 45 uses (like others) op=recv_tcp (line 1806), which sets up
"recv" operation on the server (line 433). When this cmd_str line
is sent to the server via nc (line 451), the connection is left intact,
even though the client (nc) exits one second later (-w 1). Then the
test itself proceeds (using port 4100), which makes the server-side
"recv" operation finish. Upon finishing, the server sends a return code
to the client, but the client already exited, so the kernel sends,
on behalf of the client, a TCP RST packet to the server, port 4000,
ultimately making the test PASS.
I admit, it took me several hours to figure this out. I don't really
know if this approach has been chosen intentionally, or whether somebody
made several "typos" on several places.
I would like to ask if either of those approaches is needed for the
functionality itself to be tested. Do we just need *any* RST packet
to get logged (to /var/log/messages and audit log)?
Wouldn't simply connecting to an already closed port, matching --sport,
be enough? Like *not* setting up "recv" on port 4100 and using it
to match incoming TCP RST packets, generated by a connection attempt?
Thanks for any insights,
Jiri
|