Archive for September, 2009

FreeBSD + pf problem with window scaling

FreeBSD, Problems, Windows | Posted by epistasis
Sep 13 2009

I’ve been having problems for a while with window scaling on my network. I run a FreeBSD router utilising pf for NAT/firewall. Some computers (those with Vista, Windows 7, or recent Ubuntu releases installed) could not establish connections to Google and some other websites, and applications such as Windows Live (MSN) Messenger could not establish connections.

On Windows Vista and Windows 7, disabling window scaling (also called Receive Window Auto-Tuning) with the following command was a successful patch for the problem:

netsh interface tcp set global autotuninglevel=disabled

In Ubuntu the same patch was to modify /etc/sysctl.conf to disable window scaling. I added the following line:

net.ipv4.tcp_window_scaling: 0

This was only a temporary fix however as I did not want to have to disable the feature all the time.

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, 7 and Ubuntu were happy again, with default settings so I was able to re-enable Windows auto-tuning by typing:

netsh interface tcp set global autotuninglevel=normal

and for Ubuntu, I was able to erase the line in /etc/sysctl.conf.