wgengine{,/magicsock}: fix, improve "tailscale ping" to default routes and subnets

e.g.

$ tailscale ping 1.1.1.1
exit node found but not enabled

$ tailscale ping 10.2.200.2
node "tsbfvlan2" found, but not using its 10.2.200.0/24 route

$ sudo tailscale  up --accept-routes
$ tailscale ping 10.2.200.2
pong from tsbfvlan2 (100.124.196.94) via 10.2.200.34:41641 in 1ms

$ tailscale ping mon.ts.tailscale.com
pong from monitoring (100.88.178.64) via DERP(sfo) in 83ms
pong from monitoring (100.88.178.64) via DERP(sfo) in 21ms
pong from monitoring (100.88.178.64) via [2604:a880:4:d1::37:d001]:41641 in 22ms

This necessarily moves code up from magicsock to wgengine, so we can
look at the actual wireguard config.

Fixes #1564

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2021-03-22 21:25:43 -07:00
parent 7e0d12e7cc
commit 0994a9f7c4
3 changed files with 97 additions and 54 deletions

View File

@@ -814,46 +814,6 @@ func (c *Conn) SetNetInfoCallback(fn func(*tailcfg.NetInfo)) {
}
}
// peerForIP returns the Node in nm that's responsible for
// handling the given IP address.
func peerForIP(nm *netmap.NetworkMap, ip netaddr.IP) (n *tailcfg.Node, ok bool) {
if nm == nil {
return nil, false
}
// Check for exact matches before looking for subnet matches.
for _, p := range nm.Peers {
for _, a := range p.Addresses {
if a.IP == ip {
return p, true
}
}
}
// TODO(bradfitz): this is O(n peers). Add ART to netaddr?
var best netaddr.IPPrefix
for _, p := range nm.Peers {
for _, cidr := range p.AllowedIPs {
if cidr.Contains(ip) {
if best.IsZero() || cidr.Bits > best.Bits {
n = p
best = cidr
}
}
}
}
return n, n != nil
}
// PeerForIP returns the node that ip should route to.
func (c *Conn) PeerForIP(ip netaddr.IP) (n *tailcfg.Node, ok bool) {
c.mu.Lock()
defer c.mu.Unlock()
if c.netMap == nil {
return
}
return peerForIP(c.netMap, ip)
}
// LastRecvActivityOfDisco returns the time we last got traffic from
// this endpoint (updated every ~10 seconds).
func (c *Conn) LastRecvActivityOfDisco(dk tailcfg.DiscoKey) time.Time {
@@ -871,21 +831,14 @@ func (c *Conn) LastRecvActivityOfDisco(dk tailcfg.DiscoKey) time.Time {
}
// Ping handles a "tailscale ping" CLI query.
func (c *Conn) Ping(ip netaddr.IP, cb func(*ipnstate.PingResult)) {
func (c *Conn) Ping(peer *tailcfg.Node, res *ipnstate.PingResult, cb func(*ipnstate.PingResult)) {
c.mu.Lock()
defer c.mu.Unlock()
res := &ipnstate.PingResult{IP: ip.String()}
if c.privateKey.IsZero() {
res.Err = "local tailscaled stopped"
cb(res)
return
}
peer, ok := peerForIP(c.netMap, ip)
if !ok {
res.Err = "no matching peer"
cb(res)
return
}
if len(peer.Addresses) > 0 {
res.NodeIP = peer.Addresses[0].IP.String()
}