mirror of
https://github.com/fosrl/newt.git
synced 2026-09-30 01:39:08 +02:00
Do not capture traffic destined for internal addresses
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
package netstack2
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// With an exit-node rule (0.0.0.0/0) installed, traffic addressed to newt's own
|
||||
// tunnel IP - e.g. olm's connection-status probe to the wgtester - must be left
|
||||
// for the main stack rather than matched by the catch-all and proxied out.
|
||||
func TestHandleIncomingPacket_LocalTunnelAddressBypassesCatchAll(t *testing.T) {
|
||||
ph, err := NewProxyHandler(ProxyHandlerOptions{EnableICMP: true, MTU: 1500})
|
||||
if err != nil {
|
||||
t.Fatalf("NewProxyHandler: %v", err)
|
||||
}
|
||||
if err := ph.Initialize(noopNotification{}); err != nil {
|
||||
t.Fatalf("Initialize: %v", err)
|
||||
}
|
||||
defer ph.Close()
|
||||
|
||||
tunnelIP := netip.MustParseAddr("100.90.128.1")
|
||||
clientIP := netip.MustParseAddr("100.90.128.5")
|
||||
internetIP := netip.MustParseAddr("203.0.113.50")
|
||||
|
||||
ph.SetLocalAddresses([]netip.Addr{tunnelIP})
|
||||
ph.AddSubnetRule(SubnetRule{
|
||||
SourcePrefix: netip.MustParsePrefix("100.90.128.0/24"),
|
||||
DestPrefix: netip.MustParsePrefix("0.0.0.0/0"),
|
||||
})
|
||||
|
||||
if ph.HandleIncomingPacket(buildICMPEchoRequest(t, clientIP, tunnelIP)) {
|
||||
t.Error("packet to the local tunnel IP was proxied; expected it to be left for the main stack")
|
||||
}
|
||||
if !ph.HandleIncomingPacket(buildICMPEchoRequest(t, clientIP, internetIP)) {
|
||||
t.Error("packet to an internet address should still match the exit-node rule")
|
||||
}
|
||||
}
|
||||
@@ -136,6 +136,13 @@ type ProxyHandler struct {
|
||||
accessLogger *AccessLogger // Access logger for tracking sessions
|
||||
httpRequestLogger *HTTPRequestLogger // HTTP request logger for proxied HTTP/HTTPS requests
|
||||
blocked atomic.Bool // when true, all new connections are dropped
|
||||
|
||||
// localAddrs are the addresses owned by the main netstack (the tunnel IP).
|
||||
// Traffic addressed to them terminates on the main stack (wgtester, SSH,
|
||||
// ...) and must never be proxied out to the host network, even when a
|
||||
// catch-all rule such as an exit node's 0.0.0.0/0 would otherwise match it.
|
||||
// Written once during setup, before any packet is processed.
|
||||
localAddrs map[netip.Addr]struct{}
|
||||
}
|
||||
|
||||
// ProxyHandlerOptions configures the proxy handler
|
||||
@@ -494,6 +501,19 @@ func (p *ProxyHandler) Initialize(notifiable channel.Notification) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetLocalAddresses registers the addresses owned by the main netstack so
|
||||
// packets destined to them are left for the main stack instead of being proxied.
|
||||
// Must be called before the device starts processing packets.
|
||||
func (p *ProxyHandler) SetLocalAddresses(addrs []netip.Addr) {
|
||||
if p == nil {
|
||||
return
|
||||
}
|
||||
p.localAddrs = make(map[netip.Addr]struct{}, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
p.localAddrs[addr.Unmap()] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// HandleIncomingPacket processes incoming packets and determines if they should
|
||||
// be injected into the proxy stack
|
||||
func (p *ProxyHandler) HandleIncomingPacket(packet []byte) bool {
|
||||
@@ -522,6 +542,13 @@ func (p *ProxyHandler) HandleIncomingPacket(packet []byte) bool {
|
||||
dstBytes := dstIP.As4()
|
||||
dstAddr := netip.AddrFrom4(dstBytes)
|
||||
|
||||
// Traffic for our own tunnel IP (e.g. the olm connection-status probe to the
|
||||
// wgtester, or SSH) is served by the main stack. Without this, an exit node's
|
||||
// 0.0.0.0/0 rule matches it and forwards it out to the host network instead.
|
||||
if _, isLocal := p.localAddrs[dstAddr]; isLocal {
|
||||
return false
|
||||
}
|
||||
|
||||
// Parse transport layer to get destination port
|
||||
var dstPort uint16
|
||||
protocol := ipv4Header.TransportProtocol()
|
||||
|
||||
@@ -139,6 +139,9 @@ func CreateNetTUNWithOptions(localAddresses, dnsServers []netip.Addr, mtu int, o
|
||||
dev.hasV6 = true
|
||||
}
|
||||
}
|
||||
// Packets to our own addresses belong to the main stack, not the proxy.
|
||||
dev.proxyHandler.SetLocalAddresses(localAddresses)
|
||||
|
||||
if dev.hasV4 {
|
||||
dev.stack.AddRoute(tcpip.Route{Destination: header.IPv4EmptySubnet, NIC: 1})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user