MTU settings for WireGuard in a VM "router"

Hello,

I’m trying to set up the following scenario where a Debian VM with 2 NICs, one for WAN, another for LAN serves as a router. I want to use a WireGuard tunnel to my VPN provider, and all incoming traffic from the LAN should be forwarded to the WG tunnel.

I managed to make it work as a gateway and clients can use it as such, for most websites. However, for certain HTTPS-enabled websites, the clients cannot connect at all.

Troubleshooting a bit, I found out that I need to set up the MTU at the WireGuard interface to something lower (like 1280 in the pic below)

eth0 is the WAN interface, pia is the wg interface, eth1 is the LAN interface

When from a Windows client on the same network (192.168.4.0/24) I set the network adapter to the same MTU (1280), I can connect fine to all HTTPS websites through the WG tunnel in my “VM router”. But if I leave the default 1500 in Windows, some kind of fragmentation happens in the HTTPS handshake (websites like bank of america, reddit have this problem) and the connection never gets established.

My question is: am I understanding this correctly that if the WG tunnel requires 1280 (or even something like 1420, etc…) in order for all websites to work, then all clients that use that router as the gateway will need to be configured one by one to have MTU = the same number as in the WG tunnel?

Second question: where else do I need to set up the MTU to a lower number? On the switch (if managed)? What if I have clients on another subnet? Do all those also need to have the same MTU as the WG gateway?

This seems like a lot of configuration, in an ideal world all clients of a gateway shouldn’t need to use non-default MTUs as this is a major configuration overhead. I understand that some of this can be managed with advanced DHCP options, but still

Is that how this is supposed to work? Shouldn’t all clients of that gateway be oblivious to the gateway’s MTU settings (in principle)?

Thank you

You only need to set the lower MTU on the Wiegaurd connections, not on the switches or other devices.

Thank you. Based on what you said I went back and troubleshooted a little further, and it turns out iptables was misconfigured.

For others who might have the same issue, here’s how it was resolved:

My setup looks as follows:
eth0: WAN interface
eth1: LAN interface
pia: PIA VPN over WireGuard

I set up the VM such that it would route packets from LAN (eth1) to pia, and iptables was initially set up as follows:

iptables -t nat -A POSTROUTING -o pia -j MASQUERADE
iptables -A FORWARD -i eth1 -o pia -j ACCEPT
iptables -A FORWARD -i pia -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT

However, I was having the issues I described in my initial post. The symptoms were weird. From a client machine on the same IP range of eth1 (purely switch traffic), certain websites worked ok (but relatively slow to handshake), while others (like Reddit, Bank of America, etc) did not work at all. It turns out iptables somehow was misbehaving when transmitting packets from eth1 to pia and back (apparently the MTU settings from pia were not being “observed” by iptables when routing packets back and forth).

What was missing was the following additional configuration:

iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -o pia -m tcpmss --mss 1360:1536 -j TCPMSS --set-mss 1360

Below is the explanation I got from X’s Grok about that command:

This iptables command is used to manipulate the TCP Maximum Segment Size (MSS) for packets going through a network interface named pia. Here’s a breakdown of what each part of the command does:

-t mangle: Specifies the table to use. The mangle table is used for packet alteration.
-A FORWARD: Appends a rule to the FORWARD chain. The FORWARD chain is used for packets that are being routed through the current host to another destination.
-p tcp: Specifies that this rule applies to TCP protocol packets.
--tcp-flags SYN,RST SYN: This matches packets where the TCP flags SYN and RST are set, but only checks for SYN packets. This is typically used to target connection initiation packets (SYN packets).
-o pia: Specifies that this rule applies to packets that are going out through the interface named pia.
-m tcpmss --mss 1360:1536: This uses the tcpmss match to target packets where the MSS value is between 1360 and 1536 bytes. MSS is the maximum size of the payload of a TCP segment, excluding the TCP header.
-j TCPMSS --set-mss 1360: If all the above conditions are met, this jumps to the TCPMSS target which adjusts the MSS of the TCP SYN packets to 1360 bytes.

Purpose:
This rule is likely used for:

Path MTU Discovery: By setting the MSS, you're effectively controlling the maximum size of the TCP payload to ensure that packets do not exceed the Path Maximum Transmission Unit (MTU), which can help avoid fragmentation or packet drops due to MTU limitations along the network path.
VPN or Tunneling: Given the interface name pia (which might stand for Private Internet Access, a VPN service), this could be part of configuring the network to work optimally with a VPN. VPNs often require adjustments like this because they encapsulate traffic, which can reduce the effective MTU of the path.
Avoiding Fragmentation: By reducing the MSS, you ensure that the encapsulated (or tunneled) packets plus the VPN overhead still fit within the MTU of the physical network interfaces, reducing the need for fragmentation which can degrade performance or cause issues if fragmentation is not handled well by all devices in the path.

This setting helps in optimizing TCP traffic over networks where the standard MSS might lead to issues due to lower MTU, especially common in scenarios involving VPNs or other forms of tunneling where additional headers reduce the available space for payload.

After putting in this additional settings, all https sites work, and initial handshake for all websites feel much faster.

Hope this helps somebody in the future trying to do the same!

Cheers!