netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH] tcp: Replace possible syn attack msg by counters
@ 2011-08-11  5:38 Tom Herbert
  2011-08-11  6:13 ` David Miller
  2011-08-30 13:21 ` [PATCH v2] tcp: Change possible SYN flooding messages Eric Dumazet
  0 siblings, 2 replies; 8+ messages in thread
From: Tom Herbert @ 2011-08-11  5:38 UTC (permalink / raw)
  To: davem, netdev

Rather than printing the message to the log, use a mib counter to keep
track of the count of occurences of syn cookies being used or syn
being dropped when request queue is full.

Rationale is these messages can fill up /var/log/messages on server
which is simply under heavy load... I'm not sure how much more useful
they would be in identifying a server DOS attack (compared to
counters).

Signed-off-by: Tom Herbert <therbert@google.com>
---
 include/linux/snmp.h |    2 ++
 net/ipv4/proc.c      |    2 ++
 net/ipv4/tcp_ipv4.c  |   30 +++++++++---------------------
 net/ipv6/tcp_ipv6.c  |   29 +++++++++--------------------
 4 files changed, 22 insertions(+), 41 deletions(-)

diff --git a/include/linux/snmp.h b/include/linux/snmp.h
index 12b2b18..e16557a 100644
--- a/include/linux/snmp.h
+++ b/include/linux/snmp.h
@@ -231,6 +231,8 @@ enum
 	LINUX_MIB_TCPDEFERACCEPTDROP,
 	LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */
 	LINUX_MIB_TCPTIMEWAITOVERFLOW,		/* TCPTimeWaitOverflow */
+	LINUX_MIB_TCPREQQFULLDOCOOKIES,		/* TCPReqQFullDoCookies */
+	LINUX_MIB_TCPREQQFULLDROP,		/* TCPReqQFullDrop */
 	__LINUX_MIB_MAX
 };
 
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index b14ec7d..4bfad5d 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -254,6 +254,8 @@ static const struct snmp_mib snmp4_net_list[] = {
 	SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP),
 	SNMP_MIB_ITEM("IPReversePathFilter", LINUX_MIB_IPRPFILTER),
 	SNMP_MIB_ITEM("TCPTimeWaitOverflow", LINUX_MIB_TCPTIMEWAITOVERFLOW),
+	SNMP_MIB_ITEM("TCPReqQFullDoCookies", LINUX_MIB_TCPREQQFULLDOCOOKIES),
+	SNMP_MIB_ITEM("TCPReqQFullDrop", LINUX_MIB_TCPREQQFULLDROP),
 	SNMP_MIB_SENTINEL
 };
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 955b8e6..f36ab28 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -807,21 +807,6 @@ static void tcp_v4_reqsk_destructor(struct request_sock *req)
 	kfree(inet_rsk(req)->opt);
 }
 
-static void syn_flood_warning(const struct sk_buff *skb)
-{
-	const char *msg;
-
-#ifdef CONFIG_SYN_COOKIES
-	if (sysctl_tcp_syncookies)
-		msg = "Sending cookies";
-	else
-#endif
-		msg = "Dropping request";
-
-	pr_info("TCP: Possible SYN flooding on port %d. %s.\n",
-				ntohs(tcp_hdr(skb)->dest), msg);
-}
-
 /*
  * Save and compile IPv4 options into the request_sock if needed.
  */
@@ -1249,14 +1234,17 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 	 * evidently real one.
 	 */
 	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
-		if (net_ratelimit())
-			syn_flood_warning(skb);
 #ifdef CONFIG_SYN_COOKIES
-		if (sysctl_tcp_syncookies) {
-			want_cookie = 1;
-		} else
+		want_cookie = sysctl_tcp_syncookies;
 #endif
