Skip to content

Commit cc96c93

Browse files
committed
tunnel: check for WeakHostSend/Forwarding in pitfalls
Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent eada12b commit cc96c93

File tree

4 files changed

+91
-3
lines changed

4 files changed

+91
-3
lines changed

manager/service.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
5555
}
5656

5757
services.PrintStarting()
58-
checkForPitfalls()
5958

6059
path, err := os.Executable()
6160
if err != nil {

tunnel/interfacewatcher.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func (iw *interfaceWatcher) setup(family winipcfg.AddressFamily) {
8080
iw.errors <- interfaceWatcherError{services.ErrorSetNetConfig, err}
8181
return
8282
}
83+
evaluateDynamicPitfalls(family, iw.conf, iw.luid)
8384

8485
iw.started <- family
8586
}

manager/pitfalls.go renamed to tunnel/pitfalls.go

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
44
*/
55

6-
package manager
6+
package tunnel
77

88
import (
99
"log"
@@ -12,15 +12,24 @@ import (
1212

1313
"golang.org/x/sys/windows"
1414
"golang.org/x/sys/windows/svc/mgr"
15+
"golang.zx2c4.com/go118/netip"
16+
"golang.zx2c4.com/wireguard/windows/conf"
17+
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
1518
)
1619

17-
func checkForPitfalls() {
20+
func evaluateStaticPitfalls() {
1821
go func() {
1922
pitfallDnsCacheDisabled()
2023
pitfallVirtioNetworkDriver()
2124
}()
2225
}
2326

27+
func evaluateDynamicPitfalls(family winipcfg.AddressFamily, conf *conf.Config, luid winipcfg.LUID) {
28+
go func() {
29+
pitfallWeakHostSend(family, conf, luid)
30+
}()
31+
}
32+
2433
func pitfallDnsCacheDisabled() {
2534
scm, err := mgr.Connect()
2635
if err != nil {
@@ -92,3 +101,80 @@ func pitfallVirtioNetworkDriver() {
92101
return
93102
}
94103
}
104+
105+
func pitfallWeakHostSend(family winipcfg.AddressFamily, conf *conf.Config, ourLUID winipcfg.LUID) {
106+
routingTable, err := winipcfg.GetIPForwardTable2(family)
107+
if err != nil {
108+
return
109+
}
110+
type endpointRoute struct {
111+
addr netip.Addr
112+
name string
113+
lowestMetric uint32
114+
highestCIDR uint8
115+
weakHostSend bool
116+
finalIsOurs bool
117+
}
118+
endpoints := make([]endpointRoute, 0, len(conf.Peers))
119+
for _, peer := range conf.Peers {
120+
addr, err := netip.ParseAddr(peer.Endpoint.Host)
121+
if err != nil {
122+
continue
123+
}
124+
endpoints = append(endpoints, endpointRoute{addr: addr, lowestMetric: ^uint32(0)})
125+
}
126+
for i := range routingTable {
127+
var (
128+
ifrow *winipcfg.MibIfRow2
129+
ifacerow *winipcfg.MibIPInterfaceRow
130+
metric uint32
131+
)
132+
for j := range endpoints {
133+
r, e := &routingTable[i], &endpoints[j]
134+
if (e.addr.Is4() && family != windows.AF_INET) || (e.addr.Is6() && family != windows.AF_INET6) {
135+
continue
136+
}
137+
if r.DestinationPrefix.PrefixLength < e.highestCIDR {
138+
continue
139+
}
140+
if !r.DestinationPrefix.Prefix().Contains(e.addr) {
141+
continue
142+
}
143+
if ifrow == nil {
144+
ifrow, err = r.InterfaceLUID.Interface()
145+
if err != nil {
146+
continue
147+
}
148+
}
149+
if ifrow.OperStatus != winipcfg.IfOperStatusUp {
150+
continue
151+
}
152+
if ifacerow == nil {
153+
ifacerow, err = r.InterfaceLUID.IPInterface(family)
154+
if err != nil {
155+
continue
156+
}
157+
metric = r.Metric + ifacerow.Metric
158+
}
159+
if r.DestinationPrefix.PrefixLength == e.highestCIDR && metric > e.lowestMetric {
160+
continue
161+
}
162+
e.lowestMetric = metric
163+
e.highestCIDR = r.DestinationPrefix.PrefixLength
164+
e.finalIsOurs = r.InterfaceLUID == ourLUID
165+
if !e.finalIsOurs {
166+
e.name = ifrow.Alias()
167+
e.weakHostSend = ifacerow.ForwardingEnabled || ifacerow.WeakHostSend
168+
}
169+
}
170+
}
171+
problematicInterfaces := make(map[string]bool, len(endpoints))
172+
for _, e := range endpoints {
173+
if e.weakHostSend && e.finalIsOurs {
174+
problematicInterfaces[e.name] = true
175+
}
176+
}
177+
for iface := range problematicInterfaces {
178+
log.Printf("Warning: the %q interface has Forwarding/WeakHostSend enabled, which will cause routing loops", iface)
179+
}
180+
}

tunnel/service.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
135135
}
136136
}
137137

138+
evaluateStaticPitfalls()
139+
138140
log.Println("Watching network interfaces")
139141
watcher, err = watchInterface()
140142
if err != nil {

0 commit comments

Comments
 (0)