Broken firewalls refuse ECN enabled connections
I worked through an interesting problem last night at the office.
One of our users was unable to reach the
State of California's website. We recently
installed a Squid proxy and he assumed the
proxy server was blocking his request. He got a
error reported back from Squid.
I tried to reach the site without using the Squid proxy and could do so from the firewall but not from the machine hosting the Squid proxy. Packet sniffing with tcpdump revealed the connection attempt was, indeed, reaching www.ca.gov and was being refused by it. That was confusing, because the firewall provides NAT and the target system should not have been able to distinguish any difference between a request coming directly from the firewall box and one coming from the box hosting the Squid proxy.
Comparing the captured packet headers between the successful and unsuccessful attempts I did discover a difference. The firewall box was sending a packet with the Syn flag set (as expected) which simply appears in tcpdump as 'S' in the flags field. The failed attempt from the Squid proxy box had flags 'SWE'.
Are you running kernel 2.4.x? If so, _and_ you have TCP ECN enabled, that's the problem. How to check? # sysctl net.ipv4.tcp_ecn 1 means on. How to fix? Short term: # sysctl –w net.ipv4.tcp_ecn=0
That was indeed the problem. The Linux kernel configuration help file includes the following note:
Note that, on the Internet, there are many broken firewalls which refuse connections from ECN-enabled machines, and it may be a while before these firewalls are fixed. Until then, to access a site behind such a firewall (some of which are major sites, at the time of this writing) you will have to disable this option, either by saying N now or by using the sysctl.
Given the odd symptoms, I was very pleased to have been able to find and fix the problem in just a few minutes. Thanks goes to Nathan E Norman whose post on the debian-user mailing list provided the solution and to Google fantastic search engine for making it easy to find.
I'm a Debian user myself. For the time being, I've added the following line to the appropriate interface's section in /etc/networking/interfaces:
up /sbin/sysctl –w net.ipv4.tcp_ecn=0 || true
That seems to do the trick.
This site is the personal weblog of Marc Mims. You can contact Marc
by sending e-mail to:
Marc writes here about cycling, programming, Linux, and other items of personal interest.
This site is syndicated with RSS.
CSS stolen from Tom Coates who didn't even complain.