Skip to content

Commit f1e5e4e

Browse files
committed
Fix Tailscale endpoint using wrong source IP with advertise_routes
When advertise_routes is configured, the gvisor stack may choose a subnet address as the source IP instead of the Tailscale IP. This causes ACL rules that filter by source to fail. Fix by explicitly binding to the Tailscale IP when making outbound connections, matching the behavior of the official tsnet implementation. Fixes #3489
1 parent 7fa7d4f commit f1e5e4e

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

protocol/tailscale/endpoint.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,26 +341,42 @@ func (t *Endpoint) DialContext(ctx context.Context, network string, destination
341341
}
342342
return N.DialSerial(ctx, t, network, destination, destinationAddresses)
343343
}
344-
addr := tcpip.FullAddress{
344+
addr4, addr6 := t.server.TailscaleIPs()
345+
remoteAddr := tcpip.FullAddress{
345346
NIC: 1,
346347
Port: destination.Port,
347348
Addr: addressFromAddr(destination.Addr),
348349
}
350+
var localAddr tcpip.FullAddress
349351
var networkProtocol tcpip.NetworkProtocolNumber
350352
if destination.IsIPv4() {
353+
if !addr4.IsValid() {
354+
return nil, E.New("missing Tailscale IPv4 address")
355+
}
351356
networkProtocol = header.IPv4ProtocolNumber
357+
localAddr = tcpip.FullAddress{
358+
NIC: 1,
359+
Addr: addressFromAddr(addr4),
360+
}
352361
} else {
362+
if !addr6.IsValid() {
363+
return nil, E.New("missing Tailscale IPv6 address")
364+
}
353365
networkProtocol = header.IPv6ProtocolNumber
366+
localAddr = tcpip.FullAddress{
367+
NIC: 1,
368+
Addr: addressFromAddr(addr6),
369+
}
354370
}
355371
switch N.NetworkName(network) {
356372
case N.NetworkTCP:
357-
tcpConn, err := gonet.DialContextTCP(ctx, t.stack, addr, networkProtocol)
373+
tcpConn, err := gonet.DialTCPWithBind(ctx, t.stack, localAddr, remoteAddr, networkProtocol)
358374
if err != nil {
359375
return nil, err
360376
}
361377
return tcpConn, nil
362378
case N.NetworkUDP:
363-
udpConn, err := gonet.DialUDP(t.stack, nil, &addr, networkProtocol)
379+
udpConn, err := gonet.DialUDP(t.stack, &localAddr, &remoteAddr, networkProtocol)
364380
if err != nil {
365381
return nil, err
366382
}

0 commit comments

Comments
 (0)