-		goto drop;
+		if (want_cookie)
+			NET_INC_STATS_BH(sock_net(sk),
+			      LINUX_MIB_TCPREQQFULLDOCOOKIES);
+		else {
+			NET_INC_STATS_BH(sock_net(sk),
+			    LINUX_MIB_TCPREQQFULLDROP);
+			goto drop;
+		}
 	}
 
 	/* Accept backlog is full. If we have already queued enough
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 78aa534..810ae64 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -530,20 +530,6 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
 	return tcp_v6_send_synack(sk, req, rvp);
 }
 
-static inline void syn_flood_warning(struct sk_buff *skb)
-{
-#ifdef CONFIG_SYN_COOKIES
-	if (sysctl_tcp_syncookies)
-		printk(KERN_INFO
-		       "TCPv6: Possible SYN flooding on port %d. "
-		       "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest));
-	else
-#endif
-		printk(KERN_INFO
-		       "TCPv6: Possible SYN flooding on port %d. "
-		       "Dropping request.\n", ntohs(tcp_hdr(skb)->dest));
-}
-
 static void tcp_v6_reqsk_destructor(struct request_sock *req)
 {
 	kfree_skb(inet6_rsk(req)->pktopts);
@@ -1191,14 +1177,17 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 		goto drop;
 
 	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
-		if (net_ratelimit())
-			syn_flood_warning(skb);
 #ifdef CONFIG_SYN_COOKIES
-		if (sysctl_tcp_syncookies)
-			want_cookie = 1;
-		else
+		want_cookie = sysctl_tcp_syncookies;
 #endif
-		goto drop;
+		if (want_cookie)
+			NET_INC_STATS_BH(sock_net(sk),
+			      LINUX_MIB_TCPREQQFULLDOCOOKIES);
+		else {
+			NET_INC_STATS_BH(sock_net(sk),
+			    LINUX_MIB_TCPREQQFULLDROP);
+			goto drop;
+		}
 	}
 
 	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
-- 
1.7.3.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] tcp: Replace possible syn attack msg by counters
  2011-08-11  5:38 [RFC PATCH] tcp: Replace possible syn attack msg by counters Tom Herbert
@ 2011-08-11  6:13 ` David Miller
  2011-08-11  6:33   ` Eric Dumazet
  2011-08-30 13:21 ` [PATCH v2] tcp: Change possible SYN flooding messages Eric Dumazet
  1 sibling, 1 reply; 8+ messages in thread
From: David Miller @ 2011-08-11  6:13 UTC (permalink / raw)
  To: therbert; +Cc: netdev

From: Tom Herbert <therbert@google.com>
Date: Wed, 10 Aug 2011 22:38:02 -0700 (PDT)

> Rather than printing the message to the log, use a mib counter to keep
> track of the count of occurences of syn cookies being used or syn
> being dropped when request queue is full.
> 
> Rationale is these messages can fill up /var/log/messages on server
> which is simply under heavy load... I'm not sure how much more useful
> they would be in identifying a server DOS attack (compared to
> counters).
> 
> Signed-off-by: Tom Herbert <therbert@google.com>

Print the message once, and also do the counters.

Say something like "Possible SYN flooding, see SNMP counters." or
similar.

Because if people are grepping for that message in their logs, they
will now have a false sense of confidence seeing it not being there
any more.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH] tcp: Replace possible syn attack msg by counters
  2011-08-11  6:13 ` David Miller
@ 2011-08-11  6:33   ` Eric Dumazet
  2011-08-12  6:08     ` [PATCH] tcp: Use LIMIT_NETDEBUG in syn_flood_warning() Eric Dumazet
  0 siblings, 1 reply; 8+ messages in thread
From: Eric Dumazet @ 2011-08-11  6:33 UTC (permalink / raw)
  To: David Miller; +Cc: therbert, netdev

Le mercredi 10 août 2011 à 23:13 -0700, David Miller a écrit :
> From: Tom Herbert <therbert@google.com>
> Date: Wed, 10 Aug 2011 22:38:02 -0700 (PDT)
> 
> > Rather than printing the message to the log, use a mib counter to keep
> > track of the count of occurences of syn cookies being used or syn
> > being dropped when request queue is full.
> > 
> > Rationale is these messages can fill up /var/log/messages on server
> > which is simply under heavy load... I'm not sure how much more useful
> > they would be in identifying a server DOS attack (compared to
> > counters).
> > 
> > Signed-off-by: Tom Herbert <therbert@google.com>
> 
> Print the message once, and also do the counters.
> 
> Say something like "Possible SYN flooding, see SNMP counters." or
> similar.
> 
> Because if people are grepping for that message in their logs, they
> will now have a false sense of confidence seeing it not being there
> any more.

An alternative would be to guard the message by net_msg_warn
(/proc/sys/net/core/warnings)

LIMIT_NETDEBUG(KERN_INFO "TCP: Possible SYN flooding on port %d. %s.\n" 
	...)




^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] tcp: Use LIMIT_NETDEBUG in syn_flood_warning()
  2011-08-11  6:33   ` Eric Dumazet
@ 2011-08-12  6:08     ` Eric Dumazet
  2011-08-15  3:20       ` Tom Herbert
  2011-08-15  6:39       ` David Miller
  0 siblings, 2 replies; 8+ messages in thread
From: Eric Dumazet @ 2011-08-12  6:08 UTC (permalink / raw)
  To: David Miller; +Cc: therbert, netdev

Le jeudi 11 août 2011 à 08:33 +0200, Eric Dumazet a écrit :
> Le mercredi 10 août 2011 à 23:13 -0700, David Miller a écrit :
> > From: Tom Herbert <therbert@google.com>
> > Date: Wed, 10 Aug 2011 22:38:02 -0700 (PDT)
> > 
> > > Rather than printing the message to the log, use a mib counter to keep
> > > track of the count of occurences of syn cookies being used or syn
> > > being dropped when request queue is full.
> > > 
> > > Rationale is these messages can fill up /var/log/messages on server
> > > which is simply under heavy load... I'm not sure how much more useful
> > > they would be in identifying a server DOS attack (compared to
> > > counters).
> > > 
> > > Signed-off-by: Tom Herbert <therbert@google.com>
> > 
> > Print the message once, and also do the counters.
> > 
> > Say something like "Possible SYN flooding, see SNMP counters." or
> > similar.
> > 
> > Because if people are grepping for that message in their logs, they
> > will now have a false sense of confidence seeing it not being there
> > any more.
> 
> An alternative would be to guard the message by net_msg_warn
> (/proc/sys/net/core/warnings)
> 
> LIMIT_NETDEBUG(KERN_INFO "TCP: Possible SYN flooding on port %d. %s.\n" 
> 	...)

Here is a patch implementing this.

We could add mib counters later in a second patch, inside
tcp_syn_flood_warning()

Thanks

[PATCH] tcp: Use LIMIT_NETDEBUG in syn_flood_warning()

LIMIT_NETDEBUG allows the admin to disable some warning messages :
echo 0 > /proc/sys/net/core/warnings

Use it to avoid filling syslog on busy servers.

Based on a previous patch from Tom Herbert

Factorize syn_flood_warning() IPv4/IPv6 implementations

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Tom Herbert <therbert@google.com>
---
 include/net/tcp.h   |    1 +
 net/ipv4/tcp_ipv4.c |   14 ++++++--------
 net/ipv6/tcp_ipv6.c |   17 +----------------
 3 files changed, 8 insertions(+), 24 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 149a415..964341c 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -460,6 +460,7 @@ extern int tcp_write_wakeup(struct sock *);
 extern void tcp_send_fin(struct sock *sk);
 extern void tcp_send_active_reset(struct sock *sk, gfp_t priority);
 extern int tcp_send_synack(struct sock *);
+extern void tcp_syn_flood_warning(const struct sk_buff *skb, const char *proto);
 extern void tcp_push_one(struct sock *, unsigned int mss_now);
 extern void tcp_send_ack(struct sock *sk);
 extern void tcp_send_delayed_ack(struct sock *sk);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 1c12b8e..9e622da 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -808,20 +808,19 @@ static void tcp_v4_reqsk_destructor(struct request_sock *req)
 	kfree(inet_rsk(req)->opt);
 }
 
-static void syn_flood_warning(const struct sk_buff *skb)
+void tcp_syn_flood_warning(const struct sk_buff *skb, const char *proto)
 {
-	const char *msg;
+	const char *msg = "Dropping request";
 
 #ifdef CONFIG_SYN_COOKIES
 	if (sysctl_tcp_syncookies)
 		msg = "Sending cookies";
-	else
 #endif
-		msg = "Dropping request";
 
-	pr_info("TCP: Possible SYN flooding on port %d. %s.\n",
-				ntohs(tcp_hdr(skb)->dest), msg);
+	LIMIT_NETDEBUG(KERN_INFO "%s: Possible SYN flooding on port %d. %s.\n",
+		       proto, ntohs(tcp_hdr(skb)->dest), msg);
 }
+EXPORT_SYMBOL(tcp_syn_flood_warning);
 
 /*
  * Save and compile IPv4 options into the request_sock if needed.
@@ -1250,8 +1249,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 	 * evidently real one.
 	 */
 	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
