Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix: use tailscale that avoids small MTU paths#18323

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
spikecurtis merged 3 commits intomainfromspike/15523-tailnet-fix
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes fromall commits
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
2 changes: 1 addition & 1 deletiongo.mod
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ replace github.com/tcnksm/go-httpstat => github.com/coder/go-httpstat v0.0.0-202

// There are a few minor changes we make to Tailscale that we're slowly upstreaming. Compare here:
// https://github.com/tailscale/tailscale/compare/main...coder:tailscale:main
replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20250422090654-5090e715905e
replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20250611020837-f14d20d23d8c

// This is replaced to include
// 1. a fix for a data race: c.f. https://github.com/tailscale/wireguard-go/pull/25
Expand Down
4 changes: 2 additions & 2 deletionsgo.sum
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -920,8 +920,8 @@ github.com/coder/serpent v0.10.0 h1:ofVk9FJXSek+SmL3yVE3GoArP83M+1tX+H7S4t8BSuM=
github.com/coder/serpent v0.10.0/go.mod h1:cZFW6/fP+kE9nd/oRkEHJpG6sXCtQ+AX7WMMEHv0Y3Q=
github.com/coder/ssh v0.0.0-20231128192721-70855dedb788 h1:YoUSJ19E8AtuUFVYBpXuOD6a/zVP3rcxezNsoDseTUw=
github.com/coder/ssh v0.0.0-20231128192721-70855dedb788/go.mod h1:aGQbuCLyhRLMzZF067xc84Lh7JDs1FKwCmF1Crl9dxQ=
github.com/coder/tailscale v1.1.1-0.20250422090654-5090e715905e h1:nope/SZfoLB9MCOB9wdCE6gW5+8l3PhFrDC5IWPL8bk=
github.com/coder/tailscale v1.1.1-0.20250422090654-5090e715905e/go.mod h1:1ggFFdHTRjPRu9Yc1yA7nVHBYB50w9Ce7VIXNqcW6Ko=
github.com/coder/tailscale v1.1.1-0.20250611020837-f14d20d23d8c h1:d/qBIi3Ez7KkopRgNtfdvTMqvqBg47d36qVfkd3C5EQ=
github.com/coder/tailscale v1.1.1-0.20250611020837-f14d20d23d8c/go.mod h1:l7ml5uu7lFh5hY28lGYM4b/oFSmuPHYX6uk4RAu23Lc=
github.com/coder/terraform-config-inspect v0.0.0-20250107175719-6d06d90c630e h1:JNLPDi2P73laR1oAclY6jWzAbucf70ASAvf5mh2cME0=
github.com/coder/terraform-config-inspect v0.0.0-20250107175719-6d06d90c630e/go.mod h1:Gz/z9Hbn+4KSp8A2FBtNszfLSdT2Tn/uAKGuVqqWmDI=
github.com/coder/terraform-provider-coder/v2 v2.5.3 h1:EwqIIQKe/j8bsR4WyDJ3bD0dVdkfVqJ43TwClyGneUU=
Expand Down
11 changes: 11 additions & 0 deletionstailnet/test/integration/integration.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,7 @@ import (
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"golang.org/x/sys/unix"
"golang.org/x/xerrors"
"tailscale.com/derp"
"tailscale.com/derp/derphttp"
Expand DownExpand Up@@ -458,6 +459,16 @@ func (UDPEchoService) StartService(t *testing.T, logger slog.Logger, _ *tailnet.
Port: EchoPort,
})
require.NoError(t, err)

