Vasteras - Sweden, Belgrade, Nis - Serbia

October 31, 2014

Troxo - Software Development Company

TCP window scaling conundrum

June 5th, 2008

Our brand new PCs came with Windows Vista OS preinstalled. A few of our unfortunate colleagues experienced some strange problems. They couldn’t open Google, or establish connection with any messenger for no obvious reason. Even FTP/SFTP and SSH clients acted numb. All of our XP and FreeBSD machines worked just fine in the same network. Again, Microsoft and Vista were to blame, right?

Let’s see what was going on. Vista has introduced a new feature called “Receive Window Auto-Tuning” which continuously adjusts the size of TCP receiving window, based on changing network conditions. It appears that auto-tuning causes network time-out problems with some applications and routers.

The first thing that came to our minds was to disable auto-tuning. Enter the following line into your command prompt (with high privileges):

netsh int tcp set global autotuninglevel=disabled

And miraculously, everything worked as it was supposed to, in the same way our other machines did.

But, there is more! We had just got Vista working when we came across the same problem with Ubuntu. This one was not at Microsoft’s expense, for sure.

Our first attempt to install Ubuntu 7.10 Server 64bit wasn’t successful, because of a problem with updating packages, but we thought it was the cable, or DHCP, or something else. So we plugged out the network cable and did offline installation.

When we tried to update Ubuntu, we couldn’t do it. The update showed errors on almost every package that was requested. We checked all the networking settings (acquired IP address, DNS servers and the gateway). Everything was ok, but still there was no luck with the update.

After some time spent googling, first we found symptoms similar to those we had experienced in the post about The Great Tele2.fr Network Outage of 2008 (search the page for TCPMSS). We found the solution at Ubuntu’s wiki.

In Ubuntu you can also disable TCP window auto-tunning (window scaling) by editing your /etc/sysctl.conf:

net.ipv4.tcp_window_scaling=0

Ok, both on Vista and Ubuntu? Then, we started suspecting our OpenBSD router and got digging deeper into the matter and, finally, we found the solution at the end of the great “Veghead’s Guide to OpenBSD Firewalls”:

To properly support TCP window scaling, pf must create a state on the
initial SYN packet of connection.

If the state is created on a subsequent packet (like when the SYN is
accidentally passed without creating a state, and the state is created on
the returning SYN+ACK), pf has missed the window scaling negotiation
containing the scaling factors, and will eventually stall
connections. Each peer’s scaling factor is only seen in its SYN packet,
and can’t be deduced later on.

Check your ruleset and verify that

a) there is a default block policy
b) all ‘pass’ rules applying to TCP have both ‘keep state’ and ‘flags S/SA’.

That was it! Vista and Ubuntu were happy again, with default settings so we were able to re-enable Vista auto-tuning by typing:

netsh int tcp set global autotuninglevel=normal

and for Ubuntu, we were able to erase the line in /etc/sysctl.conf:

net.ipv4.tcp_window_scaling=0