-		if (net_ratelimit())
-			syn_flood_warning(skb);
+		tcp_syn_flood_warning(skb, "TCP");
 #ifdef CONFIG_SYN_COOKIES
 		if (sysctl_tcp_syncookies) {
 			want_cookie = 1;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index d1fb63f..a043386 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -531,20 +531,6 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
 	return tcp_v6_send_synack(sk, req, rvp);
 }
 
-static inline void syn_flood_warning(struct sk_buff *skb)
-{
-#ifdef CONFIG_SYN_COOKIES
-	if (sysctl_tcp_syncookies)
-		printk(KERN_INFO
-		       "TCPv6: Possible SYN flooding on port %d. "
-		       "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest));
-	else
-#endif
-		printk(KERN_INFO
-		       "TCPv6: Possible SYN flooding on port %d. "
-		       "Dropping request.\n", ntohs(tcp_hdr(skb)->dest));
-}
-
 static void tcp_v6_reqsk_destructor(struct request_sock *req)
 {
 	kfree_skb(inet6_rsk(req)->pktopts);
@@ -1192,8 +1178,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 		goto drop;
 
 	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
-		if (net_ratelimit())
-			syn_flood_warning(skb);
+		tcp_syn_flood_warning(skb, "TCPv6");
 #ifdef CONFIG_SYN_COOKIES
 		if (sysctl_tcp_syncookies)
 			want_cookie = 1;



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] tcp: Use LIMIT_NETDEBUG in syn_flood_warning()
  2011-08-12  6:08     ` [PATCH] tcp: Use LIMIT_NETDEBUG in syn_flood_warning() Eric Dumazet
@ 2011-08-15  3:20       ` Tom Herbert
  2011-08-15  6:39       ` David Miller
  1 sibling, 0 replies; 8+ messages in thread
From: Tom Herbert @ 2011-08-15  3:20 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev

> [PATCH] tcp: Use LIMIT_NETDEBUG in syn_flood_warning()
>
> LIMIT_NETDEBUG allows the admin to disable some warning messages :
> echo 0 > /proc/sys/net/core/warnings
>
> Use it to avoid filling syslog on busy servers.
>
> Based on a previous patch from Tom Herbert
>
> Factorize syn_flood_warning() IPv4/IPv6 implementations
>

Acked-by: Tom Herbert <therbert@google.coml>

> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> CC: Tom Herbert <therbert@google.com>
> ---
>  include/net/tcp.h   |    1 +
>  net/ipv4/tcp_ipv4.c |   14 ++++++--------
>  net/ipv6/tcp_ipv6.c |   17 +----------------
>  3 files changed, 8 insertions(+), 24 deletions(-)
>
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index 149a415..964341c 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -460,6 +460,7 @@ extern int tcp_write_wakeup(struct sock *);
>  extern void tcp_send_fin(struct sock *sk);
>  extern void tcp_send_active_reset(struct sock *sk, gfp_t priority);
>  extern int tcp_send_synack(struct sock *);
> +extern void tcp_syn_flood_warning(const struct sk_buff *skb, const char *proto);
>  extern void tcp_push_one(struct sock *, unsigned int mss_now);
>  extern void tcp_send_ack(struct sock *sk);
>  extern void tcp_send_delayed_ack(struct sock *sk);
> diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
> index 1c12b8e..9e622da 100644
> --- a/net/ipv4/tcp_ipv4.c
> +++ b/net/ipv4/tcp_ipv4.c
> @@ -808,20 +808,19 @@ static void tcp_v4_reqsk_destructor(struct request_sock *req)
>        kfree(inet_rsk(req)->opt);
>  }
>
> -static void syn_flood_warning(const struct sk_buff *skb)
> +void tcp_syn_flood_warning(const struct sk_buff *skb, const char *proto)
>  {
> -       const char *msg;
> +       const char *msg = "Dropping request";
>
>  #ifdef CONFIG_SYN_COOKIES
>        if (sysctl_tcp_syncookies)
>                msg = "Sending cookies";
> -       else
>  #endif
> -               msg = "Dropping request";
>
> -       pr_info("TCP: Possible SYN flooding on port %d. %s.\n",
> -                               ntohs(tcp_hdr(skb)->dest), msg);
> +       LIMIT_NETDEBUG(KERN_INFO "%s: Possible SYN flooding on port %d. %s.\n",
> +                      proto, ntohs(tcp_hdr(skb)->dest), msg);
>  }
> +EXPORT_SYMBOL(tcp_syn_flood_warning);
>
>  /*
>  * Save and compile IPv4 options into the request_sock if needed.
> @@ -1250,8 +1249,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
>         * evidently real one.
>         */
>        if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
> -               if (net_ratelimit())
> -                       syn_flood_warning(skb);
> +               tcp_syn_flood_warning(skb, "TCP");
>  #ifdef CONFIG_SYN_COOKIES
>                if (sysctl_tcp_syncookies) {
>                        want_cookie = 1;
> diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
> index d1fb63f..a043386 100644
> --- a/net/ipv6/tcp_ipv6.c
> +++ b/net/ipv6/tcp_ipv6.c
> @@ -531,20 +531,6 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
>        return tcp_v6_send_synack(sk, req, rvp);
>  }
>
> -static inline void syn_flood_warning(struct sk_buff *skb)
> -{
> -#ifdef CONFIG_SYN_COOKIES
> -       if (sysctl_tcp_syncookies)
> -               printk(KERN_INFO
> -                      "TCPv6: Possible SYN flooding on port %d. "
> -                      "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest));
> -       else
> -#endif
> -               printk(KERN_INFO
> -                      "TCPv6: Possible SYN flooding on port %d. "
> -                      "Dropping request.\n", ntohs(tcp_hdr(skb)->dest));
> -}
> -
>  static void tcp_v6_reqsk_destructor(struct request_sock *req)
>  {
>        kfree_skb(inet6_rsk(req)->pktopts);
> @@ -1192,8 +1178,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
>                goto drop;
>
>        if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
> -               if (net_ratelimit())
> -                       syn_flood_warning(skb);
> +               tcp_syn_flood_warning(skb, "TCPv6");
>  #ifdef CONFIG_SYN_COOKIES
>                if (sysctl_tcp_syncookies)
>                        want_cookie = 1;
>
>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] tcp: Use LIMIT_NETDEBUG in syn_flood_warning()
  2011-08-12  6:08     ` [PATCH] tcp: Use LIMIT_NETDEBUG in syn_flood_warning() Eric Dumazet
  2011-08-15  3:20       ` Tom Herbert
@ 2011-08-15  6:39       ` David Miller
  1 sibling, 0 replies; 8+ messages in thread
From: David Miller @ 2011-08-15  6:39 UTC (permalink / raw)
  To: eric.dumazet; +Cc: therbert, netdev

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 12 Aug 2011 08:08:30 +0200

> [PATCH] tcp: Use LIMIT_NETDEBUG in syn_flood_warning()
> 
> LIMIT_NETDEBUG allows the admin to disable some warning messages :
> echo 0 > /proc/sys/net/core/warnings
> 
> Use it to avoid filling syslog on busy servers.
> 
> Based on a previous patch from Tom Herbert
> 
> Factorize syn_flood_warning() IPv4/IPv6 implementations
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> CC: Tom Herbert <therbert@google.com>

This is a big hammer with no granularity.

I have to give up other potentially interesting log messages (open
request drops, IP frag out-of-memory, etc.) just to get this one to go
away.

I still stand by my original suggestion, print unconditionally and
only once, and also add the statistics counters.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2] tcp: Change possible SYN flooding messages
  2011-08-11  5:38 [RFC PATCH] tcp: Replace possible syn attack msg by counters Tom Herbert
  2011-08-11  6:13 ` David Miller
@ 2011-08-30 13:21 ` Eric Dumazet
  2011-09-15 19:06   ` David Miller
  1 sibling, 1 reply; 8+ messages in thread
From: Eric Dumazet @ 2011-08-30 13:21 UTC (permalink / raw)
  To: Tom Herbert, David Miller; +Cc: netdev

"Possible SYN flooding on port xxxx " messages can fill logs on servers.

Change logic to log the message only once per listener, and add two new
SNMP counters to track :

TCPReqQFullDoCookies : number of times a SYNCOOKIE was replied to client

TCPReqQFullDrop : number of times a SYN request was dropped because
syncookies were not enabled.

Based on a prior patch from Tom Herbert, and suggestions from David.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Tom Herbert <therbert@google.com>
---
 include/linux/snmp.h       |    2 +
 include/net/request_sock.h |    3 +-
 include/net/tcp.h          |    3 ++
 net/ipv4/proc.c            |    2 +
 net/ipv4/tcp_ipv4.c        |   49 ++++++++++++++++++++---------------
 net/ipv6/tcp_ipv6.c        |   31 ++--------------------
 6 files changed, 40 insertions(+), 50 deletions(-)

diff --git a/include/linux/snmp.h b/include/linux/snmp.h
index 12b2b18..e16557a 100644
--- a/include/linux/snmp.h
+++ b/include/linux/snmp.h
@@ -231,6 +231,8 @@ enum
 	LINUX_MIB_TCPDEFERACCEPTDROP,
 	LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */
 	LINUX_MIB_TCPTIMEWAITOVERFLOW,		/* TCPTimeWaitOverflow */
+	LINUX_MIB_TCPREQQFULLDOCOOKIES,		/* TCPReqQFullDoCookies */
+	LINUX_MIB_TCPREQQFULLDROP,		/* TCPReqQFullDrop */
 	__LINUX_MIB_MAX
 };
 
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 99e6e19..4c0766e 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -96,7 +96,8 @@ extern int sysctl_max_syn_backlog;
  */
 struct listen_sock {
 	u8			max_qlen_log;
-	/* 3 bytes hole, try to use */
+	u8			synflood_warned;
+	/* 2 bytes hole, try to use */
 	int			qlen;
 	int			qlen_young;
 	int			clock_hand;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 149a415..e9b48b0 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -460,6 +460,9 @@ extern int tcp_write_wakeup(struct sock *);
 extern void tcp_send_fin(struct sock *sk);
 extern void tcp_send_active_reset(struct sock *sk, gfp_t priority);
 extern int tcp_send_synack(struct sock *);
+extern int tcp_syn_flood_action(struct sock *sk,
+				const struct sk_buff *skb,
+				const char *proto);
 extern void tcp_push_one(struct sock *, unsigned int mss_now);
 extern void tcp_send_ack(struct sock *sk);
 extern void tcp_send_delayed_ack(struct sock *sk);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index b14ec7d..4bfad5d 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -254,6 +254,8 @@ static const struct snmp_mib snmp4_net_list[] = {
 	SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP),
 	SNMP_MIB_ITEM("IPReversePathFilter", LINUX_MIB_IPRPFILTER),
 	SNMP_MIB_ITEM("TCPTimeWaitOverflow", LINUX_MIB_TCPTIMEWAITOVERFLOW),
+	SNMP_MIB_ITEM("TCPReqQFullDoCookies", LINUX_MIB_TCPREQQFULLDOCOOKIES),
+	SNMP_MIB_ITEM("TCPReqQFullDrop", LINUX_MIB_TCPREQQFULLDROP),
 	SNMP_MIB_SENTINEL
 };
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index b3f2611..c29912c 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -808,20 +808,38 @@ static void tcp_v4_reqsk_destructor(struct request_sock *req)
 	kfree(inet_rsk(req)->opt);
 }
 
-static void syn_flood_warning(const struct sk_buff *skb)
+/*
+ * Return 1 if a syncookie should be sent
+ */
+int tcp_syn_flood_action(struct sock *sk,
+			 const struct sk_buff *skb,
+			 const char *proto)
 {
-	const char *msg;
+	const char *msg = "Dropping request";
+	int want_cookie = 0;
+	struct listen_sock *lopt;
+
+
 
 #ifdef CONFIG_SYN_COOKIES
-	if (sysctl_tcp_syncookies)
+	if (sysctl_tcp_syncookies) {
 		msg = "Sending cookies";
-	else
+		want_cookie = 1;
+		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES);
+	} else
 #endif
-		msg = "Dropping request";
+		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP);
 
-	pr_info("TCP: Possible SYN flooding on port %d. %s.\n",
-				ntohs(tcp_hdr(skb)->dest), msg);
+	lopt = inet_csk(sk)->icsk_accept_queue.listen_opt;
+	if (!lopt->synflood_warned) {
+		lopt->synflood_warned = 1;
+		pr_info("%s: Possible SYN flooding on port %d. %s. "
+			" Check SNMP counters.\n",
+			proto, ntohs(tcp_hdr(skb)->dest), msg);
+	}
+	return want_cookie;
 }
+EXPORT_SYMBOL(tcp_syn_flood_action);
 
 /*
  * Save and compile IPv4 options into the request_sock if needed.
@@ -1235,11 +1253,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 	__be32 saddr = ip_hdr(skb)->saddr;
 	__be32 daddr = ip_hdr(skb)->daddr;
 	__u32 isn = TCP_SKB_CB(skb)->when;
-#ifdef CONFIG_SYN_COOKIES
 	int want_cookie = 0;
-#else
-#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
-#endif
 
 	/* Never answer to SYNs send to broadcast or multicast */
 	if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
@@ -1250,14 +1264,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 	 * evidently real one.
 	 */
 	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
-		if (net_ratelimit())
-			syn_flood_warning(skb);
-#ifdef CONFIG_SYN_COOKIES
-		if (sysctl_tcp_syncookies) {
-			want_cookie = 1;
-		} else
-#endif
-		goto drop;
+		want_cookie = tcp_syn_flood_action(sk, skb, "TCP");
+		if (!want_cookie)
+			goto drop;
 	}
 
 	/* Accept backlog is full. If we have already queued enough
@@ -1303,9 +1312,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 		while (l-- > 0)
 			*c++ ^= *hash_location++;
 
-#ifdef CONFIG_SYN_COOKIES
 		want_cookie = 0;	/* not our kind of cookie */
-#endif
 		tmp_ext.cookie_out_never = 0; /* false */
 		tmp_ext.cookie_plus = tmp_opt.cookie_plus;
 	} else if (!tp->rx_opt.cookie_in_always) {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 44a5859..12bdb9a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -531,20 +531,6 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
 	return tcp_v6_send_synack(sk, req, rvp);
 }
 
-static inline void syn_flood_warning(struct sk_buff *skb)
-{
-#ifdef CONFIG_SYN_COOKIES
-	if (sysctl_tcp_syncookies)
-		printk(KERN_INFO
-		       "TCPv6: Possible SYN flooding on port %d. "
-		       "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest));
-	else
-#endif
-		printk(KERN_INFO
-		       "TCPv6: Possible SYN flooding on port %d. "
-		       "Dropping request.\n", ntohs(tcp_hdr(skb)->dest));
-}
-
 static void tcp_v6_reqsk_destructor(struct request_sock *req)
 {
 	kfree_skb(inet6_rsk(req)->pktopts);
@@ -1179,11 +1165,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 	struct tcp_sock *tp = tcp_sk(sk);
 	__u32 isn = TCP_SKB_CB(skb)->when;
 	struct dst_entry *dst = NULL;
-#ifdef CONFIG_SYN_COOKIES
 	int want_cookie = 0;
-#else
-#define want_cookie 0
-#endif
 
 	if (skb->protocol == htons(ETH_P_IP))
 		return tcp_v4_conn_request(sk, skb);
@@ -1192,14 +1174,9 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 		goto drop;
 
 	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
-		if (net_ratelimit())
-			syn_flood_warning(skb);
-#ifdef CONFIG_SYN_COOKIES
-		if (sysctl_tcp_syncookies)
-			want_cookie = 1;
-		else
-#endif
-		goto drop;
+		want_cookie = tcp_syn_flood_action(sk, skb, "TCPv6");
+		if (!want_cookie)
+			goto drop;
 	}
 
 	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
@@ -1249,9 +1226,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 		while (l-- > 0)
 			*c++ ^= *hash_location++;
 
-#ifdef CONFIG_SYN_COOKIES
 		want_cookie = 0;	/* not our kind of cookie */
-#endif
 		tmp_ext.cookie_out_never = 0; /* false */
 		tmp_ext.cookie_plus = tmp_opt.cookie_plus;
 	} else if (!tp->rx_opt.cookie_in_always) {

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2] tcp: Change possible SYN flooding messages
  2011-08-30 13:21 ` [PATCH v2] tcp: Change possible SYN flooding messages Eric Dumazet
