FireBrick - Firewalls, Bonding ADSL, Routers, Traffic Shaping...

FireBrick FB6000
FireBrick FB6000

What is a TCP MSS fix and why?

The L2TP config has an option to set tcp-mss-fix. This sets the default for each new session which connects. The session can have this setting controlled by RADIUS response, or RADIUS CoA on a live session.

What does the setting do?

IP uses packets to transfer data. When a packet is too big for a link then something has to be done. Most links allow 1500 bytes of internet protocol (the MTU or MRU), but some allow less. The most common is 1492 bytes when using PPPoE. Some back-haul links use 1492 for all sessions. Some that use 1500 may have to use 1492 when the end user has PPPoE bridging. In some cases the L2TP traffic itself may have to pass through 1500 byte links and so only allow 1468 of payload IP packets without fragmenting. You can configure a restricted MTU on a tunnel config and per session using RADIUS.

There are two possible actions when sending a large packet down a small pipe. (a) The packet is fragmented - made in to two or more smaller packets that have to be put back together at the other end. (b) the packet is dropped and an error generated to tell the sender to use smaller packets. For IPv6 it is always the latter. For IPv4 it is decided on a packet by packet basis based on a flag in the packet.

Both of these are not advisable, it is better if the sender uses smaller packets in the first place. The main reason long packets are ever sent is TCP. TCP will send blocks of data based on a maximum segment size (MSS). Normally (for IPv4) this is 1460 as that allows 20 bytes TCP header and 20 bytes IP header. Each end tells the other the MSS it wants when the TCP session starts and this is done using the TCP MSS option.

The tcp-mss-fix option spots the TCP connection packets (SYN), finds the TCP MSS option, checked the value, and if too big it adjusts it. This way the negotiated MSS for the TCP link is lower and the end points send smaller packets to each other, so avoiding any errors or fragments.

Why do we need this setting?

The system of making fragments or sending errors is perfectly sensible. It allows the internet to work where links are smaller. It is less efficient than just using the right size packets in the first place, and so the tcp-mss-fix is an important efficiency improvement.

However, that is not the only reason. There are a lot of very broken routers and firewalls in the internet which break horribly when packets are fragmented or errors generated. For this reason some web sites and other services either don't work at all, or have long delays, when packets are too big. The tcp-mss-fix is a bodge to work around these broken configurations as best as possible. Without it the FB6000 is still working 100% correctly, but this extra feature allows for less hassle.

  • Some web sites send 1500 byte packets and perform path MTU discovery (asking for an error if too big), but then firewall the error coming back. This means they fail to send 1500 bytes and will take several seconds to fall back to a much lower MSS. This creates long delays (seconds) and then transfers data with smaller and less efficient packets.
  • Some consumer routers and end user firewalls do not allow fragments through. As such a web site may send 1500 bytes, and the link in the middle (e.g. FB6000) make fragments of it, and the end user router or firewall just drops these. If the sender may not try smaller packets as they are not doing path MTU discovery, so making the communications impossible.

What is the recommended use of this setting?

It is recommended that you have this set in any case where you have a reduced MTU, i.e. less than 1500 bytes. This can happen when using PPPoE or when using lower MTU to avoid fragmented L2TP packets. It is safe in all practical terms to leave on all of the time. However, it is tampering with packets as they pass through and so is not the default operation.