|
|
@@ -139,15 +139,40 @@ func (d *Dialer) SetNetMon(netMon *netmon.Monitor) {
|
|
|
}
|
|
|
|
|
|
func (d *Dialer) linkChanged(delta *netmon.ChangeDelta) {
|
|
|
- if !delta.Major {
|
|
|
- return
|
|
|
- }
|
|
|
d.mu.Lock()
|
|
|
defer d.mu.Unlock()
|
|
|
for id, c := range d.activeSysConns {
|
|
|
- go c.Close()
|
|
|
- delete(d.activeSysConns, id)
|
|
|
+ if changeAffectsConn(delta, c) {
|
|
|
+ d.logf("tsdial: closing system connection %v->%v due to link change", c.LocalAddr(), c.RemoteAddr())
|
|
|
+ go c.Close()
|
|
|
+ delete(d.activeSysConns, id)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// changeAffectsConn reports whether the network change delta affects
|
|
|
+// the provided connection.
|
|
|
+func changeAffectsConn(delta *netmon.ChangeDelta, conn net.Conn) bool {
|
|
|
+ la, _ := conn.LocalAddr().(*net.TCPAddr)
|
|
|
+ ra, _ := conn.RemoteAddr().(*net.TCPAddr)
|
|
|
+ if la == nil || ra == nil {
|
|
|
+ return false // not TCP
|
|
|
+ }
|
|
|
+ lip, rip := la.AddrPort().Addr(), ra.AddrPort().Addr()
|
|
|
+
|
|
|
+ if delta.Old == nil {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if delta.Old.DefaultRouteInterface != delta.New.DefaultRouteInterface ||
|
|
|
+ delta.Old.HTTPProxy != delta.New.HTTPProxy {
|
|
|
+ return true
|
|
|
}
|
|
|
+ if !delta.New.HasIP(lip) && delta.Old.HasIP(lip) {
|
|
|
+ // Our interface with this source IP went away.
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ _ = rip // TODO(bradfitz): use the remote IP?
|
|
|
+ return false
|
|
|
}
|
|
|
|
|
|
func (d *Dialer) closeSysConn(id int) {
|
|
|
@@ -263,6 +288,12 @@ func ipNetOfNetwork(n string) string {
|
|
|
return "ip"
|
|
|
}
|
|
|
|
|
|
+func (d *Dialer) logf(format string, args ...any) {
|
|
|
+ if d.Logf != nil {
|
|
|
+ d.Logf(format, args...)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// SystemDial connects to the provided network address without going over
|
|
|
// Tailscale. It prefers going over the default interface and closes existing
|
|
|
// connections if the default interface changes. It is used to connect to
|
|
|
@@ -276,11 +307,7 @@ func (d *Dialer) SystemDial(ctx context.Context, network, addr string) (net.Conn
|
|
|
}
|
|
|
|
|
|
d.netnsDialerOnce.Do(func() {
|
|
|
- logf := d.Logf
|
|
|
- if logf == nil {
|
|
|
- logf = logger.Discard
|
|
|
- }
|
|
|
- d.netnsDialer = netns.NewDialer(logf, d.netMon)
|
|
|
+ d.netnsDialer = netns.NewDialer(d.logf, d.netMon)
|
|
|
})
|
|
|
c, err := d.netnsDialer.DialContext(ctx, network, addr)
|
|
|
if err != nil {
|