|
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
|
|
From: Jiri J. <jja...@re...> - 2013-09-03 11:27:09
|
Signed-off-by: Jiri Jaburek <jja...@re...>
---
audit-test/netfilter/run.conf | 42 +++++++++++++++---------------------------
1 file changed, 15 insertions(+), 27 deletions(-)
diff --git a/audit-test/netfilter/run.conf b/audit-test/netfilter/run.conf
index 423b3cb..e519a6c 100644
--- a/audit-test/netfilter/run.conf
+++ b/audit-test/netfilter/run.conf
@@ -395,18 +395,6 @@ function setup_default {
kill -9 $tspid
fi
- # For the RST flag test of IPv4 we do not want to start the netfilter
- # server and we will run a netcat command against the ipv4 loop back
- # address after we set the iptables so just return
-
- if [[ $tnum == 46 ]]; then
- if [[ $xndpid ]]; then
- kill -9 $xndpid
- xndrst=1
- fi
- return
- fi
-
if [[ ! $xndpid ]]; then
echo "starting local lblnet_tst_server"
./do_netfilsvr.bash
@@ -661,7 +649,9 @@ function run_test {
iptables_setup
ip6tables_setup
sleep 3
- if [[ $tnum -lt 29 ]] || [[ $tnum -gt 36 ]]; then
+ # exclude ping and RST tests
+ if ! [[ $tnum -ge 29 && $tnum -le 36 ]] \
+ && ! [[ $tnum -ge 45 && $tnum -le 46 ]]; then
setup_default
echo "going to setup_default"
fi
@@ -817,15 +807,15 @@ function run_test {
protov=6
;;
45)
- ip6tables -A INPUT -p tcp --dport 4000 --tcp-flags ALL RST -j LOG --log-prefix "rst received ipv6"
- ip6tables -A INPUT -p tcp --dport 4000 --tcp-flags ALL RST -j AUDIT_ACCEPT
+ ip6tables -A INPUT -i lo -p tcp --sport $tst_port1 --tcp-flags RST RST -j LOG --log-prefix "rst received ipv6"
+ ip6tables -A INPUT -i lo -p tcp --sport $tst_port1 --tcp-flags RST RST -j AUDIT_ACCEPT
logrotate -f /etc/logrotate.d/syslog
actv=0
protov=6
;;
46)
- iptables -A INPUT -i lo -p tcp --sport 4000 --tcp-flags RST RST -j LOG --log-prefix "rst received ipv4"
- iptables -A INPUT -i lo -p tcp --sport 4000 --tcp-flags RST RST -j AUDIT_ACCEPT
+ iptables -A INPUT -i lo -p tcp --sport $tst_port1 --tcp-flags RST RST -j LOG --log-prefix "rst received ipv4"
+ iptables -A INPUT -i lo -p tcp --sport $tst_port1 --tcp-flags RST RST -j AUDIT_ACCEPT
logrotate -f /etc/logrotate.d/syslog
actv=0
protov=6
@@ -1792,32 +1782,30 @@ done
host=local type=unlabeled op=recv_tcp ipv=ipv6 port=$tst_port1 \
tnum=44 '$host_remote tcp $port'
## TESTCASE Test #44 tnum 45
-## Table Rule received tcp segments (ipv6) to destination port 4000
+## Table Rule received tcp segments (ipv6) from dst port $tst_port1
## with RST flag set are accepted and logged to
## /var/log/messages with "rst received ipv6" log prefix
## and recorded in audit.log
-## Input nc listen (forced ipv6)is started on TOE on $port and nc
-## connection (forced ipv6) is started on $port, this
-## should generate segment with an RST flag
+## Input tcp connection request (ipv6) is sent over local
+## loopback device to port $tst_port1
## Expected Result segments pass through, messages file has log, audit.log
## has record.
+ connect \
mlsop=eq expres=success \
- host=local type=unlabeled op=recv_tcp ipv=ipv6 port=$tst_port1 \
+ host=local type=unlabeled ipv=ipv6 port=$tst_port1 \
tnum=45 '$host_remote tcp $port'
## TESTCASE Test #45 tnum 46
-## Table Rule received tcp segments (ipv4) to destination port 4000
+## Table Rule received tcp segments (ipv4) from dst port $tst_port1
## with RST flag set are accepted and logged to
## /var/log/messages with "rst received ipv4" log prefix
## and recorded in audit.log
-## Input nc listen is started on TOE on $port and nc connection
-## initiation is started on $port, this should generate
-## segment with an RST flag
+## Input tcp connection request (ipv4) is sent over local
+## loopback device to port $tst_port1
## Expected Result segments pass through, messages file has log, audit.log
## has record.
+ connect \
mlsop=eq expres=success \
- host=local type=unlabeled op=recv_tcp ipv=ipv4 port=4000 \
+ host=local type=unlabeled ipv=ipv4 port=$tst_port1 \
tnum=46 '$host_remote tcp $port'
## TESTCASE Test #46 tnum 47
## Table Rule received tcp segments (ipv4) to destination port
--
1.8.3.1
|
|
From: Linda K. <lin...@hp...> - 2013-09-03 14:14:00
|
Hi Jiri,
Based on our previous mail, this looks good to me.
Looking at the code changes, it does look like some things were
missed in earlier changes to those tests. For questions about
whether the test case is sufficient, we may need to send a note to
Stephan.
-- ljk
Jiri Jaburek wrote:
> Signed-off-by: Jiri Jaburek <jja...@re...>
> ---
> audit-test/netfilter/run.conf | 42 +++++++++++++++---------------------------
> 1 file changed, 15 insertions(+), 27 deletions(-)
>
> diff --git a/audit-test/netfilter/run.conf b/audit-test/netfilter/run.conf
> index 423b3cb..e519a6c 100644
> --- a/audit-test/netfilter/run.conf
> +++ b/audit-test/netfilter/run.conf
> @@ -395,18 +395,6 @@ function setup_default {
> kill -9 $tspid
> fi
>
> - # For the RST flag test of IPv4 we do not want to start the netfilter
> - # server and we will run a netcat command against the ipv4 loop back
> - # address after we set the iptables so just return
> -
> - if [[ $tnum == 46 ]]; then
> - if [[ $xndpid ]]; then
> - kill -9 $xndpid
> - xndrst=1
> - fi
> - return
> - fi
> -
> if [[ ! $xndpid ]]; then
> echo "starting local lblnet_tst_server"
> ./do_netfilsvr.bash
> @@ -661,7 +649,9 @@ function run_test {
> iptables_setup
> ip6tables_setup
> sleep 3
> - if [[ $tnum -lt 29 ]] || [[ $tnum -gt 36 ]]; then
> + # exclude ping and RST tests
> + if ! [[ $tnum -ge 29 && $tnum -le 36 ]] \
> + && ! [[ $tnum -ge 45 && $tnum -le 46 ]]; then
> setup_default
> echo "going to setup_default"
> fi
> @@ -817,15 +807,15 @@ function run_test {
> protov=6
> ;;
> 45)
> - ip6tables -A INPUT -p tcp --dport 4000 --tcp-flags ALL RST -j LOG --log-prefix "rst received ipv6"
> - ip6tables -A INPUT -p tcp --dport 4000 --tcp-flags ALL RST -j AUDIT_ACCEPT
> + ip6tables -A INPUT -i lo -p tcp --sport $tst_port1 --tcp-flags RST RST -j LOG --log-prefix "rst received ipv6"
> + ip6tables -A INPUT -i lo -p tcp --sport $tst_port1 --tcp-flags RST RST -j AUDIT_ACCEPT
> logrotate -f /etc/logrotate.d/syslog
> actv=0
> protov=6
> ;;
> 46)
> - iptables -A INPUT -i lo -p tcp --sport 4000 --tcp-flags RST RST -j LOG --log-prefix "rst received ipv4"
> - iptables -A INPUT -i lo -p tcp --sport 4000 --tcp-flags RST RST -j AUDIT_ACCEPT
> + iptables -A INPUT -i lo -p tcp --sport $tst_port1 --tcp-flags RST RST -j LOG --log-prefix "rst received ipv4"
> + iptables -A INPUT -i lo -p tcp --sport $tst_port1 --tcp-flags RST RST -j AUDIT_ACCEPT
> logrotate -f /etc/logrotate.d/syslog
> actv=0
> protov=6
> @@ -1792,32 +1782,30 @@ done
> host=local type=unlabeled op=recv_tcp ipv=ipv6 port=$tst_port1 \
> tnum=44 '$host_remote tcp $port'
> ## TESTCASE Test #44 tnum 45
> -## Table Rule received tcp segments (ipv6) to destination port 4000
> +## Table Rule received tcp segments (ipv6) from dst port $tst_port1
> ## with RST flag set are accepted and logged to
> ## /var/log/messages with "rst received ipv6" log prefix
> ## and recorded in audit.log
> -## Input nc listen (forced ipv6)is started on TOE on $port and nc
> -## connection (forced ipv6) is started on $port, this
> -## should generate segment with an RST flag
> +## Input tcp connection request (ipv6) is sent over local
> +## loopback device to port $tst_port1
> ## Expected Result segments pass through, messages file has log, audit.log
> ## has record.
> + connect \
> mlsop=eq expres=success \
> - host=local type=unlabeled op=recv_tcp ipv=ipv6 port=$tst_port1 \
> + host=local type=unlabeled ipv=ipv6 port=$tst_port1 \
> tnum=45 '$host_remote tcp $port'
> ## TESTCASE Test #45 tnum 46
> -## Table Rule received tcp segments (ipv4) to destination port 4000
> +## Table Rule received tcp segments (ipv4) from dst port $tst_port1
> ## with RST flag set are accepted and logged to
> ## /var/log/messages with "rst received ipv4" log prefix
> ## and recorded in audit.log
> -## Input nc listen is started on TOE on $port and nc connection
> -## initiation is started on $port, this should generate
> -## segment with an RST flag
> +## Input tcp connection request (ipv4) is sent over local
> +## loopback device to port $tst_port1
> ## Expected Result segments pass through, messages file has log, audit.log
> ## has record.
> + connect \
> mlsop=eq expres=success \
> - host=local type=unlabeled op=recv_tcp ipv=ipv4 port=4000 \
> + host=local type=unlabeled ipv=ipv4 port=$tst_port1 \
> tnum=46 '$host_remote tcp $port'
> ## TESTCASE Test #46 tnum 47
> ## Table Rule received tcp segments (ipv4) to destination port
|
|
From: Linda K. <lin...@hp...> - 2013-09-03 14:07:28
|
Hi Jiri,
Jiri Jaburek wrote:
> 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.
Unfortunately, that would not surprise me.
> 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.
These tests churned quite a bit during development so I suspect that
changes weren't applied consistently and once a test appeared to work
(passed), it was forgotten.
> 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)?
I don't know. To get a ruling on what's actually needed, we might need
to ask Atsec (Stephan Mueller).
> 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?
Sounds reasonable to me. Sorry I can't offer any better advice.
-- ljk
>
> Thanks for any insights,
> Jiri
>
> ------------------------------------------------------------------------------
> Learn the latest--Visual Studio 2012, SharePoint 2013, SQL 2012, more!
> Discover the easy way to master current and previous Microsoft technologies
> and advance your career. Get an incredible 1,500+ hours of step-by-step
> tutorial videos with LearnDevNow. Subscribe today and save!
> http://pubads.g.doubleclick.net/gampad/clk?id=58040911&iu=/4140/ostg.clktrk
> _______________________________________________
> Audit-test-developer mailing list
> Aud...@li...
> https://lists.sourceforge.net/lists/listinfo/audit-test-developer
|