Skip to contentSkip to conversation

add a sysctl to disable TCP simultaneous connection opening

PATCH In review Willy Tarreau 8 participants 21 messages Oct 8, 2008 – Oct 10, 2008 1 message not in the archive

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 add a sysctl to disable TCP simultaneous connection opening

Hi David,

I hope you had a pleasant journey in Paris last week. It was nice to meet you.

In 2005, I submitted a patch for 2.6.11 which we finally did not decide on, it was about the ability to disable TCP simultaneous connection open.

For the last few years, we've been bothered several times by newbies reading "TCP/IP for dummies" then trying to get a name by discovering the ultimate vulnerability which will get a lot of press coverage. Of course those attacks are often pointless or just proofs of concepts with no application in real life, but it's nonetheless annoying to have to deal with the issues, especially to explain to customers why they shouldn't have to worry.

I would not be surprized that a next one will exploit TCP's ability to perform simultaneous connections between two clients. It's very easy to trigger, there's no SEQ to guess, just a port, and the effect is simply a poor DoS on the service trying to connect outside. In other times we would have found it very minor, but judging by the consideration given to harder and less effective "attacks" these days, this trivial one may finally get picked and annoy us again.

As a reminder (especially for those who are not aware of this feature), it is possible with TCP to connect two clients together if both send crossed SYNs, then SYN-ACKs, then ACKs. This implies that each side accepts the sequence number of the other one without any ability to check that it matches its SYN. So it's trivial for an attacker to prevent one client from establishing a connection from a known port to a known address/port by sending it a SYN to that port. The client will then send a SYN-ACK and will not accept the expected server's SYN-ACK because the SYN SEQ will be different. The server might also send an RST on the client's SYN-ACK if it's not firewalled. The connection will eventually timeout in a SYN-RECV state or simply be aborted.

The theorical DoS effect on some predictable address/port destinations is easy to understand. Services with very few destination IP/ports such as software/signature updates, SMTP relaying, DNS clients for zone transfers, or SSH remote accesses are easy targets. In practice, the SYN would have to be sent after the client's SYN and before the server's SYN-ACK, which leaves a small time window limiting the attack to far remote, unfirewalled communications.

This is very easy to test, I'm used to do it between two netcats, and preventing the initial RST by unplugging the cable before sending the connects. I remember it also worked on Solaris 8, and I don't remember about BSDs (though I would not be surprized they support it too).

