wgengine: have pinger use all single-IP routes
Fixes
@@ -156,21 +156,21 @@ func newUserspaceEngineAdvanced(logf logger.Logf, tundev tun.Device, routerGen R
// here.
go e.RequestStatus()
- // All nodes have one primary IP address, and it
- // is the first entry on the AllowedIPs list.
- //
- // This code is written defensively in case we ever
- // end up with an empty AllowedIPs list or somehow
- // have a subnet as the first entry.
- if len(allowedIPs) > 0 {
- if ones, bits := allowedIPs[0].Mask.Size(); ones == bits && ones != 0 {
+ // Ping every single-IP that peer routes.
+ // These synthetic packets are used to traverse NATs.
+ var ips []wgcfg.IP
+ for _, ipNet := range allowedIPs {
+ if ones, bits := ipNet.Mask.Size(); ones == bits && ones != 0 {
var ip wgcfg.IP
- copy(ip.Addr[:], allowedIPs[0].IP.To16())
- go e.pinger(peerKey, ip)
- return
+ copy(ip.Addr[:], ipNet.IP.To16())
+ ips = append(ips, ip)
}
}
- logf("ERROR: peer %s has unexpected AllowedIPs: %v", peerKey.ShortString(), allowedIPs)
+ if len(ips) > 0 {
+ go e.pinger(peerKey, ips)
+ } else {
+ logf("[unexpected] peer %s has no single-IP routes: %v", peerKey.ShortString(), allowedIPs)
+ }
},
CreateBind: e.magicConn.CreateBind,
CreateEndpoint: e.magicConn.CreateEndpoint,
@@ -227,8 +227,8 @@ func newUserspaceEngineAdvanced(logf logger.Logf, tundev tun.Device, routerGen R
//
// These generated packets are used to ensure we trigger the spray logic in
// the magicsock package for NAT traversal.
-func (e *userspaceEngine) pinger(peerKey wgcfg.Key, ip wgcfg.IP) {
- e.logf("generating initial ping traffic to %s (%v)", peerKey.ShortString(), ip)
+func (e *userspaceEngine) pinger(peerKey wgcfg.Key, ips []wgcfg.IP) {
+ e.logf("generating initial ping traffic to %s (%v)", peerKey.ShortString(), ips)
var srcIP packet.IP
e.wgLock.Lock()
@@ -257,7 +257,10 @@ func (e *userspaceEngine) pinger(peerKey wgcfg.Key, ip wgcfg.IP) {
const stopAfter = 3 * time.Second
start := time.Now()
- dstIP := packet.NewIP(ip.IP())
+ var dstIPs []packet.IP
+ for _, ip := range ips {
+ dstIPs = append(dstIPs, packet.NewIP(ip.IP()))
+ }
payload := []byte("magicsock_spray") // no meaning
@@ -286,10 +289,12 @@ func (e *userspaceEngine) pinger(peerKey wgcfg.Key, ip wgcfg.IP) {
if time.Since(start) > stopAfter {
return
}
+ for _, dstIP := range dstIPs {
b := packet.GenICMP(srcIP, dstIP, ipid, packet.EchoRequest, 0, payload)
- ipid++
e.wgdev.SendPacket(b)
}
+ ipid++
+ }
}
// TODO(apenwarr): dnsDomains really ought to be in wgcfg.Config.
