8000 fix: stop selecting direct connections with too-small MTU by spikecurtis · Pull Request #85 · coder/tailscale · GitHub
[go: up one dir, main page]

Skip to content

fix: stop selecting direct connections with too-small MTU #85

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 10, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
logs and comments
  • Loading branch information
spikecurtis committed Jun 9, 2025
commit c89c6b7551639ca48bff53754c9c5367bf68cfcf
5 changes: 4 additions & 1 deletion disco/disco.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ const v1 = byte(1)

// paddedPayloadLen is the desired length we want to pad Ping and Pong payloads
// to so that they are the maximum size of a Wireguard packet we would
// subsequently send.
// subsequently send. This ensures that any UDP paths we discover will actually
// support the packet sizes the net stack will send over those paths. Any peers
// behind a small-MTU link will have to depend on DERP.
// c.f. https://github.com/coder/coder/issues/15523
// Our inner IP packets can be up to 1280 bytes, with the Wireguard header of
// 30 bytes, that is 1310. The final 2 is the inner payload header's type and version.
const paddedPayloadLen = 1310 - len(Magic) - keyLen - NonceLen - box.Overhead - 2
Expand Down
7 changes: 6 additions & 1 deletion wgengine/magicsock/magicsock.go
Original file line number Diff line number Diff line change
Expand Up @@ -2377,7 +2377,12 @@ func (c *Conn) bindSocket(ruc *RebindingUDPConn, network string, curPortFate cur
continue
}
trySetSocketBuffer(pconn, c.logf)
trySetPathMTUDiscover(pconn, c.logf, network)
// CODER: https://github.com/coder/coder/issues/15523
// Attempt to tell the OS not to fragment packets over this interface. We pad disco Ping and Pong packets to the
// size of the direct UDP packets that get sent for direct connections. Thus, any interfaces or paths that
// cannot fully support direct connections due to MTU limitations will not be selected. If no direct paths meet
// the MTU requirements for a peer, we will fall back to DERP for that peer.
tryPreventFragmentation(pconn, c.logf, network)
// Success.
if debugBindSocket() {
c.logf("magicsock: bindSocket: successfully listened %v port %d", network, port)
Expand Down
12 changes: 6 additions & 6 deletions wgengine/magicsock/magicsock_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import (
"tailscale.com/types/nettype"
)

func trySetPathMTUDiscover(pconn nettype.PacketConn, logf logger.Logf, network string) {
func tryPreventFragmentation(pconn nettype.PacketConn, logf logger.Logf, network string) {
if c, ok := pconn.(*net.UDPConn); ok {
s, err := c.SyscallConn()
if err != nil {
logf("magicsock: failed to set Path MTU Discover: get syscall conn: %v", err)
logf("magicsock: dontfrag: failed to get syscall conn: %v", err)
}
level := unix.IPPROTO_IP
option := unix.IP_DONTFRAG
Expand All @@ -23,14 +23,14 @@ func trySetPathMTUDiscover(pconn nettype.PacketConn, logf logger.Logf, network s
err = s.Control(func(fd uintptr) {
err := unix.SetsockoptInt(int(fd), level, option, 1)
if err != nil {
logf("magicsock: failed to set Path MTU Discover: SetsockoptInt failed: %v", err)
logf("magicsock: dontfrag: SetsockoptInt failed: %v", err)
}
})
if err != nil {
logf("magicsock: failed to set Path MTU Discover: control connection: %v", err)
10000 logf("magicsock: dontfrag: control connection failed: %v", err)
}
logf("magicsock: successfully set Path MTU Discover on %s", pconn.LocalAddr().String())
logf("magicsock: dontfrag: success on %s", pconn.LocalAddr().String())
return
}
logf("magicsock: failed to set Path MTU Discover: not a UDPConn")
logf("magicsock: dontfrag: failed because it was not a UDPConn")
}
12 changes: 6 additions & 6 deletions wgengine/magicsock/magicsock_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,11 +405,11 @@ func init() {
controlMessageSize = unix.CmsgSpace(2)
}

func trySetPathMTUDiscover(pconn nettype.PacketConn, logf logger.Logf, network string) {
func tryPreventFragmentation(pconn nettype.PacketConn, logf logger.Logf, network string) {
if c, ok := pconn.(*net.UDPConn); ok {
s, err := c.SyscallConn()
if err != nil {
logf("magicsock: failed to set Path MTU Discover: get syscall conn: %v", err)
logf("magicsock: dontfrag: failed to get syscall conn: %v", err)
}
level := unix.IPPROTO_IP
option := unix.IP_MTU_DISCOVER
Expand All @@ -420,14 +420,14 @@ func trySetPathMTUDiscover(pconn nettype.PacketConn, logf logger.Logf, network s
err = s.Control(func(fd uintptr) {
err := unix.SetsockoptInt(int(fd), level, option, unix.IP_PMTUDISC_DO)
if err != nil {
logf("magicsock: failed to set Path MTU Discover: SetsockoptInt failed: %v", err)
logf("magicsock: dontfrag: SetsockoptInt failed: %v", err)
}
})
if err != nil {
logf("magicsock: failed to set Path MTU Discover: control connection: %v", err)
logf("magicsock: dontfrag: control connection failed: %v", err)
}
logf("magicsock: successfully set Path MTU Discover on %s", pconn.LocalAddr().String())
logf("magicsock: dontfrag: success on %s", pconn.LocalAddr().String())
return
}
logf("magicsock: failed to set Path MTU Discover: not a UDPConn")
logf("magicsock: dontfrag: failed because it was not a UDPConn")
}
12 changes: 6 additions & 6 deletions wgengine/magicsock/magicsock_windows.go
8655
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ const (
IP_PMTUDISC_MAX
)

func trySetPathMTUDiscover(pconn nettype.PacketConn, logf logger.Logf, network string) {
func tryPreventFragmentation(pconn nettype.PacketConn, logf logger.Logf, network string) {
if c, ok := pconn.(*net.UDPConn); ok {
s, err := c.SyscallConn()
if err != nil {
logf("magicsock: failed to set Path MTU Discover: get syscall conn: %v", err)
logf("magicsock: dontfrag: failed to get syscall conn: %v", err)
}
level := windows.IPPROTO_IP
if network == "udp6" {
Expand All @@ -34,14 +34,14 @@ func trySetPathMTUDiscover(pconn nettype.PacketConn, logf logger.Logf, network s
err = s.Control(func(fd uintptr) {
err := windows.SetsockoptInt(windows.Handle(fd), level, IP_MTU_DISCOVER, IP_PMTUDISC_DO)
if err != nil {
logf("magicsock: failed to set Path MTU Discover: SetsockoptInt failed: %v", err)
logf("magicsock: dontfrag: SetsockoptInt failed: %v", err)
}
})
if err != nil {
logf("magicsock: failed to set Path MTU Discover: control connection: %v", err)
logf("magicsock: dontfrag: control connection failed: %v", err)
}
logf("magicsock: successfully set Path MTU Discover on %s", pconn.LocalAddr().String())
logf("magicsock: dontfrag: success on %s", pconn.LocalAddr().String())
return
}
logf("magicsock: failed to set Path MTU Discover: not a UDPConn")
logf("magicsock: dontfrag: failed because it was not a UDPConn")
}
Loading
0