33 * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
44 */
55
6- package manager
6+ package tunnel
77
88import (
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+
2433func pitfallDnsCacheDisabled () {
2534 scm , err := mgr .Connect ()
2635 if err != nil {
@@ -92,3 +101,77 @@ 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 || (addr .Is4 () && family != windows .AF_INET ) || (addr .Is6 () && family != windows .AF_INET6 ) {
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 r .DestinationPrefix .PrefixLength < e .highestCIDR {
135+ continue
136+ }
137+ if ! r .DestinationPrefix .Prefix ().Contains (e .addr ) {
138+ continue
139+ }
140+ if ifrow == nil {
141+ ifrow , err = r .InterfaceLUID .Interface ()
142+ if err != nil {
143+ continue
144+ }
145+ }
146+ if ifrow .OperStatus != winipcfg .IfOperStatusUp {
147+ continue
148+ }
149+ if ifacerow == nil {
150+ ifacerow , err = r .InterfaceLUID .IPInterface (family )
151+ if err != nil {
152+ continue
153+ }
154+ metric = r .Metric + ifacerow .Metric
155+ }
156+ if r .DestinationPrefix .PrefixLength == e .highestCIDR && metric > e .lowestMetric {
157+ continue
158+ }
159+ e .lowestMetric = metric
160+ e .highestCIDR = r .DestinationPrefix .PrefixLength
161+ e .finalIsOurs = r .InterfaceLUID == ourLUID
162+ if ! e .finalIsOurs {
163+ e .name = ifrow .Alias ()
164+ e .weakHostSend = ifacerow .ForwardingEnabled || ifacerow .WeakHostSend
165+ }
166+ }
167+ }
168+ problematicInterfaces := make (map [string ]bool , len (endpoints ))
169+ for _ , e := range endpoints {
170+ if e .weakHostSend && e .finalIsOurs {
171+ problematicInterfaces [e .name ] = true
172+ }
173+ }
174+ for iface := range problematicInterfaces {
175+ log .Printf ("Warning: the %q interface has Forwarding/WeakHostSend enabled, which will cause routing loops" , iface )
176+ }
177+ }
0 commit comments