I just discovered something really subtle about WireGuard... TL;DR if you are adjusting interface MTUs precisely, and you have mismatched MTUs between peers in some cases, make sure your smallest MTU is always a multiple of 16!

WireGuard header overhead is said to be 32 bytes + UDP + IP, so 80 bytes for IPv6 and 60 bytes for IPv4. That's where you get the default MTU of 1420 (1500 - 80, so it works with IPv6).

But that's not precisely true! Actually, WireGuard will add up to 15 bytes of padding to the data, to make it a multiple of 16, as long as it doesn't exceed the MTU on that side of the connection.

So let's say you have a server with the MTU set at 1440, but you also have a client that is using IPv4 over PPPoE. So you set its MTU to 1432, subtracting the PPPoE overhead of 8 bytes. That should be fine, since the client will figure out the right path MTU for any connections, right?

Wrong!

The TCP client and server will negotiate an MSS that gives 1432 byte IP packets within the tunnel. But 1432 is not a multiple of 16! However, the client WireGuard instance knows that there is no headroom, so it will send 1432 + 60 = 1492 byte packets, which is the maximum PPPoE MTU. But on the way back, the server thinks it can go up to 1440! 1432 % 16 == 8, so it will try to round up to 1440. Then, it sends 1500 byte packets, which don't fit in PPPoE!

The fix is to either set both the client and server MTU to 1432, or to round down the client MTU to 1424.

@lina Sounds like a failure of the implementation of the autonegotiations, or not truly complying with the standards themselves somewhere.
@raulinbonn As far as I know WireGuard does not do PMTU discovery for the upper layer at all. You have to set the right MTU or you get fragmentation/etc issues.
@lina @raulinbonn WireGuard is, at many points, too simple. 😦
@Conan_Kudo @lina Yes, too simple an implementation --> poor or nonexistent autonegotiation. Burden is on the administrator/user setting up things, instead of on the software itself at runtime.

@raulinbonn @Conan_Kudo It's not actually possible to implement this properly. WireGuard supports roaming and TCP essentially does not. If MTU were autoconfigured it could change when roaming, and that would break TCP on the inner connection.

So there is really nothing "correct" that WireGuard could do. The only real solution is for the user to manually configured the lowest expected MTU.

@lina @raulinbonn @Conan_Kudo it is possible to implement this correctly. Do PMTU discovery on the outside of the tunnel and then emit the correct ICMP messages inside
@lina @Conan_Kudo But could the user make better guesses about lower expected MTU than the software itself? And if the user can do a good guess, the software ought to do it at least as well, either by asking the user, or making an even better best-guess. But my point: I think this type of config burden should hardly ever be left on the user. The user should not worry, and should not even care or know about any lower expected MTU or any of the tech stack and standards/protocols being used.

@raulinbonn @Conan_Kudo The software can't magically guess what kind of networks the user might roam on. The user is already "asked" since MTU is a configurable setting. You already have to configure tunnels manually in general. Some settings just have defaults, like this one.

If anything, perhaps GUI WireGuard tools should default to something lower like 1392, so that the most common roaming/mobile use cases (GUI machines like laptops) have a more conservative default (this value works for DS-Lite over PPPoE connections). There isn't much else you can do...

@lina @Conan_Kudo The user also can't magically know what kind of networks he/she might roam on. If there are issues, the user has to lower settings manually. That's something the software could lift from the user's shoulders, to some extent at least. For starters, just assuming a worst case scenario like using let's say 1000. Then, if a techy user knows what's going on, ok let that user config/optimize things manually. But for the userbase at large (just my personal philosophical stand) I think the software and its developers should lift all or as many as possible burdens from the user.

@raulinbonn @Conan_Kudo That's what I'm saying, that the default for systems likely to roam should be conservative. This is not necessary for setups that are non-roaming, like servers talking to each other or other fixed systems. It doesn't make sense to have a really conservative MTU for those by default.

1000 is invalid BTW. The minimum for IPv6 to work is 1280.