diff mbox

`iptables -m tcp --syn` doesn't do what the man says

Message ID 1333142365.2325.2579.camel@edumazet-glaptop
State Not Applicable
Headers show

Commit Message

Eric Dumazet March 30, 2012, 9:19 p.m. UTC
On Sat, 2012-03-31 at 00:58 +0400, Artyom Gavrichenkov wrote:
> Hi all,
> 
> The iptables(8) manpage says:
> 
> --- [cut here] ---
>    tcp
>        These extensions can be used if `--protocol tcp' is specified. It provides the following options:
>        [!] --syn
>               Only  match  TCP packets with the SYN bit set and the ACK,RST and FIN bits cleared.  Such packets are used to request TCP connection initia‐
>               tion; for example, blocking such packets coming in an interface will prevent incoming TCP connections, but outgoing TCP connections will  be
>               unaffected.   It  is  equivalent  to  --tcp-flags  SYN,RST,ACK,FIN  SYN.   If  the "!" flag precedes the "--syn", the sense of the option is
>               inverted.
> --- [cut here] ---
> 
> Unfortunately, with current stable Linux kernel release (as well as
> with most of the previous versions) blocking TCP packets with the SYN
> bit set and the ACK,RST and FIN bits cleared won't prevent incoming
> TCP connections.
> 
> Currently Linux TCP stack considers an incoming TCP segment to be a
> connection initiation request if the segment only has SYN flag set and
> ACK and RST flags cleared. You can easily check it yourself with your
> nearest Linux box, as well as on the netfilter.org (213.95.27.115):
> 
> # hping3 -c 2 -n -FS -p 80 netfilter.org
> HPING netfilter.org (wlan0 213.95.27.115): SF set, 40 headers + 0 data bytes
> len=44 ip=213.95.27.115 ttl=52 DF id=0 sport=80 flags=SA seq=0 win=5840 rtt=58.8 ms
> len=44 ip=213.95.27.115 ttl=52 DF id=0 sport=80 flags=SA seq=1 win=5840 rtt=51.1 ms
> 
> --- netfilter.org hping statistic ---
> 2 packets transmitted, 2 packets received, 0% packet loss
> round-trip min/avg/max = 51.1/55.0/58.8 ms
> # 
> 
> As you see, the netfilter.org server sends SYN/ACK in response to an
> incoming SYN/FIN, indicating that a connection is being established.
> It is only a matter of a few checks to make sure that the indication
> is correct and the connection is indeed initialized.
> 
> This might be a Linux bug as well to accept SYN/FIN as a connection
> initiation attempt. However, there could as well be a reason for kernel
> developers to do this, because such thing as T/TCP (RFC 1644) allows a
> TCP server to act like this, and though this RFC is experimental and
> obsolete, as far as I know, it is still implemented somewhere, for
> example, in FreeBSD.
> 

FYI current linux kernel just drops this kind of message (SYN+FIN)

git describe --contains fdf5af0daf8019cec2396cdef8fb042d80fe71fa
v3.3-rc1~182^2~365

commit fdf5af0daf8019cec2396cdef8fb042d80fe71fa
Author: Eric Dumazet <eric.dumazet@gmail.com>
Date:   Fri Dec 2 23:41:42 2011 +0000

    tcp: drop SYN+FIN messages
    
    Denys Fedoryshchenko reported that SYN+FIN attacks were bringing his
    linux machines to their limits.
    
    Dont call conn_request() if the TCP flags includes SYN flag
    
    Reported-by: Denys Fedoryshchenko <denys@visp.net.lb>
    Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>




> I guess that most iptables setups probably are not affected by this
> behaviour, because `iptables -m tcp --syn' is often used for something
> in lines of this:
> 
> iptables -A INPUT -p tcp -m tcp --dport 22 --syn -j ACCEPT
> iptables -A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT
> iptables -A INPUT -j DROP
> 
> In this case, SYN/FIN segments will be dropped, because they are not
> considered plain SYN and they are not associated with an established
> connection. My guess is that, for example, kernel.org is set up like that:
> 

Or it runs linux 3.3

> # hping3 -c 2 -n -FS -p 80 kernel.org
> HPING kernel.org (wlan0 149.20.4.69): SF set, 40 headers + 0 data bytes
> 
> --- kernel.org hping statistic ---
> 2 packets transmitted, 0 packets received, 100% packet loss
> round-trip min/avg/max = 0.0/0.0/0.0 ms
> #
> 
> However, there are cases when this behaviour produces clear security
> breach, for example, when one is trying to prevent incoming TCP
> connections from a certain IP (as manpage suggests) or when one is
> trying to limit the rate of connection establishment attempts. In
> this case attacker can send SYN/FIN packets which would pass all the
> rules containing --syn and would establish a connection.
> 
> The patch to fix this is trivial (it is attached below), however, it
> might be a good idea to discuss reasons first and find the best
> solution possible.
> 
> P. S. Sorry for being so verbose, I'm new to this mailing list and I'm
> trying to explain everything as clear as I can.
> 

Thats perfect, thanks !

> -- 
> | Artyom Gavrichenkov
> | gpg: fa1c670e
> | mailto: ximaera@gmail.com
> | xmpp: ximaera@gmail.com
> | skype: xima_era
> | tel. no: +7 916 515 49 58
> 
> -- Signed-off-by: Artyom Gavrichenkov <ximaera@gmail.com>
> 
> diff --git a/extensions/libxt_tcp.c b/extensions/libxt_tcp.c
> index e849fa2..3af03c4 100644
> --- a/extensions/libxt_tcp.c
> +++ b/extensions/libxt_tcp.c
> @@ -169,7 +169,7 @@ tcp_parse(int c, char **argv, int invert, unsigned int *flags,
>                         xtables_error(PARAMETER_PROBLEM,
>                                    "Only one of `--syn' or `--tcp-flags' "
>                                    " allowed");
> -               parse_tcp_flags(tcpinfo, "SYN,RST,ACK,FIN", "SYN", invert);
> +               parse_tcp_flags(tcpinfo, "SYN,RST,ACK", "SYN", invert);
>                 *flags |= TCP_FLAGS;
>                 break;
>  
> diff --git a/extensions/libxt_tcp.man b/extensions/libxt_tcp.man
> index 7a16118..e1698df 100644
> --- a/extensions/libxt_tcp.man
> +++ b/extensions/libxt_tcp.man
> @@ -31,12 +31,12 @@ will only match packets with the SYN flag set, and the ACK, FIN and
>  RST flags unset.
>  .TP
>  [\fB!\fP] \fB\-\-syn\fP
> -Only match TCP packets with the SYN bit set and the ACK,RST and FIN bits
> +Only match TCP packets with the SYN bit set and the ACK and RST bits
>  cleared.  Such packets are used to request TCP connection initiation;
>  for example, blocking such packets coming in an interface will prevent
>  incoming TCP connections, but outgoing TCP connections will be
>  unaffected.
> -It is equivalent to \fB\-\-tcp\-flags SYN,RST,ACK,FIN SYN\fP.
> +It is equivalent to \fB\-\-tcp\-flags SYN,RST,ACK SYN\fP.
>  If the "!" flag precedes the "\-\-syn", the sense of the
>  option is inverted.
>  .TP
> 


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 78dd38c..0cbb440 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5811,6 +5811,8 @@  int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 			goto discard;
 
 		if (th->syn) {
+			if (th->fin)
+				goto discard;
 			if (icsk->icsk_af_ops->conn_request(sk, skb) < 0)
 				return 1;