@ 2011-09-15 19:06   ` David Miller
  0 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2011-09-15 19:06 UTC (permalink / raw)
  To: eric.dumazet; +Cc: therbert, netdev

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 30 Aug 2011 15:21:44 +0200

> "Possible SYN flooding on port xxxx " messages can fill logs on servers.
> 
> Change logic to log the message only once per listener, and add two new
> SNMP counters to track :
> 
> TCPReqQFullDoCookies : number of times a SYNCOOKIE was replied to client
> 
> TCPReqQFullDrop : number of times a SYN request was dropped because
> syncookies were not enabled.
> 
> Based on a prior patch from Tom Herbert, and suggestions from David.
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied, thanks Eric.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-09-15 19:07 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-11  5:38 [RFC PATCH] tcp: Replace possible syn attack msg by counters Tom Herbert
2011-08-11  6:13 ` David Miller
2011-08-11  6:33   ` Eric Dumazet
2011-08-12  6:08     ` [PATCH] tcp: Use LIMIT_NETDEBUG in syn_flood_warning() Eric Dumazet
2011-08-15  3:20       ` Tom Herbert
2011-08-15  6:39       ` David Miller
2011-08-30 13:21 ` [PATCH v2] tcp: Change possible SYN flooding messages Eric Dumazet
2011-09-15 19:06   ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).