Skip to content

Conversation

@qdm12
Copy link
Owner

@qdm12 qdm12 commented Nov 14, 2024

Run with image tag pr-2586 that's it 😉

Fix #2570

  • pmtud for IPv4, which takes up to 1s
  • pmtud for IPv6 (untested), which takes up to 1s
  • Fallback on a binary search with echo requests of different sizes, which takes up to 3 seconds (3 x 11 ICMP echoes)
  • if icmp isn't available, fall back to use WIREGUARD_MTU or a default 1300 conservative mtu
  • Run PMTUD after VPN is up and modify live the VPN link MTU with netlink. This is blocking otherwise other network operations would fail in parallel, due to the temporary high MTU set on the link.

Note for Openvpn, mssfix might still have an impact on changing the mtu

@frozenfoxx
Copy link

Tested this with ProtonVPN using Wireguard, doesn't work for me:

2025-09-10T18:11:16Z INFO [MTU discovery] finding maximum MTU, this can take up to 4 seconds
2025-09-10T18:11:16Z ERROR [vpn] path MTU discovering: finding IPv4 next hop MTU: ICMP destination unreachable: code 13
2025-09-10T18:11:20Z WARN [dns] cannot update filter block lists: Get "https://raw.githubusercontent.com/qdm12/files/master/malicious-hostnames.updated": context deadline exceeded (Client.Timeout exceeded while awaiting headers), Get "https://raw.githubusercontent.com/qdm12/files/master/malicious-ips.updated": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
2025-09-10T18:11:20Z INFO [dns] attempting restart in 20s

@qdm12
Copy link
Owner Author

qdm12 commented Sep 12, 2025

Can you try re-pulling the image and see if it works? It should now fallback on the more-bruteforcey method of finding the MTU, if PMTUD isn't allowed by their firewall.

@tribut
Copy link

tribut commented Sep 13, 2025

Tried it out and the feature seems to fall back to the minimum MTU of 68:

INFO [MTU discovery] finding maximum MTU, this can take up to 4 seconds
INFO [MTU discovery] VPN interface tun0 MTU set to maximum valid MTU 68                                

However, when I connect a debian:stable container to the gluetun network, I get responses from the Proton VPN endpoint up to ping -M do -s 1472 -c 1 89.36.76.130 (the link MTU is 1500).

@DrummyFloyd
Copy link

