Skip to content

Commit

Permalink
tunnel: check for WeakHostSend/Forwarding in pitfalls
Browse files Browse the repository at this point in the history
Signed-off-by: Jason A. Donenfeld <[email protected]>
  • Loading branch information
zx2c4 committed Nov 8, 2021
1 parent eada12b commit b1fc806
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
1 change: 0 additions & 1 deletion manager/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
}

services.PrintStarting()
checkForPitfalls()

path, err := os.Executable()
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions tunnel/interfacewatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
87 changes: 85 additions & 2 deletions manager/pitfalls.go → tunnel/pitfalls.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/

package manager
package tunnel

import (
"log"
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
}
}
2 changes: 2 additions & 0 deletions tunnel/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit b1fc806

Please sign in to comment.