IMHO this feature is totally useless nowadays, because :
- if one of the machines is firewalled, the firewall will block it (none of the firewalls I've tested among Netfilter, Checkpoint, Cisco, Fortinet, Juniper supports simultaneous connect, and it would cause a big security issue).

- if neither machines are firewalled, then the SYN to a closed port will immediately trigger an RST, making it very difficult to establish a working connection.

For this reason, I'd like that we plan on merging the attached patch (or any variant) for 2.6.28 or 2.6.29 before a new random junkie comes aroung screaming loud he uncovered a big DoS hole in Linux TCP stack. The patch provides a sysctl allowing the user to enable or disable the feature. I've been running all my kernels with the code ifdef'ed out for the last 4-5 years, but I certainly can understand that some people want to be able to enable it for any reason (even for educationnal purposes), hence the sysctl.

I have rediffed the patch for 2.6.27-rc9 and successfully tested it (both with feature enabled and disabled). It disables the feature by default, but I have no problem with leaving it on and expecting that distros will ship it off.

By the way, during the tests I noticed something strange. While the socket is in SYN_RECV on the first side to receive the other one's SYN, it has a huge receive queue :

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 3964220580 1 192.32.189.160:12346 192.32.189.228:4000 SYN_RECV

The value corresponds to the ACK value emitted, which is equal to the other end's SYN+1. I don't know if this is just an artefact of the way the queue size is reported (probably because the first ACK has not yet been considered since we're not in ESTABLISHED state) or if this can have any further impact (eg: unexpected memory freeing on termination, etc...).

Best regards,
Willy

Quoted 1 line

From 61abc5ef6c3bc210c63036b5f36cc96a7802b605 Mon Sep 17 00:00:00 2001

From: Willy Tarreau <[email protected]>
Date: Wed, 8 Oct 2008 10:00:42 +0200
Subject: TCP: add a sysctl to disable simultaneous connection opening.

Strict implementation of RFC793 (TCP) requires support for a feature called "simultaneous connect", which allows two clients to connect to each other without anyone entering a listening state. While almost never used, and supported by few OSes, Linux supports this feature.

However, it introduces a weakness in the protocol which makes it very easy for an attacker to prevent a client from connecting to a known server. The attacker only has to guess the source port to shut down the client connection during its establishment. The impact is limited, but it may be used to prevent an antivirus or IPS from fetching updates and not detecting an attack, or to prevent an SSL gateway from fetching a CRL for example.

This patch provides a new sysctl "tcp_simult_connect" to enable or disable support for this useless feature. It comes disabled by default.

Hundreds of systems running with that feature disabled for more than 4 years have never encountered an application which requires it. It is almost never supported by firewalls BTW.

---
 Documentation/networking/ip-sysctl.txt |   22 ++++++++++++++++++++++
 include/linux/sysctl.h                 |    1 +
 include/net/tcp.h                      |    1 +
 net/ipv4/sysctl_net_ipv4.c             |    8 ++++++++
 net/ipv4/tcp_input.c                   |    5 ++++-
 5 files changed, 36 insertions(+), 1 deletions(-)
Documentation/networking/ip-sysctl.txt +22 -0
index d849326..cefc894 100644
@@ -101,6 +101,28 @@ inet_peer_gc_maxtime - INTEGER
 
 TCP variables: 
 
+tcp_simult_connect - BOOLEAN
+	Enables TCP simultaneous connect feature conforming to RFC793.
+	Strict implementation of RFC793 (TCP) requires support for a feature
+	called "simultaneous connect", which allows two clients to connect to
+	each other without anyone entering a listening state.  While almost
+	never used, and supported by few OSes, Linux supports this feature.
+
+	However, it introduces a weakness in the protocol which makes it very
+	easy for an attacker to prevent a client from connecting to a known
+	server. The attacker only has to guess the source port to shut down
+	the client connection during its establishment. The impact is limited,
+	but it may be used to prevent an antivirus or IPS from fetching updates
+	and not detecting an attack, or to prevent an SSL gateway from fetching
+	a CRL for example.
+
+	If you want absolute compatibility with any possible application,
+	you should set it to 1. If you prefer to enhance security on your
+	systems you'd better let it to 0. After four years of usage on
+	hundreds of systems, no application was ever found to require this
+	feature, which is not even supported by most firewalls.
+	Default: 0
+
 somaxconn - INTEGER
 	Limit of socket listen() backlog, known in userspace as SOMAXCONN.
 	Defaults to 128.  See also tcp_max_syn_backlog for additional tuning
include/linux/sysctl.h +1 -0
index d0437f3..0e23062 100644
@@ -435,6 +435,7 @@ enum
 	NET_TCP_ALLOWED_CONG_CONTROL=123,
 	NET_TCP_MAX_SSTHRESH=124,
 	NET_TCP_FRTO_RESPONSE=125,
+	NET_TCP_SIMULT_CONNECT=126,
 };
 
 enum {
include/net/tcp.h +1 -0
index 8983386..c61fe3c 100644
@@ -236,6 +236,7 @@ extern int sysctl_tcp_base_mss;
 extern int sysctl_tcp_workaround_signed_windows;
 extern int sysctl_tcp_slow_start_after_idle;
 extern int sysctl_tcp_max_ssthresh;
+extern int sysctl_tcp_simult_connect;
 
 extern atomic_t tcp_memory_allocated;
 extern atomic_t tcp_sockets_allocated;
net/ipv4/sysctl_net_ipv4.c +8 -0
index e0689fd..d2a73ec 100644
@@ -716,6 +716,14 @@ static struct ctl_table ipv4_table[] = {
 		.proc_handler	= &proc_dointvec,
 	},
 	{
+		.ctl_name	= NET_TCP_SIMULT_CONNECT,
+		.procname	= "tcp_simult_connect",
+		.data		= &sysctl_tcp_simult_connect,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "udp_mem",
 		.data		= &sysctl_udp_mem,
net/ipv4/tcp_input.c +4 -1
index 67ccce2..932504e 100644
@@ -87,6 +87,7 @@ int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
 int sysctl_tcp_frto __read_mostly = 2;
 int sysctl_tcp_frto_response __read_mostly;
 int sysctl_tcp_nometrics_save __read_mostly;
+int sysctl_tcp_simult_connect __read_mostly;
 
 int sysctl_tcp_moderate_rcvbuf __read_mostly = 1;
 int sysctl_tcp_abc __read_mostly;
@@ -5149,10 +5150,12 @@ discard:
 	    tcp_paws_check(&tp->rx_opt, 0))
 		goto discard_and_undo;
 
-	if (th->syn) {
+	if (th->syn && sysctl_tcp_simult_connect) {
 		/* We see SYN without ACK. It is attempt of
 		 * simultaneous connect with crossed SYNs.
 		 * Particularly, it can be connect to self.
+		 * This feature is disabled by default as it introduces a
+		 * weakness in the protocol. It can be enabled by a sysctl.
 		 */
 		tcp_set_state(sk, TCP_SYN_RECV);
 
Signature · 1 line
1.5.3.3

A message that is not in the archive (sent off-list or not yet received): 20081008081109.GA25342-K+wRfnb2/[email protected]

#2 lore raw

[[email protected]]

(As very recently noted in SubmittingPatches)

Quoted 236 lines · Willy Tarreau

Hi David,

I hope you had a pleasant journey in Paris last week. It was nice to meet you.

In 2005, I submitted a patch for 2.6.11 which we finally did not decide on, it was about the ability to disable TCP simultaneous connection open.

For the last few years, we've been bothered several times by newbies reading "TCP/IP for dummies" then trying to get a name by discovering the ultimate vulnerability which will get a lot of press coverage. Of course those attacks are often pointless or just proofs of concepts with no application in real life, but it's nonetheless annoying to have to deal with the issues, especially to explain to customers why they shouldn't have to worry.

I would not be surprized that a next one will exploit TCP's ability to perform simultaneous connections between two clients. It's very easy to trigger, there's no SEQ to guess, just a port, and the effect is simply a poor DoS on the service trying to connect outside. In other times we would have found it very minor, but judging by the consideration given to harder and less effective "attacks" these days, this trivial one may finally get picked and annoy us again.

As a reminder (especially for those who are not aware of this feature), it is possible with TCP to connect two clients together if both send crossed SYNs, then SYN-ACKs, then ACKs. This implies that each side accepts the sequence number of the other one without any ability to check that it matches its SYN. So it's trivial for an attacker to prevent one client from establishing a connection from a known port to a known address/port by sending it a SYN to that port. The client will then send a SYN-ACK and will not accept the expected server's SYN-ACK because the SYN SEQ will be different. The server might also send an RST on the client's SYN-ACK if it's not firewalled. The connection will eventually timeout in a SYN-RECV state or simply be aborted.

The theorical DoS effect on some predictable address/port destinations is easy to understand. Services with very few destination IP/ports such as software/signature updates, SMTP relaying, DNS clients for zone transfers, or SSH remote accesses are easy targets. In practice, the SYN would have to be sent after the client's SYN and before the server's SYN-ACK, which leaves a small time window limiting the attack to far remote, unfirewalled communications.

This is very easy to test, I'm used to do it between two netcats, and preventing the initial RST by unplugging the cable before sending the connects. I remember it also worked on Solaris 8, and I don't remember about BSDs (though I would not be surprized they support it too).

IMHO this feature is totally useless nowadays, because :
- if one of the machines is firewalled, the firewall will block it (none of the firewalls I've tested among Netfilter, Checkpoint, Cisco, Fortinet, Juniper supports simultaneous connect, and it would cause a big security issue).

- if neither machines are firewalled, then the SYN to a closed port will immediately trigger an RST, making it very difficult to establish a working connection.

For this reason, I'd like that we plan on merging the attached patch (or any variant) for 2.6.28 or 2.6.29 before a new random junkie comes aroung screaming loud he uncovered a big DoS hole in Linux TCP stack. The patch provides a sysctl allowing the user to enable or disable the feature. I've been running all my kernels with the code ifdef'ed out for the last 4-5 years, but I certainly can understand that some people want to be able to enable it for any reason (even for educationnal purposes), hence the sysctl.

I have rediffed the patch for 2.6.27-rc9 and successfully tested it (both with feature enabled and disabled). It disables the feature by default, but I have no problem with leaving it on and expecting that distros will ship it off.

By the way, during the tests I noticed something strange. While the socket is in SYN_RECV on the first side to receive the other one's SYN, it has a huge receive queue :

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 3964220580 1 192.32.189.160:12346 192.32.189.228:4000 SYN_RECV

The value corresponds to the ACK value emitted, which is equal to the other end's SYN+1. I don't know if this is just an artefact of the way the queue size is reported (probably because the first ACK has not yet been considered since we're not in ESTABLISHED state) or if this can have any further impact (eg: unexpected memory freeing on termination, etc...).

Best regards,
Willy

From 61abc5ef6c3bc210c63036b5f36cc96a7802b605 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <[email protected]>
Date: Wed, 8 Oct 2008 10:00:42 +0200
Subject: TCP: add a sysctl to disable simultaneous connection opening.

Strict implementation of RFC793 (TCP) requires support for a feature called "simultaneous connect", which allows two clients to connect to each other without anyone entering a listening state. While almost never used, and supported by few OSes, Linux supports this feature.

However, it introduces a weakness in the protocol which makes it very easy for an attacker to prevent a client from connecting to a known server. The attacker only has to guess the source port to shut down the client connection during its establishment. The impact is limited, but it may be used to prevent an antivirus or IPS from fetching updates and not detecting an attack, or to prevent an SSL gateway from fetching a CRL for example.

This patch provides a new sysctl "tcp_simult_connect" to enable or disable support for this useless feature. It comes disabled by default.

Hundreds of systems running with that feature disabled for more than 4 years have never encountered an application which requires it. It is almost never supported by firewalls BTW.

---
 Documentation/networking/ip-sysctl.txt |   22 ++++++++++++++++++++++
 include/linux/sysctl.h                 |    1 +
 include/net/tcp.h                      |    1 +
 net/ipv4/sysctl_net_ipv4.c             |    8 ++++++++
 net/ipv4/tcp_input.c                   |    5 ++++-
 5 files changed, 36 insertions(+), 1 deletions(-)
Documentation/networking/ip-sysctl.txt +22 -0
index d849326..cefc894 100644
@@ -101,6 +101,28 @@ inet_peer_gc_maxtime - INTEGER
 
 TCP variables:
 
+tcp_simult_connect - BOOLEAN
+       Enables TCP simultaneous connect feature conforming to RFC793.
+       Strict implementation of RFC793 (TCP) requires support for a feature
+       called "simultaneous connect", which allows two clients to connect to
+       each other without anyone entering a listening state.  While almost
+       never used, and supported by few OSes, Linux supports this feature.
+
+       However, it introduces a weakness in the protocol which makes it very
+       easy for an attacker to prevent a client from connecting to a known
+       server. The attacker only has to guess the source port to shut down
+       the client connection during its establishment. The impact is limited,
+       but it may be used to prevent an antivirus or IPS from fetching updates
+       and not detecting an attack, or to prevent an SSL gateway from fetching
+       a CRL for example.
+
+       If you want absolute compatibility with any possible application,
+       you should set it to 1. If you prefer to enhance security on your
+       systems you'd better let it to 0. After four years of usage on
+       hundreds of systems, no application was ever found to require this
+       feature, which is not even supported by most firewalls.
+       Default: 0
+
 somaxconn - INTEGER
       Limit of socket listen() backlog, known in userspace as SOMAXCONN.
       Defaults to 128.  See also tcp_max_syn_backlog for additional tuning
include/linux/sysctl.h +1 -0
index d0437f3..0e23062 100644
@@ -435,6 +435,7 @@ enum
       NET_TCP_ALLOWED_CONG_CONTROL=123,
       NET_TCP_MAX_SSTHRESH=124,
       NET_TCP_FRTO_RESPONSE=125,
+       NET_TCP_SIMULT_CONNECT=126,
 };
 
 enum {
include/net/tcp.h +1 -0
index 8983386..c61fe3c 100644
@@ -236,6 +236,7 @@ extern int sysctl_tcp_base_mss;
 extern int sysctl_tcp_workaround_signed_windows;
 extern int sysctl_tcp_slow_start_after_idle;
 extern int sysctl_tcp_max_ssthresh;
+extern int sysctl_tcp_simult_connect;
 
 extern atomic_t tcp_memory_allocated;
 extern atomic_t tcp_sockets_allocated;
net/ipv4/sysctl_net_ipv4.c +8 -0
index e0689fd..d2a73ec 100644
@@ -716,6 +716,14 @@ static struct ctl_table ipv4_table[] = {
               .proc_handler   = &proc_dointvec,
       },
       {
+               .ctl_name       = NET_TCP_SIMULT_CONNECT,
+               .procname       = "tcp_simult_connect",
+               .data           = &sysctl_tcp_simult_connect,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+       {
               .ctl_name       = CTL_UNNUMBERED,
               .procname       = "udp_mem",
               .data           = &sysctl_udp_mem,
net/ipv4/tcp_input.c +4 -2
index 67ccce2..932504e 100644
@@ -87,6 +87,7 @@ int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
 int sysctl_tcp_frto __read_mostly = 2;
 int sysctl_tcp_frto_response __read_mostly;
 int sysctl_tcp_nometrics_save __read_mostly;
+int sysctl_tcp_simult_connect __read_mostly;
 
 int sysctl_tcp_moderate_rcvbuf __read_mostly = 1;
 int sysctl_tcp_abc __read_mostly;
@@ -5149,10 +5150,12 @@ discard:
           tcp_paws_check(&tp->rx_opt, 0))
               goto discard_and_undo;
 
-       if (th->syn) {
+       if (th->syn && sysctl_tcp_simult_connect) {
               /* We see SYN without ACK. It is attempt of
                * simultaneous connect with crossed SYNs.
                * Particularly, it can be connect to self.
+                * This feature is disabled by default as it introduces a
+                * weakness in the protocol. It can be enabled by a sysctl.
                */
               tcp_set_state(sk, TCP_SYN_RECV);
 
--

1.5.3.3

--
To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer;
http://www.kernel.org/doc/man-pages/ Found a documentation bug?
http://www.kernel.org/doc/man-pages/reporting_bugs.html
--
To unsubscribe from this list: send the line "unsubscribe linux-api" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#3 lore raw
In reply to Willy Tarreau
Quoted 88 lines · On Wed, 8 Oct 2008 10:11:09 +0200 Willy Tarreau <[email protected]> wrote:

Hi David,

I hope you had a pleasant journey in Paris last week. It was nice to meet you.

In 2005, I submitted a patch for 2.6.11 which we finally did not decide on, it was about the ability to disable TCP simultaneous connection open.

For the last few years, we've been bothered several times by newbies reading "TCP/IP for dummies" then trying to get a name by discovering the ultimate vulnerability which will get a lot of press coverage. Of course those attacks are often pointless or just proofs of concepts with no application in real life, but it's nonetheless annoying to have to deal with the issues, especially to explain to customers why they shouldn't have to worry.

I would not be surprized that a next one will exploit TCP's ability to perform simultaneous connections between two clients. It's very easy to trigger, there's no SEQ to guess, just a port, and the effect is simply a poor DoS on the service trying to connect outside. In other times we would have found it very minor, but judging by the consideration given to harder and less effective "attacks" these days, this trivial one may finally get picked and annoy us again.

As a reminder (especially for those who are not aware of this feature), it is possible with TCP to connect two clients together if both send crossed SYNs, then SYN-ACKs, then ACKs. This implies that each side accepts the sequence number of the other one without any ability to check that it matches its SYN. So it's trivial for an attacker to prevent one client from establishing a connection from a known port to a known address/port by sending it a SYN to that port. The client will then send a SYN-ACK and will not accept the expected server's SYN-ACK because the SYN SEQ will be different. The server might also send an RST on the client's SYN-ACK if it's not firewalled. The connection will eventually timeout in a SYN-RECV state or simply be aborted.

The theorical DoS effect on some predictable address/port destinations is easy to understand. Services with very few destination IP/ports such as software/signature updates, SMTP relaying, DNS clients for zone transfers, or SSH remote accesses are easy targets. In practice, the SYN would have to be sent after the client's SYN and before the server's SYN-ACK, which leaves a small time window limiting the attack to far remote, unfirewalled communications.

This is very easy to test, I'm used to do it between two netcats, and preventing the initial RST by unplugging the cable before sending the connects. I remember it also worked on Solaris 8, and I don't remember about BSDs (though I would not be surprized they support it too).

IMHO this feature is totally useless nowadays, because :
- if one of the machines is firewalled, the firewall will block it (none of the firewalls I've tested among Netfilter, Checkpoint, Cisco, Fortinet, Juniper supports simultaneous connect, and it would cause a big security issue).

- if neither machines are firewalled, then the SYN to a closed port will immediately trigger an RST, making it very difficult to establish a working connection.

For this reason, I'd like that we plan on merging the attached patch (or any variant) for 2.6.28 or 2.6.29 before a new random junkie comes aroung screaming loud he uncovered a big DoS hole in Linux TCP stack. The patch provides a sysctl allowing the user to enable or disable the feature. I've been running all my kernels with the code ifdef'ed out for the last 4-5 years, but I certainly can understand that some people want to be able to enable it for any reason (even for educationnal purposes), hence the sysctl.

I have rediffed the patch for 2.6.27-rc9 and successfully tested it (both with feature enabled and disabled). It disables the feature by default, but I have no problem with leaving it on and expecting that distros will ship it off.

By the way, during the tests I noticed something strange. While the socket is in SYN_RECV on the first side to receive the other one's SYN, it has a huge receive queue :

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 3964220580 1 192.32.189.160:12346 192.32.189.228:4000 SYN_RECV

The value corresponds to the ACK value emitted, which is equal to the other end's SYN+1. I don't know if this is just an artefact of the way the queue size is reported (probably because the first ACK has not yet been considered since we're not in ESTABLISHED state) or if this can have any further impact (eg: unexpected memory freeing on termination, etc...).

Quoted 2 lines

Best regards,
Willy

Does this break NAT traversal via STUNT used by applications like Skype?

#4 lore raw

Hi Stephen,

Quoted 91 lines · Stephen Hemminger
Quoted 88 lines · On Wed, 8 Oct 2008 10:11:09 +0200 Willy Tarreau <[email protected]> wrote:

Hi David,

I hope you had a pleasant journey in Paris last week. It was nice to meet you.

In 2005, I submitted a patch for 2.6.11 which we finally did not decide on, it was about the ability to disable TCP simultaneous connection open.

For the last few years, we've been bothered several times by newbies reading "TCP/IP for dummies" then trying to get a name by discovering the ultimate vulnerability which will get a lot of press coverage. Of course those attacks are often pointless or just proofs of concepts with no application in real life, but it's nonetheless annoying to have to deal with the issues, especially to explain to customers why they shouldn't have to worry.

I would not be surprized that a next one will exploit TCP's ability to perform simultaneous connections between two clients. It's very easy to trigger, there's no SEQ to guess, just a port, and the effect is simply a poor DoS on the service trying to connect outside. In other times we would have found it very minor, but judging by the consideration given to harder and less effective "attacks" these days, this trivial one may finally get picked and annoy us again.

As a reminder (especially for those who are not aware of this feature), it is possible with TCP to connect two clients together if both send crossed SYNs, then SYN-ACKs, then ACKs. This implies that each side accepts the sequence number of the other one without any ability to check that it matches its SYN. So it's trivial for an attacker to prevent one client from establishing a connection from a known port to a known address/port by sending it a SYN to that port. The client will then send a SYN-ACK and will not accept the expected server's SYN-ACK because the SYN SEQ will be different. The server might also send an RST on the client's SYN-ACK if it's not firewalled. The connection will eventually timeout in a SYN-RECV state or simply be aborted.

The theorical DoS effect on some predictable address/port destinations is easy to understand. Services with very few destination IP/ports such as software/signature updates, SMTP relaying, DNS clients for zone transfers, or SSH remote accesses are easy targets. In practice, the SYN would have to be sent after the client's SYN and before the server's SYN-ACK, which leaves a small time window limiting the attack to far remote, unfirewalled communications.

This is very easy to test, I'm used to do it between two netcats, and preventing the initial RST by unplugging the cable before sending the connects. I remember it also worked on Solaris 8, and I don't remember about BSDs (though I would not be surprized they support it too).

IMHO this feature is totally useless nowadays, because :
- if one of the machines is firewalled, the firewall will block it (none of the firewalls I've tested among Netfilter, Checkpoint, Cisco, Fortinet, Juniper supports simultaneous connect, and it would cause a big security issue).

- if neither machines are firewalled, then the SYN to a closed port will immediately trigger an RST, making it very difficult to establish a working connection.

For this reason, I'd like that we plan on merging the attached patch (or any variant) for 2.6.28 or 2.6.29 before a new random junkie comes aroung screaming loud he uncovered a big DoS hole in Linux TCP stack. The patch provides a sysctl allowing the user to enable or disable the feature. I've been running all my kernels with the code ifdef'ed out for the last 4-5 years, but I certainly can understand that some people want to be able to enable it for any reason (even for educationnal purposes), hence the sysctl.

I have rediffed the patch for 2.6.27-rc9 and successfully tested it (both with feature enabled and disabled). It disables the feature by default, but I have no problem with leaving it on and expecting that distros will ship it off.

By the way, during the tests I noticed something strange. While the socket is in SYN_RECV on the first side to receive the other one's SYN, it has a huge receive queue :

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 3964220580 1 192.32.189.160:12346 192.32.189.228:4000 SYN_RECV

The value corresponds to the ACK value emitted, which is equal to the other end's SYN+1. I don't know if this is just an artefact of the way the queue size is reported (probably because the first ACK has not yet been considered since we're not in ESTABLISHED state) or if this can have any further impact (eg: unexpected memory freeing on termination, etc...).

Quoted 4 lines
Quoted 2 lines

Best regards,
Willy

Does this break NAT traversal via STUNT used by applications like Skype?

Not IMHO. I've seen UDP-based protocols used for NAT traversal, since it's stateless and the firewall is not able to perform much control, but TCP would not work with most firewalls (starting with netfilter) because the firewall will not accept a SYN in return to a SYN.

Regards,
Willy

#5 lore raw
In reply to Stephen Hemminger

Le mercredi 8 octobre 2008 14:54:02 Stephen Hemminger, vous avez écrit :

Quoted 1 line

Does this break NAT traversal via STUNT used by applications like Skype?

This will break the main ICE-TCP mechanism (IETF draft-ietf-mmusic-ice-tcp). I am not aware of any application using this _as_of_now_. Probably too many NAT and firewall implementations will reject it already. And then, some TCP stacks reportedly do not support it (e.g. Windows before Vista).

On the other hand, if someone were to tunnel/encapsulate TCP over UDP, this could actually be useful - think about peer-to-peer NATted-to-NATted file transfers for instance.

Signature · 2 lines
Rémi Denis-Courmont
http://www.remlab.net/
#6 lore raw
Quoted 7 lines · Rémi Denis-Courmont

Le mercredi 8 octobre 2008 14:54:02 Stephen Hemminger, vous avez écrit :

Quoted 1 line

Does this break NAT traversal via STUNT used by applications like Skype?

This will break the main ICE-TCP mechanism (IETF draft-ietf-mmusic-ice-tcp). I am not aware of any application using this _as_of_now_. Probably too many NAT and firewall implementations will reject it already. And then, some TCP stacks reportedly do not support it (e.g. Windows before Vista).

And opening this through firewalls would be too much dangerous as it would allow servers to reconnect outside, pretty much defeating the initial purpose of the firewall.

Quoted 3 lines

On the other hand, if someone were to tunnel/encapsulate TCP over UDP, this could actually be useful - think about peer-to-peer NATted-to-NATted file transfers for instance.

This is already possible using netcat. You can force both ports. It has no flow control but would be enough to chat or transfer small config files.

Willy

#7 lore raw
Quoted 11 lines · you
Quoted 9 lines · Rémi Denis-Courmont

Le mercredi 8 octobre 2008 14:54:02 Stephen Hemminger, vous avez écrit :

Quoted 2 lines

Does this break NAT traversal via STUNT used by applications like Skype?

This will break the main ICE-TCP mechanism (IETF draft-ietf-mmusic-ice-tcp). I am not aware of any application using this _as_of_now_. Probably too many NAT and firewall implementations will reject it already. And then, some TCP stacks reportedly do not support it (e.g. Windows before Vista).

Quoted 3 lines

And opening this through firewalls would be too much dangerous as it would allow servers to reconnect outside, pretty much defeating the initial purpose of the firewall.

Duh? If you require a SYN from the outside to the server, before you allow the server to send either SYN or SYN/ACK, I fail to see the problem.

Quoted 6 lines
Quoted 3 lines

On the other hand, if someone were to tunnel/encapsulate TCP over UDP, this could actually be useful - think about peer-to-peer NATted-to-NATted file transfers for instance.

This is already possible using netcat. You can force both ports. It has no flow control but would be enough to chat or transfer small config files.

Files transfer over UDP? Come on. I won't restart the UDP sendfile discussion.

Signature · 1 line
Rémi Denis-Courmont
#8 lore raw
Quoted 12 lines · Rémi Denis-Courmont
Quoted 11 lines · you
Quoted 9 lines · Rémi Denis-Courmont

Le mercredi 8 octobre 2008 14:54:02 Stephen Hemminger, vous avez écrit :

Quoted 2 lines

Does this break NAT traversal via STUNT used by applications like Skype?

This will break the main ICE-TCP mechanism (IETF draft-ietf-mmusic-ice-tcp). I am not aware of any application using this _as_of_now_. Probably too many NAT and firewall implementations will reject it already. And then, some TCP stacks reportedly do not support it (e.g. Windows before Vista).

Quoted 6 lines
Quoted 3 lines

And opening this through firewalls would be too much dangerous as it would allow servers to reconnect outside, pretty much defeating the initial purpose of the firewall.

Duh? If you require a SYN from the outside to the server, before you allow the server to send either SYN or SYN/ACK, I fail to see the problem.

Requiring the firewall to expect a first SYN to come from the internet is like doing no check at all. When your server has been rooted, you can pretty much expect that your guest has no problem sending you a SYN.

Willy

#9 lore raw
Quoted 6 lines · you
Quoted 3 lines

Duh? If you require a SYN from the outside to the server, before you allow the server to send either SYN or SYN/ACK, I fail to see the problem.

Requiring the firewall to expect a first SYN to come from the internet is like doing no check at all.

On ports which are open to the outside you MUST allow inbound SYNs anyway. From a security perspective, it does not matter whether the server answers with a SYN/ACK as normally or with a SYN-not-ACK as in "simultaneous open".

On ports which the server is using outbound only (if any), you can expect the server to send a SYN out first. It again does not matter whether the other end answers with a SYN/ACK or a SYN-not-ACK.

On other ports, a plain dumb stateless blackhole will do.

Quoted 2 lines

When your server has been rooted, you can
pretty much expect that your guest has no problem sending you a SYN.

And why would (s)he have problem sending a SYN/ACK? It makes no difference.

Signature · 1 line
Rémi Denis-Courmont
#10 lore raw
Quoted 16 lines · Rémi Denis-Courmont
Quoted 6 lines · you
Quoted 3 lines

Duh? If you require a SYN from the outside to the server, before you allow the server to send either SYN or SYN/ACK, I fail to see the problem.

Requiring the firewall to expect a first SYN to come from the internet is like doing no check at all.

On ports which are open to the outside you MUST allow inbound SYNs anyway.

Quoted 1 line

From a security perspective, it does not matter whether the server answers

with a SYN/ACK as normally or with a SYN-not-ACK as in "simultaneous open".

On ports which the server is using outbound only (if any), you can expect the server to send a SYN out first. It again does not matter whether the other end answers with a SYN/ACK or a SYN-not-ACK.

Quoted 6 lines

On other ports, a plain dumb stateless blackhole will do.

Quoted 2 lines

When your server has been rooted, you can
pretty much expect that your guest has no problem sending you a SYN.

And why would (s)he have problem sending a SYN/ACK? It makes no difference.

It's just that it would be useless. If sending a fake SYN from port 25 to your server's port 443 allows it to establish connections from port 443 to port 25, it becomes an easy spam platform. That's just an example. I'm just trying to explain that supporting simultaneous connect on a firewall prevents you from precisely controlling the direction of the streams.

Willy

#11 lore raw
In reply to Willy Tarreau

include/linux/sysctl.h enum · line 438

Quoted 9 lines
include/linux/sysctl.h +1 -0
index d0437f3..0e23062 100644
@@ -435,6 +435,7 @@ enum
 	NET_TCP_ALLOWED_CONG_CONTROL=123,
 	NET_TCP_MAX_SSTHRESH=124,
 	NET_TCP_FRTO_RESPONSE=125,
+	NET_TCP_SIMULT_CONNECT=126,

Minor - sysctl syscall (as long as numbers and ->strategy callbacks) are about to be removed some time, so new sysctls are to be CTL_UNNUMBERED.

Quoted 3 lines
include/linux/sysctl.h +0 -0
 };
 
 enum {
#12 lore raw

Hi Pavel,

Quoted 4 lines · Pavel Emelyanov
Quoted 4 lines
include/linux/sysctl.h +0 -0
index d0437f3..0e23062 100644
Quoted 8 lines

include/linux/sysctl.h enum · line 438

Quoted 5 lines
include/linux/sysctl.h +1 -0
@@ -435,6 +435,7 @@ enum
 	NET_TCP_ALLOWED_CONG_CONTROL=123,
 	NET_TCP_MAX_SSTHRESH=124,
 	NET_TCP_FRTO_RESPONSE=125,
+	NET_TCP_SIMULT_CONNECT=126,

Minor - sysctl syscall (as long as numbers and ->strategy callbacks) are about to be removed some time, so new sysctls are to be CTL_UNNUMBERED.

I noticed that one in the two latest UDP sysctls, but was not aware of the rules related to its use. Given the number of unconverted sysctls, is it worth changing it now ?

Willy

#13 lore raw
Quoted 15 lines · Willy Tarreau

Hi Pavel,

Quoted 11 lines · Pavel Emelyanov

include/linux/sysctl.h enum · line 438

Quoted 9 lines
include/linux/sysctl.h +1 -0
index d0437f3..0e23062 100644
@@ -435,6 +435,7 @@ enum
 	NET_TCP_ALLOWED_CONG_CONTROL=123,
 	NET_TCP_MAX_SSTHRESH=124,
 	NET_TCP_FRTO_RESPONSE=125,
+	NET_TCP_SIMULT_CONNECT=126,

Minor - sysctl syscall (as long as numbers and ->strategy callbacks) are about to be removed some time, so new sysctls are to be CTL_UNNUMBERED.

Quoted 3 lines

I noticed that one in the two latest UDP sysctls, but was not aware of the rules related to its use. Given the number of unconverted sysctls, is it worth changing it now ?

Sorry, I don't get you here. Sysctls are not supposed to get converted, the intention is just to a) stop adding new sysctls with strategies and
b) drop all the existing strategies in the future.

Quoted 7 lines

Willy

--
To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#14 lore raw
Quoted 16 lines · Pavel Emelyanov
Quoted 15 lines · Willy Tarreau

Hi Pavel,

Quoted 11 lines · Pavel Emelyanov

include/linux/sysctl.h enum · line 438

Quoted 9 lines
include/linux/sysctl.h +1 -0
index d0437f3..0e23062 100644
@@ -435,6 +435,7 @@ enum
 	NET_TCP_ALLOWED_CONG_CONTROL=123,
 	NET_TCP_MAX_SSTHRESH=124,
 	NET_TCP_FRTO_RESPONSE=125,
+	NET_TCP_SIMULT_CONNECT=126,

Minor - sysctl syscall (as long as numbers and ->strategy callbacks) are about to be removed some time, so new sysctls are to be CTL_UNNUMBERED.

Quoted 8 lines
Quoted 3 lines

I noticed that one in the two latest UDP sysctls, but was not aware of the rules related to its use. Given the number of unconverted sysctls, is it worth changing it now ?

Sorry, I don't get you here. Sysctls are not supposed to get converted, the intention is just to a) stop adding new sysctls with strategies and

b) drop all the existing strategies in the future.

If existing declarations eventually get changed, that's what I call a conversion :-)

OK I get you here. The patch will be resent with CTL_UNNUMBERED if there is an agreement to get it merged.

Regards,
Willy

#15 lore raw
In reply to Willy Tarreau
Quoted 18 lines · On Wed, 8 Oct 2008 10:11:09 +0200 Willy Tarreau wrote:
 Documentation/networking/ip-sysctl.txt |   22 ++++++++++++++++++++++
Documentation/networking/ip-sysctl.txt +8 -0
index d849326..cefc894 100644
@@ -101,6 +101,28 @@ inet_peer_gc_maxtime - INTEGER
 
 TCP variables: 
 
+tcp_simult_connect - BOOLEAN
+	Enables TCP simultaneous connect feature conforming to RFC793.
+	Strict implementation of RFC793 (TCP) requires support for a feature
+	called "simultaneous connect", which allows two clients to connect to
+	each other without anyone entering a listening state.  While almost
+	never used, and supported by few OSes, Linux supports this feature.
+
+	However, it introduces a weakness in the protocol which makes it very

Documentation/networking/ip-sysctl.txt inet_peer_gc_maxtime - INTEGER · line 121

Quoted 10 lines
Documentation/networking/ip-sysctl.txt +10 -0
+	easy for an attacker to prevent a client from connecting to a known
+	server. The attacker only has to guess the source port to shut down
+	the client connection during its establishment. The impact is limited,
+	but it may be used to prevent an antivirus or IPS from fetching updates
+	and not detecting an attack, or to prevent an SSL gateway from fetching
+	a CRL for example.
+
+	If you want absolute compatibility with any possible application,
+	you should set it to 1. If you prefer to enhance security on your
+	systems you'd better let it to 0. After four years of usage on

set it to 0.
or did you mean: (?)
let it be 0.

Documentation/networking/ip-sysctl.txt inet_peer_gc_maxtime - INTEGER · line 128

Quoted 7 lines
Documentation/networking/ip-sysctl.txt +4 -0
+	hundreds of systems, no application was ever found to require this
+	feature, which is not even supported by most firewalls.
+	Default: 0
+
 somaxconn - INTEGER
 	Limit of socket listen() backlog, known in userspace as SOMAXCONN.
 	Defaults to 128.  See also tcp_max_syn_backlog for additional tuning

---
~Randy

#16 lore raw
Quoted 7 lines · Randy Dunlap

Documentation/networking/ip-sysctl.txt inet_peer_gc_maxtime - INTEGER · line 121

Quoted 3 lines
Documentation/networking/ip-sysctl.txt +3 -0
+	If you want absolute compatibility with any possible application,
+	you should set it to 1. If you prefer to enhance security on your
+	systems you'd better let it to 0. After four years of usage on

set it to 0.
or did you mean: (?)
let it be 0.

I meant "leave it" but I'd prefer "let it be 0".

Thanks Randy,
Willy

maintainer
#17 lore raw
In reply to Willy Tarreau

I'm not really interested in applying this.

You can make the same argument for just about any queer corner case aspect of TCP.

The world hasn't ended even though this patch hasn't applied since 2005 and that's a good argument to not apply "yet another random knob" to the kernel.

#18 lore raw
Quoted 2 lines · David Miller

I'm not really interested in applying this.

OK.

Quoted 2 lines

You can make the same argument for just about any queer corner case aspect of TCP.

Not exactly since there are very few corner cases not conditionned by guessing a 32-bit sequence number, and this one certainly is.

Quoted 2 lines

The world hasn't ended even though this patch hasn't applied since 2005

Oh don't take me wrong. I'm pretty much convinced this is not critical at all. It's just that it's a tempting attack vector for an easy DoS proof of concept relying on a feature not even usable today.

Quoted 2 lines

and that's a good argument to not apply "yet another random knob" to the kernel.

OK for the random knob. If you feel comfortable with a patch to simply remove the feature, I can send you such a patch too. BTW, the strange netstat output I got also shows that the code paths involved to support this feature are not much exercised, which would be another argument to disable it.

Anyway, I'm not trying to put any pressure. I can continue to live with the ifdef patch in my trees. I just wanted to get your opinion on this one since the discussion I initiated about it in 2005 brought to nowhere.

Regards,
Willy

maintainer
#19 lore raw

From: Willy Tarreau <[email protected]>
Date: Wed, 8 Oct 2008 19:07:39 +0200

Quoted 6 lines · David Miller
Quoted 2 lines

and that's a good argument to not apply "yet another random knob" to the kernel.

OK for the random knob. If you feel comfortable with a patch to simply remove the feature, I can send you such a patch too.

If I don't want the knob, what makes you think I'll accept a patch to remove or ifdef the code?

I absolutely will not.

#20 lore raw
Quoted 7 lines · David Miller

From: Willy Tarreau <[email protected]>
Date: Wed, 8 Oct 2008 19:07:39 +0200

Quoted 4 lines · David Miller
Quoted 2 lines

and that's a good argument to not apply "yet another random knob" to the kernel.

Quoted 7 lines
Quoted 2 lines

OK for the random knob. If you feel comfortable with a patch to simply remove the feature, I can send you such a patch too.

If I don't want the knob, what makes you think I'll accept a patch to remove or ifdef the code?

I absolutely will not.

OK at least now it's clear.

Thanks anyway,
Willy

#21 lore raw
In reply to Willy Tarreau
Quoted 4 lines · Willy Tarreau

As a reminder (especially for those who are not aware of this feature), it is possible with TCP to connect two clients together if both send crossed SYNs, then SYN-ACKs, then ACKs. This implies that each side accepts the sequence number of the other one without any ability to

Quoted 8 lines

check that it matches its SYN. So it's trivial for an attacker to prevent one client from establishing a connection from a known port to a known address/port by sending it a SYN to that port. The client will then send a SYN-ACK and will not accept the expected server's SYN-ACK because the SYN SEQ will be different. The server might also send an RST on the client's SYN-ACK if it's not firewalled. The connection will eventually timeout in a SYN-RECV state or simply be aborted.

One reasonable tweak for this would be to use a very aggressive timeout for simultaneously opened connections that didn't get an ACK yet.

But to be honest it doesn't seem like a very pressing problem to me either.

-Andi

Signature · 1 line
[email protected]