hi, thank for your hard work !
i've just tested the PR, (wireguard+AirVpn) and i 'e reached 1320 MTU (the best value i've already found earlier )

@qdm12
Copy link
Owner Author

qdm12 commented Sep 26, 2025

@tribut can you run with LOG_LEVEL=debug? 68 is the minimum MTU possible, that's odd.

@tribut
Copy link

tribut commented Sep 27, 2025

I've tried again with LOG_LEVEL=debug and it looks like some sort of race condition? When the VPN is not healthy on first try, it works after a reconnect:

INFO [wireguard] Connecting to 217.138.216.130:51820
DEBUG [netlink] ip -f inet rule add lookup 51820 pref 101
INFO [wireguard] Wireguard setup is complete. Note Wireguard is a silent protocol and it may or may not work, without giving any error message. Typically i/o timeout errors indicate the Wireguard connection is not working.
INFO [MTU discovery] finding maximum MTU, this can take up to 4 seconds
DEBUG [MTU discovery] VPN interface tun0 MTU temporarily set to 1440
DEBUG [MTU discovery] finding IPv4 next hop MTU
DEBUG [MTU discovery] falling back to sending different sized echo packets
DEBUG [MTU discovery] testing the following MTUs: [192 316 440 564 688 812 936 1060 1184 1308 1440]
DEBUG [MTU discovery] testing the following MTUs: [79 90 101 112 123 134 145 156 167 178 191]
DEBUG [MTU discovery] testing the following MTUs: [69 70 71 72 73 74 75 76 77 78]
INFO [MTU discovery] VPN interface tun0 MTU set to maximum valid MTU 68
INFO [dns] downloading hostnames and IP block lists
INFO [dns] DNS server listening on [::]:53
INFO [dns] ready
INFO [healthcheck] program has been unhealthy for 6s: restarting VPN (healthcheck error: dialing: dial tcp4: lookup cloudflare.com: i/o timeout)
INFO [healthcheck] 👉 See https://github.com/qdm12/gluetun-wiki/blob/main/faq/healthcheck.md
INFO [healthcheck] DO NOT OPEN AN ISSUE UNLESS YOU READ AND TRIED EACH POSSIBLE SOLUTION
INFO [vpn] stopping
ERROR [vpn] getting public IP address information: fetching information: Get "https://ipinfo.io/": context canceled
ERROR [vpn] cannot get version information: Get "https://api.github.com/repos/qdm12/gluetun/releases": context canceled
DEBUG [wireguard] closing controller client...
DEBUG [wireguard] removing IPv4 rule...
DEBUG [netlink] ip -f inet rule del lookup 51820 pref 101
DEBUG [wireguard] shutting down link...
DEBUG [wireguard] deleting link...
INFO [vpn] starting
DEBUG [wireguard] Wireguard server public key: XXXXXXXXXXXXXXX
DEBUG [wireguard] Wireguard client private key: XXXXXXXXXXXXXXX
DEBUG [wireguard] Wireguard pre-shared key: [not set]
INFO [firewall] allowing VPN connection...
INFO [wireguard] Using available kernelspace implementation
INFO [wireguard] Connecting to 217.138.216.130:51820
DEBUG [netlink] ip -f inet rule add lookup 51820 pref 101
INFO [wireguard] Wireguard setup is complete. Note Wireguard is a silent protocol and it may or may not work, without giving any error message. Typically i/o timeout errors indicate the Wireguard connection is not working.
INFO [MTU discovery] finding maximum MTU, this can take up to 4 seconds
DEBUG [MTU discovery] VPN interface tun0 MTU temporarily set to 1440
DEBUG [MTU discovery] finding IPv4 next hop MTU
INFO [MTU discovery] VPN interface tun0 MTU set to maximum valid MTU 1440
INFO [healthcheck] healthy!

But when the VPN is healthy on first connect, it's stuck on 68:

INFO [wireguard] Connecting to 185.159.158.178:51820
DEBUG [netlink] ip -f inet rule add lookup 51820 pref 101
INFO [wireguard] Wireguard setup is complete. Note Wireguard is a silent protocol and it may or may not work, without giving any error message. Typically i/o timeout errors indicate the Wireguard connection is not working.
INFO [MTU discovery] finding maximum MTU, this can take up to 4 seconds
DEBUG [MTU discovery] VPN interface tun0 MTU temporarily set to 1440
DEBUG [MTU discovery] finding IPv4 next hop MTU
DEBUG [MTU discovery] falling back to sending different sized echo packets
DEBUG [MTU discovery] testing the following MTUs: [192 316 440 564 688 812 936 1060 1184 1308 1440]
DEBUG [MTU discovery] testing the following MTUs: [79 90 101 112 123 134 145 156 167 178 191]
DEBUG [MTU discovery] testing the following MTUs: [69 70 71 72 73 74 75 76 77 78]
INFO [MTU discovery] VPN interface tun0 MTU set to maximum valid MTU 68
INFO [dns] downloading hostnames and IP block lists
INFO [dns] DNS server listening on [::]:53
INFO [healthcheck] healthy!
INFO [dns] ready

I've restarted it a few times and this appears to be reproducible.

@strunzoz
Copy link

is there a wiki explaining how to do this

@qdm12
Copy link
Owner Author

qdm12 commented Oct 2, 2025

Ok so INFO [MTU discovery] VPN interface tun0 MTU set to maximum valid MTU 68 is definitely wrong when the connection doesn't work. I just changed it to return an error and stop guessing MTUs if all MTU tested (68...1440) fail, since it cannot be lower than 68 for ipv4 for example.

But when the VPN is healthy on first connect, it's stuck on 68

Now I'm a bit confused by this, this is not happening for me or @DrummyFloyd so that's kind of odd! I'm wondering if all MTU testing fail (like above), maybe because ICMP is blocked 🤔 So it's healthy (i.e. for https etc.) but not ICMP 🤔 🤔 That would indicate we definitely need a backup mechanism if ICMP is blocked, for example default to 1300.


@strunzoz run the container image with tag :pr-2586 that's it. The more we can test this with different providers, the better it is 💪 !

@qdm12
Copy link
Owner Author

qdm12 commented Oct 3, 2025

the previous container image was bugged, it's now fixed. New additions:

  • the lowest MTU possible 68 (for ipv4) is now tested as well
  • if all MTU testing fail, it doesn't set it to 68, it returns an error which is then handled and it reverts to the VPN interface MTU set before (set by openvpn+OPENVPN_MSSFIX or WIREGUARD_MTU). This can happen if ICMP is blocked OR if the connection simply doesn't work.
  • VPN_PMTUD variable removed, since it should be on always, especially because it manages to fallback on WIREGUARD_MTU etc. if it fails.

All in all, I think this should work in all situations now:

  • Your connection works and accepts ICMP: PMTUD finds the optimal MTU
  • Your connection works and rejects ICMP: PMTUD fails and reverts to the previous MTU set on the VPN interface
  • Your connection does not work: PMTUD fails and reverts to the previous MTU set on the VPN interface

@qdm12 qdm12 requested a review from Copilot October 3, 2025 14:22
@qdm12 qdm12 marked this pull request as ready for review October 3, 2025 14:22
@qdm12
Copy link
Owner Author

qdm12 commented Oct 3, 2025

@tribut let me know if you still are facing issues 🙏 Thanks!

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements path MTU discovery (PMTUD) for VPN connections to automatically find the optimal MTU size. The implementation adds a new pmtud package that performs ICMP-based MTU discovery for both IPv4 and IPv6 connections, with fallback mechanisms when ICMP is blocked.

Key changes:

  • New pmtud package with IPv4/IPv6 MTU discovery using ICMP packets
  • Integration of PMTUD into VPN tunnel setup process
  • Refactoring of VPN setup functions to return full connection objects instead of individual fields

Reviewed Changes

Copilot reviewed 23 out of 24 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
internal/pmtud/*.go New package implementing path MTU discovery with ICMP probing and binary search fallback
internal/vpn/tunnelup.go Integration of MTU discovery into tunnel setup process
internal/vpn/wireguard.go Refactored to return connection object instead of individual fields
internal/vpn/openvpn.go Refactored to return connection object instead of individual fields
internal/vpn/run.go Updated to use connection object from setup functions
internal/vpn/interfaces.go Added LinkSetMTU method to Linker interface
internal/netlink/link.go Implementation of LinkSetMTU method
cmd/gluetun/main.go Added LinkSetMTU to Linker interface
Comments suppressed due to low confidence (1)

internal/pmtud/ipv4.go:1

  • Using panic for invalid IP version is inappropriate in this context. This should return an error instead of panicking, as invalid input should be handled gracefully.
package pmtud

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@tribut
Copy link

tribut commented Oct 15, 2025

@tribut let me know if you still are facing issues 🙏 Thanks!

Can't reproduce the problem with the latest changes. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: MTU testing to find the best MTU

6 participants