WIP: rebase fork onto upstream/main (v1.103.0) #15
@@ -1154,6 +1154,26 @@ func (t *Wrapper) injectedRead(res tunInjectedRead, outBuffs [][]byte, sizes []i
|
||||
}
|
||||
|
||||
invertGSOChecksum(pkt, gso)
|
||||
// Check if this is a packet for conn25-style app connectors,
|
||||
// and perform the necessary NAT. The main case that requires
|
||||
// NAT from netstack toward WireGuard is an SNAT on return traffic
|
||||
// from the target application on the internet, translating
|
||||
// the original server's source IP to the TransitIP.
|
||||
// The hook can also perform DNAT for client-originated traffic,
|
||||
// translating the destination MagicIP to a TransitIP, and rejects
|
||||
// MagicIPs that have not been approved for the client.
|
||||
//
|
||||
// Normal non-connector traffic is forwarded unmodified.
|
||||
//
|
||||
// Cross-tailnet conn25 app connector connections are not supported,
|
||||
// so at most one of this hook and the following pc.snat should modify the packet.
|
||||
if t.PreFilterPacketOutboundToWireGuardAppConnectorIntercept != nil {
|
||||
if r := t.PreFilterPacketOutboundToWireGuardAppConnectorIntercept(p, t); r.IsDrop() {
|
||||
metricPacketOut.Add(1)
|
||||
metricPacketOutDrop.Add(1)
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
pc.snat(p)
|
||||
invertGSOChecksum(pkt, gso)
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"tailscale.com/disco"
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/net/packet"
|
||||
"tailscale.com/net/packet/checksum"
|
||||
"tailscale.com/tstest"
|
||||
"tailscale.com/tstime/mono"
|
||||
"tailscale.com/types/ipproto"
|
||||
@@ -1120,3 +1121,36 @@ func TestInterceptOrdering(t *testing.T) {
|
||||
t.Errorf("got number of intercepts run in Read(): %d; want: %d", seq, numOutboundIntercepts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInjectedReadCallsAppConnectorHook(t *testing.T) {
|
||||
var called bool
|
||||
hook := func(p *packet.Parsed, _ *Wrapper) filter.Response {
|
||||
called = true
|
||||
checksum.UpdateSrcAddr(p, netip.MustParseAddr("169.254.0.1"))
|
||||
return filter.Accept
|
||||
}
|
||||
|
||||
bus := eventbustest.NewBus(t)
|
||||
_, tun := newFakeTUN(t.Logf, bus, false)
|
||||
tun.PreFilterPacketOutboundToWireGuardAppConnectorIntercept = hook
|
||||
tun.Start()
|
||||
defer tun.Close()
|
||||
|
||||
if err := tun.InjectOutbound(udp4("145.53.32.10", "100.25.63.57", 80, 12345)); err != nil {
|
||||
t.Fatalf("InjectOutbound error: %v", err)
|
||||
}
|
||||
|
||||
var buf [MaxPacketSize]byte
|
||||
sizes := make([]int, 1)
|
||||
tun.Read([][]byte{buf[:]}, sizes, 0)
|
||||
|
||||
if !called {
|
||||
t.Error("app connector hook was not called in InjectOutbound")
|
||||
}
|
||||
|
||||
wantPkt := udp4("169.254.0.1", "100.25.63.57", 80, 12345)
|
||||
gotPkt := buf[:sizes[0]]
|
||||
if !bytes.Equal(wantPkt, gotPkt) {
|
||||
t.Errorf("packet mismatch\nwant:\t% x\ngot:\t% x", wantPkt, gotPkt)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user