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

Commitaf4a668

Browse files
authored
fix: use tailscale that avoids small MTU paths (#18323)
Fixes#15523Uses latesthttps://github.com/coder/tailscale which includescoder/tailscale#85 to stop selecting paths with small MTU for direct connections.Also updates the tailnet integration test to reproduce the issue. The previous version had the 2 peers connected by a single veth, but this allows the OS to fragment the packet. In the new version, the 2 peers (and server) are all connected by a central router. The link between peer 1 and the router has an adjustable MTU. IPv6 does not allow packets to be fragmented by intermediate routers, so sending a too-large packet in this scenario forces the router to drop packets and reproduce the issue (without the tailscale changes).
1 parent2377d76 commitaf4a668

File tree

5 files changed

+109
-85
lines changed

5 files changed

+109
-85
lines changed

‎go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ replace github.com/tcnksm/go-httpstat => github.com/coder/go-httpstat v0.0.0-202
3636

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

4141
// This is replaced to include
4242
// 1. a fix for a data race: c.f. https://github.com/tailscale/wireguard-go/pull/25

‎go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -920,8 +920,8 @@ github.com/coder/serpent v0.10.0 h1:ofVk9FJXSek+SmL3yVE3GoArP83M+1tX+H7S4t8BSuM=
920920
github.com/coder/serpentv0.10.0/go.mod h1:cZFW6/fP+kE9nd/oRkEHJpG6sXCtQ+AX7WMMEHv0Y3Q=
921921
github.com/coder/sshv0.0.0-20231128192721-70855dedb788 h1:YoUSJ19E8AtuUFVYBpXuOD6a/zVP3rcxezNsoDseTUw=
922922
github.com/coder/sshv0.0.0-20231128192721-70855dedb788/go.mod h1:aGQbuCLyhRLMzZF067xc84Lh7JDs1FKwCmF1Crl9dxQ=
923-
github.com/coder/tailscalev1.1.1-0.20250422090654-5090e715905e h1:nope/SZfoLB9MCOB9wdCE6gW5+8l3PhFrDC5IWPL8bk=
924-
github.com/coder/tailscalev1.1.1-0.20250422090654-5090e715905e/go.mod h1:1ggFFdHTRjPRu9Yc1yA7nVHBYB50w9Ce7VIXNqcW6Ko=
923+
github.com/coder/tailscalev1.1.1-0.20250611020837-f14d20d23d8c h1:d/qBIi3Ez7KkopRgNtfdvTMqvqBg47d36qVfkd3C5EQ=
924+
github.com/coder/tailscalev1.1.1-0.20250611020837-f14d20d23d8c/go.mod h1:l7ml5uu7lFh5hY28lGYM4b/oFSmuPHYX6uk4RAu23Lc=
925925
github.com/coder/terraform-config-inspectv0.0.0-20250107175719-6d06d90c630e h1:JNLPDi2P73laR1oAclY6jWzAbucf70ASAvf5mh2cME0=
926926
github.com/coder/terraform-config-inspectv0.0.0-20250107175719-6d06d90c630e/go.mod h1:Gz/z9Hbn+4KSp8A2FBtNszfLSdT2Tn/uAKGuVqqWmDI=
927927
github.com/coder/terraform-provider-coder/v2v2.5.3 h1:EwqIIQKe/j8bsR4WyDJ3bD0dVdkfVqJ43TwClyGneUU=

‎tailnet/test/integration/integration.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/go-chi/chi/v5"
2626
"github.com/google/uuid"
2727
"github.com/stretchr/testify/require"
28+
"golang.org/x/sys/unix"
2829
"golang.org/x/xerrors"
2930
"tailscale.com/derp"
3031
"tailscale.com/derp/derphttp"
@@ -458,6 +459,16 @@ func (UDPEchoService) StartService(t *testing.T, logger slog.Logger, _ *tailnet.
458459
Port:EchoPort,
459460
})
460461
require.NoError(t,err)
462+
463+
// set path MTU discovery so that we don't fragment the responses.
464+
c,err:=l.SyscallConn()
465+
require.NoError(t,err)
466+
varsockErrerror
467+
err=c.Control(func(fduintptr) {
468+
sockErr=unix.SetsockoptInt(int(fd),unix.IPPROTO_IPV6,unix.IPV6_MTU_DISCOVER,unix.IP_PMTUDISC_DO)
469+
})
470+
require.NoError(t,err)
471+
require.NoError(t,sockErr)
461472
logger.Info(context.Background(),"started UDPEcho server")
462473
t.Cleanup(func() {
463474
lCloseErr:=l.Close()

‎tailnet/test/integration/integration_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ var topologies = []integration.TestTopology{
112112
{
113113
// Test that direct over normal MTU works.
114114
Name:"DirectMTU1500",
115-
NetworkingProvider: integration.TriangleNetwork{InterClientMTU:1500},
115+
NetworkingProvider: integration.TriangleNetwork{Client1MTU:1500},
116116
Server: integration.SimpleServerOptions{},
117117
ClientStarter: integration.BasicClientStarter{
118118
WaitForDirect:true,
@@ -124,7 +124,7 @@ var topologies = []integration.TestTopology{
124124
{
125125
// Test that small MTU works.
126126
Name:"MTU1280",
127-
NetworkingProvider: integration.TriangleNetwork{InterClientMTU:1280},
127+
NetworkingProvider: integration.TriangleNetwork{Client1MTU:1280},
128128
Server: integration.SimpleServerOptions{},
129129
ClientStarter: integration.BasicClientStarter{Service: integration.UDPEchoService{},LogPackets:true},
130130
RunTests:integration.TestBigUDP,

‎tailnet/test/integration/network.go

Lines changed: 93 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -390,33 +390,38 @@ func createFakeInternet(t *testing.T) fakeInternet {
390390
}
391391

392392
typeTriangleNetworkstruct {
393-
InterClientMTUint
393+
Client1MTUint
394394
}
395395

396396
typefakeTriangleNetworkstruct {
397-
NamePrefixstring
398-
ServerNetNS*os.File
399-
Client1NetNS*os.File
400-
Client2NetNS*os.File
401-
ServerClient1VethPairvethPair
402-
ServerClient2VethPairvethPair
403-
Client1Client2VethPairvethPair
397+
NamePrefixstring
398+
ServerNetNS*os.File
399+
Client1NetNS*os.File
400+
Client2NetNS*os.File
401+
RouterNetNS*os.File
402+
ServerVethPairvethPair
403+
Client1VethPairvethPair
404+
Client2VethPairvethPair
404405
}
405406

406-
// SetupNetworking creates multiple namespaces with veth pairs between them
407-
// with the following topology:
407+
// SetupNetworking creates multiple namespaces with a central router in the following topology
408408
// .
409-
// . ┌────────────────────────────────────────────┐
410-
// . │ Server │
411-
// . └─────┬───────────────────────────────────┬──┘
412-
// . │fdac:38fa:ffff:2::3 │fdac:38fa:ffff:3::3
413-
// . veth│ veth│
414-
// . │fdac:38fa:ffff:2::1 │fdac:38fa:ffff:3::2
415-
// . ┌───────┴──────┐ ┌─────┴───────┐
416-
// . │ │ fdac:38fa:ffff:1::2│ │
417-
// . │ Client 1 ├──────────────────────┤ Client 2 │
418-
// . │ │fdac:38fa:ffff:1::1 │ │
419-
// . └──────────────┘ └─────────────┘
409+
// . ┌──────────────┐
410+
// . │ │
411+
// . │ Server ├─────────────────────────────────────┐
412+
// . │ │fdac:38fa:ffff:3::2 │
413+
// . └──────────────┘ │ fdac:38fa:ffff:3::1
414+
// . ┌──────────────┐ ┌─────┴───────┐
415+
// . │ │ fdac:38fa:ffff:1::1│ │
416+
// . │ Client 1 ├───────────────────────────────┤ Router │
417+
// . │ │fdac:38fa:ffff:1::2 │ │
418+
// . └──────────────┘ └─────┬───────┘
419+
// . ┌──────────────┐ │ fdac:38fa:ffff:2::1
420+
// . │ │ │
421+
// . │ Client 2 ├─────────────────────────────────────┘
422+
// . │ │fdac:38fa:ffff:2::2
423+
// . └──────────────┘
424+
// The veth link between Client 1 and the router has a configurable MTU via Client1MTU.
420425
func (nTriangleNetwork)SetupNetworking(t*testing.T,l slog.Logger)TestNetworking {
421426
logger:=l.Named("setup-networking").Leveled(slog.LevelDebug)
422427
t.Helper()
@@ -433,101 +438,109 @@ func (n TriangleNetwork) SetupNetworking(t *testing.T, l slog.Logger) TestNetwor
433438
network.ServerNetNS=createNetNS(t,namePrefix+"server")
434439
network.Client1NetNS=createNetNS(t,namePrefix+"client1")
435440
network.Client2NetNS=createNetNS(t,namePrefix+"client2")
441+
network.RouterNetNS=createNetNS(t,namePrefix+"router")
436442

437-
// Create veth pair between server andclient1
438-
network.ServerClient1VethPair=vethPair{
439-
Outer:namePrefix+"s-1",
440-
Inner:namePrefix+"1-s",
443+
// Create veth pair between server androuter
444+
network.ServerVethPair=vethPair{
445+
Outer:namePrefix+"s-r",
446+
Inner:namePrefix+"r-s",
441447
}
442-
err:=createVethPair(network.ServerClient1VethPair.Outer,network.ServerClient1VethPair.Inner)
448+
err:=createVethPair(network.ServerVethPair.Outer,network.ServerVethPair.Inner)
443449
require.NoErrorf(t,err,"create veth pair %q <-> %q",
444-
network.ServerClient1VethPair.Outer,network.ServerClient1VethPair.Inner)
450+
network.ServerVethPair.Outer,network.ServerVethPair.Inner)
445451

446-
// Move server-client1 veth ends to their respective namespaces
447-
err=setVethNetNS(network.ServerClient1VethPair.Outer,int(network.ServerNetNS.Fd()))
448-
require.NoErrorf(t,err,"set veth %q to server NetNS",network.ServerClient1VethPair.Outer)
449-
err=setVethNetNS(network.ServerClient1VethPair.Inner,int(network.Client1NetNS.Fd()))
450-
require.NoErrorf(t,err,"set veth %q toclient1 NetNS",network.ServerClient1VethPair.Inner)
452+
// Move server-router veth ends to their respective namespaces
453+
err=setVethNetNS(network.ServerVethPair.Outer,int(network.ServerNetNS.Fd()))
454+
require.NoErrorf(t,err,"set veth %q to server NetNS",network.ServerVethPair.Outer)
455+
err=setVethNetNS(network.ServerVethPair.Inner,int(network.RouterNetNS.Fd()))
456+
require.NoErrorf(t,err,"set veth %q torouter NetNS",network.ServerVethPair.Inner)
451457

452-
// Create veth pair betweenserver andclient2
453-
network.ServerClient2VethPair=vethPair{
454-
Outer:namePrefix+"s-2",
455-
Inner:namePrefix+"2-s",
458+
// Create veth pair betweenclient1 androuter
459+
network.Client1VethPair=vethPair{
460+
Outer:namePrefix+"1-r",
461+
Inner:namePrefix+"r-1",
456462
}
457-
err=createVethPair(network.ServerClient2VethPair.Outer,network.ServerClient2VethPair.Inner)
463+
logger.Debug(context.Background(),"creating client1 link",slog.F("mtu",n.Client1MTU))
464+
err=createVethPair(network.Client1VethPair.Outer,network.Client1VethPair.Inner,withMTU(n.Client1MTU))
458465
require.NoErrorf(t,err,"create veth pair %q <-> %q",
459-
network.ServerClient2VethPair.Outer,network.ServerClient2VethPair.Inner)
466+
network.Client1VethPair.Outer,network.Client1VethPair.Inner)
460467

461-
// Moveserver-client2 veth ends to their respective namespaces
462-
err=setVethNetNS(network.ServerClient2VethPair.Outer,int(network.ServerNetNS.Fd()))
463-
require.NoErrorf(t,err,"set veth %q to server NetNS",network.ServerClient2VethPair.Outer)
464-
err=setVethNetNS(network.ServerClient2VethPair.Inner,int(network.Client2NetNS.Fd()))
465-
require.NoErrorf(t,err,"set veth %q to client2 NetNS",network.ServerClient2VethPair.Inner)
468+
// Moveclient1-router veth ends to their respective namespaces
469+
err=setVethNetNS(network.Client1VethPair.Outer,int(network.Client1NetNS.Fd()))
470+
require.NoErrorf(t,err,"set veth %q to server NetNS",network.Client1VethPair.Outer)
471+
err=setVethNetNS(network.Client1VethPair.Inner,int(network.RouterNetNS.Fd()))
472+
require.NoErrorf(t,err,"set veth %q to client2 NetNS",network.Client1VethPair.Inner)
466473

467474
// Create veth pair between client1 and client2
468-
network.Client1Client2VethPair=vethPair{
469-
Outer:namePrefix+"1-2",
470-
Inner:namePrefix+"2-1",
475+
network.Client2VethPair=vethPair{
476+
Outer:namePrefix+"2-r",
477+
Inner:namePrefix+"r-2",
471478
}
472-
logger.Debug(context.Background(),"creating inter-client link",slog.F("mtu",n.InterClientMTU))
473-
err=createVethPair(network.Client1Client2VethPair.Outer,network.Client1Client2VethPair.Inner,
474-
withMTU(n.InterClientMTU))
479+
480+
err=createVethPair(network.Client2VethPair.Outer,network.Client2VethPair.Inner)
475481
require.NoErrorf(t,err,"create veth pair %q <-> %q",
476-
network.Client1Client2VethPair.Outer,network.Client1Client2VethPair.Inner)
482+
network.Client2VethPair.Outer,network.Client2VethPair.Inner)
477483

478484
// Move client1-client2 veth ends to their respective namespaces
479-
err=setVethNetNS(network.Client1Client2VethPair.Outer,int(network.Client1NetNS.Fd()))
480-
require.NoErrorf(t,err,"set veth %q to client1 NetNS",network.Client1Client2VethPair.Outer)
481-
err=setVethNetNS(network.Client1Client2VethPair.Inner,int(network.Client2NetNS.Fd()))
482-
require.NoErrorf(t,err,"set veth %q to client2 NetNS",network.Client1Client2VethPair.Inner)
485+
err=setVethNetNS(network.Client2VethPair.Outer,int(network.Client2NetNS.Fd()))
486+
require.NoErrorf(t,err,"set veth %q to client1 NetNS",network.Client2VethPair.Outer)
487+
err=setVethNetNS(network.Client2VethPair.Inner,int(network.RouterNetNS.Fd()))
488+
require.NoErrorf(t,err,"set veth %q to client2 NetNS",network.Client2VethPair.Inner)
483489

484490
// Set IP addresses according to the diagram:
485-
err=setInterfaceIP6(network.ServerNetNS,network.ServerClient1VethPair.Outer,ula+"2::3")
486-
require.NoErrorf(t,err,"set IP on server-client1 interface")
487-
err=setInterfaceIP6(network.ServerNetNS,network.ServerClient2VethPair.Outer,ula+"3::3")
488-
require.NoErrorf(t,err,"set IP on server-client2 interface")
489-
490-
err=setInterfaceIP6(network.Client1NetNS,network.ServerClient1VethPair.Inner,ula+"2::1")
491-
require.NoErrorf(t,err,"set IP on client1-server interface")
492-
err=setInterfaceIP6(network.Client1NetNS,network.Client1Client2VethPair.Outer,ula+"1::1")
493-
require.NoErrorf(t,err,"set IP on client1-client2 interface")
494-
495-
err=setInterfaceIP6(network.Client2NetNS,network.ServerClient2VethPair.Inner,ula+"3::2")
496-
require.NoErrorf(t,err,"set IP on client2-server interface")
497-
err=setInterfaceIP6(network.Client2NetNS,network.Client1Client2VethPair.Inner,ula+"1::2")
498-
require.NoErrorf(t,err,"set IP on client2-client1 interface")
491+
err=setInterfaceIP6(network.ServerNetNS,network.ServerVethPair.Outer,ula+"3::2")
492+
require.NoErrorf(t,err,"set IP on server interface")
493+
err=setInterfaceIP6(network.Client1NetNS,network.Client1VethPair.Outer,ula+"1::2")
494+
require.NoErrorf(t,err,"set IP on client1 interface")
495+
err=setInterfaceIP6(network.Client2NetNS,network.Client2VethPair.Outer,ula+"2::2")
496+
require.NoErrorf(t,err,"set IP on client2 interface")
497+
498+
err=setInterfaceIP6(network.RouterNetNS,network.ServerVethPair.Inner,ula+"3::1")
499+
require.NoErrorf(t,err,"set IP on router-server interface")
500+
err=setInterfaceIP6(network.RouterNetNS,network.Client1VethPair.Inner,ula+"1::1")
501+
require.NoErrorf(t,err,"set IP on router-client1 interface")
502+
err=setInterfaceIP6(network.RouterNetNS,network.Client2VethPair.Inner,ula+"2::1")
503+
require.NoErrorf(t,err,"set IP on router-client2 interface")
499504

500505
// Bring up all interfaces
501506
interfaces:= []struct {
502-
netNS*os.File
503-
ifaceNamestring
507+
netNS*os.File
508+
ifaceNamestring
509+
defaultRoutestring
504510
}{
505-
{network.ServerNetNS,network.ServerClient1VethPair.Outer},
506-
{network.ServerNetNS,network.ServerClient2VethPair.Outer},
507-
{network.Client1NetNS,network.ServerClient1VethPair.Inner},
508-
{network.Client1NetNS,network.Client1Client2VethPair.Outer},
509-
{network.Client2NetNS,network.ServerClient2VethPair.Inner},
510-
{network.Client2NetNS,network.Client1Client2VethPair.Inner},
511+
{network.ServerNetNS,network.ServerVethPair.Outer,ula+"3::1"},
512+
{network.Client1NetNS,network.Client1VethPair.Outer,ula+"1::1"},
513+
{network.Client2NetNS,network.Client2VethPair.Outer,ula+"2::1"},
514+
{network.RouterNetNS,network.ServerVethPair.Inner,""},
515+
{network.RouterNetNS,network.Client1VethPair.Inner,""},
516+
{network.RouterNetNS,network.Client2VethPair.Inner,""},
511517
}
512518
for_,iface:=rangeinterfaces {
513519
err=setInterfaceUp(iface.netNS,iface.ifaceName)
514520
require.NoErrorf(t,err,"bring up interface %q",iface.ifaceName)
515-
// Note: routes are not needed as we are fully connected, so nothing needs to forward IP to a further
516-
// destination.
521+
522+
ififace.defaultRoute!="" {
523+
err=addRouteInNetNS(iface.netNS, []string{"default","via",iface.defaultRoute,"dev",iface.ifaceName})
524+
require.NoErrorf(t,err,"add peer default route to %s",iface.defaultRoute)
525+
}
517526
}
518527

528+
// enable IP forwarding in the router
529+
_,err=commandInNetNS(network.RouterNetNS,"sysctl", []string{"-w","net.ipv6.conf.all.forwarding=1"}).Output()
530+
require.NoError(t,wrapExitErr(err),"enable IPv6 forwarding in router NetNS")
531+
519532
returnTestNetworking{
520533
Server:TestNetworkingServer{
521534
Process:TestNetworkingProcess{NetNS:network.ServerNetNS},
522535
ListenAddr:"[::]:8080",// Server listens on all IPs
523536
},
524537
Client1:TestNetworkingClient{
525538
Process:TestNetworkingProcess{NetNS:network.Client1NetNS},
526-
ServerAccessURL:"http://["+ula+"2::3]:8080",// Client1 accesses server directly
539+
ServerAccessURL:"http://["+ula+"3::2]:8080",
527540
},
528541
Client2:TestNetworkingClient{
529542
Process:TestNetworkingProcess{NetNS:network.Client2NetNS},
530-
ServerAccessURL:"http://["+ula+"3::3]:8080",// Client2 accesses server directly
543+
ServerAccessURL:"http://["+ula+"3::2]:8080",
531544
},
532545
}
533546
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp