From patchwork Fri Mar 30 20:58:54 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Artyom Gavrichenkov X-Patchwork-Id: 149751 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 86487B6EF4 for ; Sat, 31 Mar 2012 07:40:14 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933357Ab2C3UkL (ORCPT ); Fri, 30 Mar 2012 16:40:11 -0400 Received: from mail-bk0-f46.google.com ([209.85.214.46]:47255 "EHLO mail-bk0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933072Ab2C3UkK (ORCPT ); Fri, 30 Mar 2012 16:40:10 -0400 Received: by bkcik5 with SMTP id ik5so975213bkc.19 for ; Fri, 30 Mar 2012 13:40:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:subject :x-enigmail-version:content-type; bh=QR47LyoNkG0ZuY+8dZICBJuuZao+ceAlRy6Q7juE4ds=; b=yNP1z4mL9bW+La53lqK4vVXiWiw41xcnu4pAXnhTzh3WYx5w3llffQsJBPOzCRLcEB 2J2cFSqEShcwfjhflxAgn5nVBfUd3z5E2DieUsFxAaxNR++/5KDo4hqf7mihrgVpdr77 Ur3GkAez5BHRkEhFL1R58w+ainR27lOWnicIVAH3HuiSCWxIpuk2mvhht1cfOfOExDuo GEz+4cjT5YI849xjJqM/HbXxA0rfhPjvXVk9r4IcVpMU5q9G0gAjOwbVPAsJNAhFG/BY oHKMREw66IPDeEiiqFlaF3LJ/AHQj+bid76kgIFsB5Ze0zwzXSt1GcaxRp1fOiumDoSb 9e9Q== Received: by 10.205.132.71 with SMTP id ht7mr1552351bkc.19.1333140008862; Fri, 30 Mar 2012 13:40:08 -0700 (PDT) Received: from [192.168.1.18] ([90.155.184.67]) by mx.google.com with ESMTPS id x4sm22817460bkv.8.2012.03.30.13.40.06 (version=SSLv3 cipher=OTHER); Fri, 30 Mar 2012 13:40:07 -0700 (PDT) Message-ID: <4F761E8E.9000708@gmail.com> Date: Sat, 31 Mar 2012 00:58:54 +0400 From: Artyom Gavrichenkov User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:11.0) Gecko/20120310 Thunderbird/11.0 MIME-Version: 1.0 To: netfilter-devel@vger.kernel.org Subject: `iptables -m tcp --syn` doesn't do what the man says X-Enigmail-Version: 1.4 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org 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. 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: # 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. 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