public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: davem@davemloft.net
Cc: netdev@vger.kernel.org, Patrick McHardy <kaber@trash.net>,
	netfilter-devel@vger.kernel.org
Subject: netfilter 01/04: nf_ct_tcp: fix accepting invalid RST segments
Date: Wed, 27 May 2009 16:35:25 +0200 (MEST)	[thread overview]
Message-ID: <20090527143523.4649.91602.sendpatchset@x2.localnet> (raw)
In-Reply-To: <20090527143521.4649.73610.sendpatchset@x2.localnet>

commit bfcaa50270e18f35220a11d46e98fc6232c24606
Author: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Date:   Mon May 25 17:23:15 2009 +0200

    netfilter: nf_ct_tcp: fix accepting invalid RST segments
    
    Robert L Mathews discovered that some clients send evil TCP RST segments,
    which are accepted by netfilter conntrack but discarded by the
    destination. Thus the conntrack entry is destroyed but the destination
    retransmits data until timeout.
    
    The same technique, i.e. sending properly crafted RST segments, can easily
    be used to bypass connlimit/connbytes based restrictions (the sample
    script written by Robert can be found in the netfilter mailing list
    archives).
    
    The patch below adds a new flag and new field to struct ip_ct_tcp_state so
    that checking RST segments can be made more strict and thus TCP conntrack
    can catch the invalid ones: the RST segment is accepted only if its
    sequence number higher than or equal to the highest ack we seen from the
    other direction. (The last_ack field cannot be reused because it is used
    to catch resent packets.)
    
    Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/include/linux/netfilter/nf_conntrack_tcp.h b/include/linux/netfilter/nf_conntrack_tcp.h
index 3066789..b2f384d 100644
--- a/include/linux/netfilter/nf_conntrack_tcp.h
+++ b/include/linux/netfilter/nf_conntrack_tcp.h
@@ -35,6 +35,9 @@ enum tcp_conntrack {
 /* Has unacknowledged data */
 #define IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED	0x10
 
+/* The field td_maxack has been set */
+#define IP_CT_TCP_FLAG_MAXACK_SET		0x20
+
 struct nf_ct_tcp_flags {
 	__u8 flags;
 	__u8 mask;
@@ -46,6 +49,7 @@ struct ip_ct_tcp_state {
 	u_int32_t	td_end;		/* max of seq + len */
 	u_int32_t	td_maxend;	/* max of ack + max(win, 1) */
 	u_int32_t	td_maxwin;	/* max(win) */
+	u_int32_t	td_maxack;	/* max of ack */
 	u_int8_t	td_scale;	/* window scale factor */
 	u_int8_t	flags;		/* per direction options */
 };
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index b5ccf2b..97a6e93 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -634,6 +634,14 @@ static bool tcp_in_window(const struct nf_conn *ct,
 			sender->td_end = end;
 			sender->flags |= IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;
 		}
+		if (tcph->ack) {
+			if (!(sender->flags & IP_CT_TCP_FLAG_MAXACK_SET)) {
+				sender->td_maxack = ack;
+				sender->flags |= IP_CT_TCP_FLAG_MAXACK_SET;
+			} else if (after(ack, sender->td_maxack))
+				sender->td_maxack = ack;
+		}
+
 		/*
 		 * Update receiver data.
 		 */
@@ -919,6 +927,16 @@ static int tcp_packet(struct nf_conn *ct,
 		return -NF_ACCEPT;
 	case TCP_CONNTRACK_CLOSE:
 		if (index == TCP_RST_SET
+		    && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET)
+		    && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) {
+			/* Invalid RST  */
+			write_unlock_bh(&tcp_lock);
+			if (LOG_INVALID(net, IPPROTO_TCP))
+				nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+					  "nf_ct_tcp: invalid RST ");
+			return -NF_ACCEPT;
+		}
+		if (index == TCP_RST_SET
 		    && ((test_bit(IPS_SEEN_REPLY_BIT, &ct->status)
 			 && ct->proto.tcp.last_index == TCP_SYN_SET)
 			|| (!test_bit(IPS_ASSURED_BIT, &ct->status)

  reply	other threads:[~2009-05-27 14:35 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-27 14:35 netfilter 00/04: netfilter fixes Patrick McHardy
2009-05-27 14:35 ` Patrick McHardy [this message]
2009-05-27 14:35 ` netfilter 02/04: nf_ct_dccp: add missing DCCP protocol changes in event cache Patrick McHardy
2009-05-27 14:35 ` netfilter 03/04: xt_hashlimit does a wrong SEQ_SKIP Patrick McHardy
2009-05-27 14:35 ` netfilter 04/04: nfnetlink_log: fix wrong skbuff size calculation Patrick McHardy
2009-05-27 22:52 ` netfilter 00/04: netfilter fixes David Miller
2009-05-28 16:34   ` Patrick McHardy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090527143523.4649.91602.sendpatchset@x2.localnet \
    --to=kaber@trash.net \
    --cc=davem@davemloft.net \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox