netfilter: more strict TCP flag matching in SYNPROXY
authorJesper Dangaard Brouer <brouer@redhat.com>
Wed, 28 Aug 2013 13:14:38 +0000 (15:14 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 4 Sep 2013 09:43:11 +0000 (11:43 +0200)
Its seems Patrick missed to incoorporate some of my requested changes
during review v2 of SYNPROXY netfilter module.

Which were, to avoid SYN+ACK packets to enter the path, meant for the
ACK packet from the client (from the 3WHS).

Further there were a bug in ip6t_SYNPROXY.c, for matching SYN packets
that didn't exclude the ACK flag.

Go a step further with SYN packet/flag matching by excluding flags
ACK+FIN+RST, in both IPv4 and IPv6 modules.

The intented usage of SYNPROXY is as follows:
(gracefully describing usage in commit)

 iptables -t raw -A PREROUTING -i eth0 -p tcp --dport 80 --syn -j NOTRACK
 iptables -A INPUT -i eth0 -p tcp --dport 80 -m state UNTRACKED,INVALID \
         -j SYNPROXY --sack-perm --timestamp --mss 1480 --wscale 7 --ecn

 echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose

This does filter SYN flags early, for packets in the UNTRACKED state,
but packets in the INVALID state with other TCP flags could still
reach the module, thus this stricter flag matching is still needed.

Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/ipv4/netfilter/ipt_SYNPROXY.c
net/ipv6/netfilter/ip6t_SYNPROXY.c

index 94371db6aeccc0a99c53da339cf7b068b0008254..90e489eb1c0a346cfe0c5c15cf52900f908f0a2f 100644 (file)
@@ -269,7 +269,7 @@ synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 
        synproxy_parse_options(skb, par->thoff, th, &opts);
 
-       if (th->syn && !th->ack) {
+       if (th->syn && !(th->ack || th->fin || th->rst)) {
                /* Initial SYN from client */
                this_cpu_inc(snet->stats->syn_received);
 
@@ -285,7 +285,7 @@ synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par)
                                          XT_SYNPROXY_OPT_ECN);
 
                synproxy_send_client_synack(skb, th, &opts);
-       } else if (th->ack && !(th->fin || th->rst))
+       } else if (th->ack && !(th->fin || th->rst || th->syn))
                /* ACK from client */
                synproxy_recv_client_ack(snet, skb, th, &opts, ntohl(th->seq));
 
index 4270a9b145e5968a577f4db06c762de48afdb35b..a5af0bfef126973938786e98028acbcb767dea53 100644 (file)
@@ -284,7 +284,7 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 
        synproxy_parse_options(skb, par->thoff, th, &opts);
 
-       if (th->syn) {
+       if (th->syn && !(th->ack || th->fin || th->rst)) {
                /* Initial SYN from client */
                this_cpu_inc(snet->stats->syn_received);
 
@@ -300,7 +300,7 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
                                          XT_SYNPROXY_OPT_ECN);
 
                synproxy_send_client_synack(skb, th, &opts);
-       } else if (th->ack && !(th->fin || th->rst))
+       } else if (th->ack && !(th->fin || th->rst || th->syn))
                /* ACK from client */
                synproxy_recv_client_ack(snet, skb, th, &opts, ntohl(th->seq));