aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-11-08 20:23:42 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2021-11-08 20:32:38 +0100
commitb1fc806ad0a845a4f4c8404cace4678ca8b7b702 (patch)
treed965c2cb5985c10302810f1c7807920e7d2f0fb9
parentbuild: bump to go 1.17.3 (diff)
downloadwireguard-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.go1
-rw-r--r--tunnel/interfacewatcher.go1
-rw-r--r--tunnel/pitfalls.go (renamed from manager/pitfalls.go)87
-rw-r--r--tunnel/service.go2
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 {