aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2009-05-25 11:23:15 -0400
committerPatrick McHardy <kaber@trash.net>2009-05-25 11:23:15 -0400
commitbfcaa50270e18f35220a11d46e98fc6232c24606 (patch)
treedd06bf91db9aff84adf442b6c8aa6be58c923ec0 /net
parentfecc1133b66af6e0cd49115a248f34bbb01f180a (diff)
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>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index b5ccf2b4b2e7..97a6e93d742e 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,
634 sender->td_end = end; 634 sender->td_end = end;
635 sender->flags |= IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED; 635 sender->flags |= IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;
636 } 636 }
637 if (tcph->ack) {
638 if (!(sender->flags & IP_CT_TCP_FLAG_MAXACK_SET)) {
639 sender->td_maxack = ack;
640 sender->flags |= IP_CT_TCP_FLAG_MAXACK_SET;
641 } else if (after(ack, sender->td_maxack))
642 sender->td_maxack = ack;
643 }
644
637 /* 645 /*
638 * Update receiver data. 646 * Update receiver data.
639 */ 647 */
@@ -919,6 +927,16 @@ static int tcp_packet(struct nf_conn *ct,
919 return -NF_ACCEPT; 927 return -NF_ACCEPT;
920 case TCP_CONNTRACK_CLOSE: 928 case TCP_CONNTRACK_CLOSE:
921 if (index == TCP_RST_SET 929 if (index == TCP_RST_SET
930 && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET)
931 && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) {
932 /* Invalid RST */
933 write_unlock_bh(&tcp_lock);
934 if (LOG_INVALID(net, IPPROTO_TCP))
935 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
936 "nf_ct_tcp: invalid RST ");
937 return -NF_ACCEPT;
938 }
939 if (index == TCP_RST_SET
922 && ((test_bit(IPS_SEEN_REPLY_BIT, &ct->status) 940 && ((test_bit(IPS_SEEN_REPLY_BIT, &ct->status)
923 && ct->proto.tcp.last_index == TCP_SYN_SET) 941 && ct->proto.tcp.last_index == TCP_SYN_SET)
924 || (!test_bit(IPS_ASSURED_BIT, &ct->status) 942 || (!test_bit(IPS_ASSURED_BIT, &ct->status)