// set path MTU discovery so that we don't fragment the responses.
c, err := l.SyscallConn()
require.NoError(t, err)
var sockErr error
err = c.Control(func(fd uintptr) {
sockErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_MTU_DISCOVER, unix.IP_PMTUDISC_DO)
})
require.NoError(t, err)
require.NoError(t, sockErr)
logger.Info(context.Background(), "started UDPEcho server")
t.Cleanup(func() {
lCloseErr := l.Close()
Expand Down
4 changes: 2 additions & 2 deletionstailnet/test/integration/integration_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -112,7 +112,7 @@ var topologies = []integration.TestTopology{
{
// Test that direct over normal MTU works.
Name: "DirectMTU1500",
NetworkingProvider: integration.TriangleNetwork{InterClientMTU: 1500},
NetworkingProvider: integration.TriangleNetwork{Client1MTU: 1500},
Server: integration.SimpleServerOptions{},
ClientStarter: integration.BasicClientStarter{
WaitForDirect: true,
Expand All@@ -124,7 +124,7 @@ var topologies = []integration.TestTopology{
{
// Test that small MTU works.
Name: "MTU1280",
NetworkingProvider: integration.TriangleNetwork{InterClientMTU: 1280},
NetworkingProvider: integration.TriangleNetwork{Client1MTU: 1280},
Server: integration.SimpleServerOptions{},
ClientStarter: integration.BasicClientStarter{Service: integration.UDPEchoService{}, LogPackets: true},
RunTests: integration.TestBigUDP,
Expand Down
173 changes: 93 additions & 80 deletionstailnet/test/integration/network.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -390,33 +390,38 @@ func createFakeInternet(t *testing.T) fakeInternet {
}

type TriangleNetwork struct {
InterClientMTU int
Client1MTU int
}

type fakeTriangleNetwork struct {
NamePrefix string
ServerNetNS *os.File
Client1NetNS *os.File
Client2NetNS *os.File
ServerClient1VethPair vethPair
ServerClient2VethPair vethPair
Client1Client2VethPair vethPair
NamePrefix string
ServerNetNS *os.File
Client1NetNS *os.File
Client2NetNS *os.File
RouterNetNS *os.File
ServerVethPair vethPair
Client1VethPair vethPair
Client2VethPair vethPair
}

// SetupNetworking creates multiple namespaces with veth pairs between them
// with the following topology:
// SetupNetworking creates multiple namespaces with a central router in the following topology
// .
// . ┌────────────────────────────────────────────┐
// . │ Server │
// . └─────┬───────────────────────────────────┬──┘
// . │fdac:38fa:ffff:2::3 │fdac:38fa:ffff:3::3
// . veth│ veth│
// . │fdac:38fa:ffff:2::1 │fdac:38fa:ffff:3::2
// . ┌───────┴──────┐ ┌─────┴───────┐
// . │ │ fdac:38fa:ffff:1::2│ │
// . │ Client 1 ├──────────────────────┤ Client 2 │
// . │ │fdac:38fa:ffff:1::1 │ │
// . └──────────────┘ └─────────────┘
// . ┌──────────────┐
// . │ │
// . │ Server ├─────────────────────────────────────┐
// . │ │fdac:38fa:ffff:3::2 │
// . └──────────────┘ │ fdac:38fa:ffff:3::1
// . ┌──────────────┐ ┌─────┴───────┐
// . │ │ fdac:38fa:ffff:1::1│ │
// . │ Client 1 ├───────────────────────────────┤ Router │
// . │ │fdac:38fa:ffff:1::2 │ │
// . └──────────────┘ └─────┬───────┘
// . ┌──────────────┐ │ fdac:38fa:ffff:2::1
// . │ │ │
// . │ Client 2 ├─────────────────────────────────────┘
// . │ │fdac:38fa:ffff:2::2
// . └──────────────┘
// The veth link between Client 1 and the router has a configurable MTU via Client1MTU.
func (n TriangleNetwork) SetupNetworking(t *testing.T, l slog.Logger) TestNetworking {
Copy link
Member

Choose a reason for hiding this comment

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

It's not really a triangle anymore unfortunately, more of a pitchfork 🤣

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Untitled.jpg

Copy link
Member

Choose a reason for hiding this comment

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

You should redo the diagram to be triforce 🤣

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Not sure unicode has the correct (60°) diagonals

logger := l.Named("setup-networking").Leveled(slog.LevelDebug)
t.Helper()
Expand All@@ -433,101 +438,109 @@ func (n TriangleNetwork) SetupNetworking(t *testing.T, l slog.Logger) TestNetwor
network.ServerNetNS = createNetNS(t, namePrefix+"server")
network.Client1NetNS = createNetNS(t, namePrefix+"client1")
network.Client2NetNS = createNetNS(t, namePrefix+"client2")
network.RouterNetNS = createNetNS(t, namePrefix+"router")

// Create veth pair between server andclient1
network.ServerClient1VethPair = vethPair{
Outer: namePrefix + "s-1",
Inner: namePrefix + "1-s",
// Create veth pair between server androuter
network.ServerVethPair = vethPair{
Outer: namePrefix + "s-r",
Inner: namePrefix + "r-s",
}
err := createVethPair(network.ServerClient1VethPair.Outer, network.ServerClient1VethPair.Inner)
err := createVethPair(network.ServerVethPair.Outer, network.ServerVethPair.Inner)
require.NoErrorf(t, err, "create veth pair %q <-> %q",
network.ServerClient1VethPair.Outer, network.ServerClient1VethPair.Inner)
network.ServerVethPair.Outer, network.ServerVethPair.Inner)

// Move server-client1 veth ends to their respective namespaces
err = setVethNetNS(network.ServerClient1VethPair.Outer, int(network.ServerNetNS.Fd()))
require.NoErrorf(t, err, "set veth %q to server NetNS", network.ServerClient1VethPair.Outer)
err = setVethNetNS(network.ServerClient1VethPair.Inner, int(network.Client1NetNS.Fd()))
require.NoErrorf(t, err, "set veth %q toclient1 NetNS", network.ServerClient1VethPair.Inner)
// Move server-router veth ends to their respective namespaces
err = setVethNetNS(network.ServerVethPair.Outer, int(network.ServerNetNS.Fd()))
require.NoErrorf(t, err, "set veth %q to server NetNS", network.ServerVethPair.Outer)
err = setVethNetNS(network.ServerVethPair.Inner, int(network.RouterNetNS.Fd()))
require.NoErrorf(t, err, "set veth %q torouter NetNS", network.ServerVethPair.Inner)

// Create veth pair betweenserver andclient2
network.ServerClient2VethPair = vethPair{
Outer: namePrefix + "s-2",
Inner: namePrefix + "2-s",
// Create veth pair betweenclient1 androuter
network.Client1VethPair = vethPair{
Outer: namePrefix + "1-r",
Inner: namePrefix + "r-1",
}
err = createVethPair(network.ServerClient2VethPair.Outer, network.ServerClient2VethPair.Inner)
logger.Debug(context.Background(), "creating client1 link", slog.F("mtu", n.Client1MTU))
err = createVethPair(network.Client1VethPair.Outer, network.Client1VethPair.Inner, withMTU(n.Client1MTU))
require.NoErrorf(t, err, "create veth pair %q <-> %q",
network.ServerClient2VethPair.Outer, network.ServerClient2VethPair.Inner)
network.Client1VethPair.Outer, network.Client1VethPair.Inner)

// Moveserver-client2 veth ends to their respective namespaces
err = setVethNetNS(network.ServerClient2VethPair.Outer, int(network.ServerNetNS.Fd()))
require.NoErrorf(t, err, "set veth %q to server NetNS", network.ServerClient2VethPair.Outer)
err = setVethNetNS(network.ServerClient2VethPair.Inner, int(network.Client2NetNS.Fd()))
require.NoErrorf(t, err, "set veth %q to client2 NetNS", network.ServerClient2VethPair.Inner)
// Moveclient1-router veth ends to their respective namespaces
err = setVethNetNS(network.Client1VethPair.Outer, int(network.Client1NetNS.Fd()))
require.NoErrorf(t, err, "set veth %q to server NetNS", network.Client1VethPair.Outer)
err = setVethNetNS(network.Client1VethPair.Inner, int(network.RouterNetNS.Fd()))
require.NoErrorf(t, err, "set veth %q to client2 NetNS", network.Client1VethPair.Inner)

// Create veth pair between client1 and client2
network.Client1Client2VethPair = vethPair{
Outer: namePrefix + "1-2",
Inner: namePrefix + "2-1",
network.Client2VethPair = vethPair{
Outer: namePrefix + "2-r",
Inner: namePrefix + "r-2",
}
logger.Debug(context.Background(), "creating inter-client link", slog.F("mtu", n.InterClientMTU))
err = createVethPair(network.Client1Client2VethPair.Outer, network.Client1Client2VethPair.Inner,
withMTU(n.InterClientMTU))

err = createVethPair(network.Client2VethPair.Outer, network.Client2VethPair.Inner)
require.NoErrorf(t, err, "create veth pair %q <-> %q",
network.Client1Client2VethPair.Outer, network.Client1Client2VethPair.Inner)
network.Client2VethPair.Outer, network.Client2VethPair.Inner)

// Move client1-client2 veth ends to their respective namespaces
err = setVethNetNS(network.Client1Client2VethPair.Outer, int(network.Client1NetNS.Fd()))
require.NoErrorf(t, err, "set veth %q to client1 NetNS", network.Client1Client2VethPair.Outer)
err = setVethNetNS(network.Client1Client2VethPair.Inner, int(network.Client2NetNS.Fd()))
require.NoErrorf(t, err, "set veth %q to client2 NetNS", network.Client1Client2VethPair.Inner)
err = setVethNetNS(network.Client2VethPair.Outer, int(network.Client2NetNS.Fd()))
require.NoErrorf(t, err, "set veth %q to client1 NetNS", network.Client2VethPair.Outer)
err = setVethNetNS(network.Client2VethPair.Inner, int(network.RouterNetNS.Fd()))
require.NoErrorf(t, err, "set veth %q to client2 NetNS", network.Client2VethPair.Inner)

// Set IP addresses according to the diagram:
err = setInterfaceIP6(network.ServerNetNS, network.ServerClient1VethPair.Outer, ula+"2::3")
require.NoErrorf(t, err, "set IP on server-client1 interface")
err = setInterfaceIP6(network.ServerNetNS, network.ServerClient2VethPair.Outer, ula+"3::3")
require.NoErrorf(t, err, "set IP on server-client2 interface")

err = setInterfaceIP6(network.Client1NetNS, network.ServerClient1VethPair.Inner, ula+"2::1")
require.NoErrorf(t, err, "set IP on client1-server interface")
err = setInterfaceIP6(network.Client1NetNS, network.Client1Client2VethPair.Outer, ula+"1::1")
require.NoErrorf(t, err, "set IP on client1-client2 interface")

err = setInterfaceIP6(network.Client2NetNS, network.ServerClient2VethPair.Inner, ula+"3::2")
require.NoErrorf(t, err, "set IP on client2-server interface")
err = setInterfaceIP6(network.Client2NetNS, network.Client1Client2VethPair.Inner, ula+"1::2")
require.NoErrorf(t, err, "set IP on client2-client1 interface")
err = setInterfaceIP6(network.ServerNetNS, network.ServerVethPair.Outer, ula+"3::2")
require.NoErrorf(t, err, "set IP on server interface")
err = setInterfaceIP6(network.Client1NetNS, network.Client1VethPair.Outer, ula+"1::2")
require.NoErrorf(t, err, "set IP on client1 interface")
err = setInterfaceIP6(network.Client2NetNS, network.Client2VethPair.Outer, ula+"2::2")
require.NoErrorf(t, err, "set IP on client2 interface")

err = setInterfaceIP6(network.RouterNetNS, network.ServerVethPair.Inner, ula+"3::1")
require.NoErrorf(t, err, "set IP on router-server interface")
err = setInterfaceIP6(network.RouterNetNS, network.Client1VethPair.Inner, ula+"1::1")
require.NoErrorf(t, err, "set IP on router-client1 interface")
err = setInterfaceIP6(network.RouterNetNS, network.Client2VethPair.Inner, ula+"2::1")
require.NoErrorf(t, err, "set IP on router-client2 interface")

// Bring up all interfaces
interfaces := []struct {
netNS *os.File
ifaceName string
netNS *os.File
ifaceName string
defaultRoute string
}{
{network.ServerNetNS, network.ServerClient1VethPair.Outer},
{network.ServerNetNS, network.ServerClient2VethPair.Outer},
{network.Client1NetNS, network.ServerClient1VethPair.Inner},
{network.Client1NetNS, network.Client1Client2VethPair.Outer},
{network.Client2NetNS, network.ServerClient2VethPair.Inner},
{network.Client2NetNS, network.Client1Client2VethPair.Inner},
{network.ServerNetNS, network.ServerVethPair.Outer, ula + "3::1"},
{network.Client1NetNS, network.Client1VethPair.Outer, ula + "1::1"},
{network.Client2NetNS, network.Client2VethPair.Outer, ula + "2::1"},
{network.RouterNetNS, network.ServerVethPair.Inner, ""},
{network.RouterNetNS, network.Client1VethPair.Inner, ""},
{network.RouterNetNS, network.Client2VethPair.Inner, ""},
}
for _, iface := range interfaces {
err = setInterfaceUp(iface.netNS, iface.ifaceName)
require.NoErrorf(t, err, "bring up interface %q", iface.ifaceName)
// Note: routes are not needed as we are fully connected, so nothing needs to forward IP to a further
// destination.

if iface.defaultRoute != "" {
err = addRouteInNetNS(iface.netNS, []string{"default", "via", iface.defaultRoute, "dev", iface.ifaceName})
require.NoErrorf(t, err, "add peer default route to %s", iface.defaultRoute)
}
}

// enable IP forwarding in the router
_, err = commandInNetNS(network.RouterNetNS, "sysctl", []string{"-w", "net.ipv6.conf.all.forwarding=1"}).Output()
require.NoError(t, wrapExitErr(err), "enable IPv6 forwarding in router NetNS")

return TestNetworking{
Server: TestNetworkingServer{
Process: TestNetworkingProcess{NetNS: network.ServerNetNS},
ListenAddr: "[::]:8080", // Server listens on all IPs
},
Client1: TestNetworkingClient{
Process: TestNetworkingProcess{NetNS: network.Client1NetNS},
ServerAccessURL: "http://[" + ula + "2::3]:8080", // Client1 accesses server directly
ServerAccessURL: "http://[" + ula + "3::2]:8080",
},
Client2: TestNetworkingClient{
Process: TestNetworkingProcess{NetNS: network.Client2NetNS},
ServerAccessURL: "http://[" + ula + "3::3]:8080", // Client2 accesses server directly
ServerAccessURL: "http://[" + ula + "3::2]:8080",
},
}
}
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp