diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-11-08 20:23:42 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-11-08 20:32:38 +0100 |
commit | b1fc806ad0a845a4f4c8404cace4678ca8b7b702 (patch) | |
tree | d965c2cb5985c10302810f1c7807920e7d2f0fb9 | |
parent | build: bump to go 1.17.3 (diff) | |
download | wireguard-windows-b1fc806ad0a845a4f4c8404cace4678ca8b7b702.tar.xz wireguard-windows-b1fc806ad0a845a4f4c8404cace4678ca8b7b702.zip |
tunnel: check for WeakHostSend/Forwarding in pitfalls
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r-- | manager/service.go | 1 | ||||
-rw-r--r-- | tunnel/interfacewatcher.go | 1 | ||||
-rw-r--r-- | tunnel/pitfalls.go (renamed from manager/pitfalls.go) | 87 | ||||
-rw-r--r-- | tunnel/service.go | 2 |
4 files changed, 88 insertions, 3 deletions
diff --git a/manager/service.go b/manager/service.go index ba59a20e..d5c50156 100644 --- a/manager/service.go +++ b/manager/service.go @@ -55,7 +55,6 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest } services.PrintStarting() - checkForPitfalls() path, err := os.Executable() if err != nil { diff --git a/tunnel/interfacewatcher.go b/tunnel/interfacewatcher.go index f3dbc46a..08e8936a 100644 --- a/tunnel/interfacewatcher.go +++ b/tunnel/interfacewatcher.go @@ -80,6 +80,7 @@ func (iw *interfaceWatcher) setup(family winipcfg.AddressFamily) { iw.errors <- interfaceWatcherError{services.ErrorSetNetConfig, err} return } + evaluateDynamicPitfalls(family, iw.conf, iw.luid) iw.started <- family } diff --git a/manager/pitfalls.go b/tunnel/pitfalls.go index d7a11f90..6ac0f725 100644 --- a/manager/pitfalls.go +++ b/tunnel/pitfalls.go @@ -3,7 +3,7 @@ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved. */ -package manager +package tunnel import ( "log" @@ -12,15 +12,24 @@ import ( "golang.org/x/sys/windows" "golang.org/x/sys/windows/svc/mgr" + "golang.zx2c4.com/go118/netip" + "golang.zx2c4.com/wireguard/windows/conf" + "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" ) -func checkForPitfalls() { +func evaluateStaticPitfalls() { go func() { pitfallDnsCacheDisabled() pitfallVirtioNetworkDriver() }() } +func evaluateDynamicPitfalls(family winipcfg.AddressFamily, conf *conf.Config, luid winipcfg.LUID) { + go func() { + pitfallWeakHostSend(family, conf, luid) + }() +} + func pitfallDnsCacheDisabled() { scm, err := mgr.Connect() if err != nil { @@ -92,3 +101,77 @@ func pitfallVirtioNetworkDriver() { return } } + +func pitfallWeakHostSend(family winipcfg.AddressFamily, conf *conf.Config, ourLUID winipcfg.LUID) { + routingTable, err := winipcfg.GetIPForwardTable2(family) + if err != nil { + return + } + type endpointRoute struct { + addr netip.Addr + name string + lowestMetric uint32 + highestCIDR uint8 + weakHostSend bool + finalIsOurs bool + } + endpoints := make([]endpointRoute, 0, len(conf.Peers)) + for _, peer := range conf.Peers { + addr, err := netip.ParseAddr(peer.Endpoint.Host) + if err != nil || (addr.Is4() && family != windows.AF_INET) || (addr.Is6() && family != windows.AF_INET6) { + continue + } + endpoints = append(endpoints, endpointRoute{addr: addr, lowestMetric: ^uint32(0)}) + } + for i := range routingTable { + var ( + ifrow *winipcfg.MibIfRow2 + ifacerow *winipcfg.MibIPInterfaceRow + metric uint32 + ) + for j := range endpoints { + r, e := &routingTable[i], &endpoints[j] + if r.DestinationPrefix.PrefixLength < e.highestCIDR { + continue + } + if !r.DestinationPrefix.Prefix().Contains(e.addr) { + continue + } + if ifrow == nil { + ifrow, err = r.InterfaceLUID.Interface() + if err != nil { + continue + } + } + if ifrow.OperStatus != winipcfg.IfOperStatusUp { + continue + } + if ifacerow == nil { + ifacerow, err = r.InterfaceLUID.IPInterface(family) + if err != nil { + continue + } + metric = r.Metric + ifacerow.Metric + } + if r.DestinationPrefix.PrefixLength == e.highestCIDR && metric > e.lowestMetric { + continue + } + e.lowestMetric = metric + e.highestCIDR = r.DestinationPrefix.PrefixLength + e.finalIsOurs = r.InterfaceLUID == ourLUID + if !e.finalIsOurs { + e.name = ifrow.Alias() + e.weakHostSend = ifacerow.ForwardingEnabled || ifacerow.WeakHostSend + } + } + } + problematicInterfaces := make(map[string]bool, len(endpoints)) + for _, e := range endpoints { + if e.weakHostSend && e.finalIsOurs { + problematicInterfaces[e.name] = true + } + } + for iface := range problematicInterfaces { + log.Printf("Warning: the %q interface has Forwarding/WeakHostSend enabled, which will cause routing loops", iface) + } +} diff --git a/tunnel/service.go b/tunnel/service.go index 4a4f5e40..374d71d3 100644 --- a/tunnel/service.go +++ b/tunnel/service.go @@ -135,6 +135,8 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest, } } + evaluateStaticPitfalls() + log.Println("Watching network interfaces") watcher, err = watchInterface() if err != nil { |