Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 946cedcc authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

tcp: Change possible SYN flooding messages



"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: default avatarEric Dumazet <eric.dumazet@gmail.com>
CC: Tom Herbert <therbert@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 27e95a8c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
};

+2 −1
Original line number Diff line number Diff line
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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
};

+28 −21
Original line number Diff line number Diff line
@@ -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,13 +1264,8 @@ 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
		want_cookie = tcp_syn_flood_action(sk, skb, "TCP");
		if (!want_cookie)
			goto drop;
	}

@@ -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) {
Loading