net/tsdial: assume all connections are affected if no default route is present

If this happens, it results in us pessimistically closing more
connections than might be necessary, but is more correct since we won't
"miss" a change to the default route interface and keep trying to send
data over a nonexistent interface, or one that can't reach the internet.

Updates tailscale/corp#19124

Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Ia0b8b04cb8cdcb0da0155fd08751c9dccba62c1a
This commit is contained in:
Andrew Dunham 2024-04-17 10:59:30 -04:00
parent 9e1c86901b
commit 375617c5c8

View File

@ -142,10 +142,16 @@ func (d *Dialer) SetNetMon(netMon *netmon.Monitor) {
}
var (
metricLinkChangeConnClosed = clientmetric.NewCounter("tsdial_linkchange_closes")
metricLinkChangeConnClosed = clientmetric.NewCounter("tsdial_linkchange_closes")
metricChangeDeltaNoDefaultRoute = clientmetric.NewCounter("tsdial_changedelta_no_default_route")
)
func (d *Dialer) linkChanged(delta *netmon.ChangeDelta) {
// Track how often we see ChangeDeltas with no DefaultRouteInterface.
if delta.New.DefaultRouteInterface == "" {
metricChangeDeltaNoDefaultRoute.Add(1)
}
d.mu.Lock()
defer d.mu.Unlock()
var anyClosed bool
@ -179,6 +185,14 @@ func changeAffectsConn(delta *netmon.ChangeDelta, conn net.Conn) bool {
delta.Old.HTTPProxy != delta.New.HTTPProxy {
return true
}
// In a few cases, we don't have a new DefaultRouteInterface (e.g. on
// Android; see tailscale/corp#19124); if so, pessimistically assume
// that all connections are affected.
if delta.New.DefaultRouteInterface == "" {
return true
}
if !delta.New.HasIP(lip) && delta.Old.HasIP(lip) {
// Our interface with this source IP went away.
return true