wgengine/netstack: handle 4via6 routes that are advertised by the same node
Previously, a node that was advertising a 4via6 route wouldn't be able to make use of that same route; the packet would be delivered to Tailscale, but since we weren't accepting it in handleLocalPackets, the packet wouldn't be delivered to netstack and would never hit the 4via6 logic. Let's add that support so that usage of 4via6 is consistent regardless of where the connection is initiated from. Updates #11304 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: Ic28dc2e58080d76100d73b93360f4698605af7cb
This commit is contained in:
@ -706,3 +706,94 @@ func TestTCPForwardLimits_PerClient(t *testing.T) {
|
||||
t.Errorf("got clientmetric limit metric=%d, want 1", v)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandleLocalPackets tests the handleLocalPackets function, ensuring that
|
||||
// we are properly deciding to handle packets that are destined for "local"
|
||||
// IPs–addresses that are either for this node, or that it is responsible for.
|
||||
//
|
||||
// See, e.g. #11304
|
||||
func TestHandleLocalPackets(t *testing.T) {
|
||||
var (
|
||||
selfIP4 = netip.MustParseAddr("100.64.1.2")
|
||||
selfIP6 = netip.MustParseAddr("fd7a:115c:a1e0::123")
|
||||
)
|
||||
|
||||
impl := makeNetstack(t, func(impl *Impl) {
|
||||
impl.ProcessSubnets = false
|
||||
impl.ProcessLocalIPs = false
|
||||
impl.atomicIsLocalIPFunc.Store(func(addr netip.Addr) bool {
|
||||
return addr == selfIP4 || addr == selfIP6
|
||||
})
|
||||
})
|
||||
|
||||
prefs := ipn.NewPrefs()
|
||||
prefs.AdvertiseRoutes = []netip.Prefix{
|
||||
// $ tailscale debug via 7 10.1.1.0/24
|
||||
// fd7a:115c:a1e0:b1a:0:7:a01:100/120
|
||||
netip.MustParsePrefix("fd7a:115c:a1e0:b1a:0:7:a01:100/120"),
|
||||
}
|
||||
_, err := impl.lb.EditPrefs(&ipn.MaskedPrefs{
|
||||
Prefs: *prefs,
|
||||
AdvertiseRoutesSet: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("EditPrefs: %v", err)
|
||||
}
|
||||
|
||||
t.Run("ShouldHandleServiceIP", func(t *testing.T) {
|
||||
pkt := &packet.Parsed{
|
||||
IPVersion: 4,
|
||||
IPProto: ipproto.TCP,
|
||||
Src: netip.MustParseAddrPort("127.0.0.1:9999"),
|
||||
Dst: netip.MustParseAddrPort("100.100.100.100:53"),
|
||||
TCPFlags: packet.TCPSyn,
|
||||
}
|
||||
resp := impl.handleLocalPackets(pkt, impl.tundev)
|
||||
if resp != filter.DropSilently {
|
||||
t.Errorf("got filter outcome %v, want filter.DropSilently", resp)
|
||||
}
|
||||
})
|
||||
t.Run("ShouldHandle4via6", func(t *testing.T) {
|
||||
pkt := &packet.Parsed{
|
||||
IPVersion: 6,
|
||||
IPProto: ipproto.TCP,
|
||||
Src: netip.MustParseAddrPort("[::1]:1234"),
|
||||
|
||||
// This is an IP in the above 4via6 subnet that this node handles.
|
||||
// $ tailscale debug via 7 10.1.1.9/24
|
||||
// fd7a:115c:a1e0:b1a:0:7:a01:109/120
|
||||
Dst: netip.MustParseAddrPort("[fd7a:115c:a1e0:b1a:0:7:a01:109]:5678"),
|
||||
TCPFlags: packet.TCPSyn,
|
||||
}
|
||||
resp := impl.handleLocalPackets(pkt, impl.tundev)
|
||||
|
||||
// DropSilently is the outcome we expected, since we actually
|
||||
// handled this packet by injecting it into netstack, which
|
||||
// will handle creating the TCP forwarder. We drop it so we
|
||||
// don't process the packet outside of netstack.
|
||||
if resp != filter.DropSilently {
|
||||
t.Errorf("got filter outcome %v, want filter.DropSilently", resp)
|
||||
}
|
||||
})
|
||||
t.Run("OtherNonHandled", func(t *testing.T) {
|
||||
pkt := &packet.Parsed{
|
||||
IPVersion: 6,
|
||||
IPProto: ipproto.TCP,
|
||||
Src: netip.MustParseAddrPort("[::1]:1234"),
|
||||
|
||||
// This IP is *not* in the above 4via6 route
|
||||
// $ tailscale debug via 99 10.1.1.9/24
|
||||
// fd7a:115c:a1e0:b1a:0:63:a01:109/120
|
||||
Dst: netip.MustParseAddrPort("[fd7a:115c:a1e0:b1a:0:63:a01:109]:5678"),
|
||||
TCPFlags: packet.TCPSyn,
|
||||
}
|
||||
resp := impl.handleLocalPackets(pkt, impl.tundev)
|
||||
|
||||
// Accept means that handleLocalPackets does not handle this
|
||||
// packet, we "accept" it to continue further processing,
|
||||
// instead of dropping because it was already handled.
|
||||
if resp != filter.Accept {
|
||||
t.Errorf("got filter outcome %v, want filter.Accept", resp)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user