mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
control/controlhttp: add health warning for macOS filtering blocking Tailscale (#12546)
Updates #9658 Updates #12545 Change-Id: I6612b9b65eb193a1a651e219b5198c7c20ed94e1 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Co-authored-by: Andrea Gottardo <andrea@tailscale.com>
This commit is contained in:
parent
1023b2a82c
commit
0004827681
@ -32,12 +32,14 @@
|
|||||||
"net/http/httptrace"
|
"net/http/httptrace"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"tailscale.com/control/controlbase"
|
"tailscale.com/control/controlbase"
|
||||||
"tailscale.com/envknob"
|
"tailscale.com/envknob"
|
||||||
|
"tailscale.com/health"
|
||||||
"tailscale.com/net/dnscache"
|
"tailscale.com/net/dnscache"
|
||||||
"tailscale.com/net/dnsfallback"
|
"tailscale.com/net/dnsfallback"
|
||||||
"tailscale.com/net/netutil"
|
"tailscale.com/net/netutil"
|
||||||
@ -396,12 +398,28 @@ func (a *Dialer) resolver() *dnscache.Resolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isLoopback(a net.Addr) bool {
|
||||||
|
if ta, ok := a.(*net.TCPAddr); ok {
|
||||||
|
return ta.IP.IsLoopback()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var macOSScreenTime = health.Register(&health.Warnable{
|
||||||
|
Code: "macos-screen-time",
|
||||||
|
Title: "Tailscale blocked by Screen Time",
|
||||||
|
Text: func(args health.Args) string {
|
||||||
|
return "macOS Screen Time seems to be blocking Tailscale. Try disabling Screen Time in System Settings > Screen Time > Content & Privacy > Access to Web Content."
|
||||||
|
},
|
||||||
|
ImpactsConnectivity: true,
|
||||||
|
})
|
||||||
|
|
||||||
// tryURLUpgrade connects to u, and tries to upgrade it to a net.Conn. If addr
|
// tryURLUpgrade connects to u, and tries to upgrade it to a net.Conn. If addr
|
||||||
// is valid, then no DNS is used and the connection will be made to the
|
// is valid, then no DNS is used and the connection will be made to the
|
||||||
// provided address.
|
// provided address.
|
||||||
//
|
//
|
||||||
// Only the provided ctx is used, not a.ctx.
|
// Only the provided ctx is used, not a.ctx.
|
||||||
func (a *Dialer) tryURLUpgrade(ctx context.Context, u *url.URL, addr netip.Addr, init []byte) (net.Conn, error) {
|
func (a *Dialer) tryURLUpgrade(ctx context.Context, u *url.URL, addr netip.Addr, init []byte) (_ net.Conn, retErr error) {
|
||||||
var dns *dnscache.Resolver
|
var dns *dnscache.Resolver
|
||||||
|
|
||||||
// If we were provided an address to dial, then create a resolver that just
|
// If we were provided an address to dial, then create a resolver that just
|
||||||
@ -423,6 +441,30 @@ func (a *Dialer) tryURLUpgrade(ctx context.Context, u *url.URL, addr netip.Addr,
|
|||||||
dialer = stdDialer.DialContext
|
dialer = stdDialer.DialContext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On macOS, see if Screen Time is blocking things.
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
var proxydIntercepted atomic.Bool // intercepted by macOS webfilterproxyd
|
||||||
|
origDialer := dialer
|
||||||
|
dialer = func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
|
c, err := origDialer(ctx, network, address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if isLoopback(c.LocalAddr()) && isLoopback(c.RemoteAddr()) {
|
||||||
|
proxydIntercepted.Store(true)
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil && proxydIntercepted.Load() {
|
||||||
|
a.HealthTracker.SetUnhealthy(macOSScreenTime, nil)
|
||||||
|
retErr = fmt.Errorf("macOS Screen Time is blocking network access: %w", retErr)
|
||||||
|
} else {
|
||||||
|
a.HealthTracker.SetHealthy(macOSScreenTime)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||||
defer tr.CloseIdleConnections()
|
defer tr.CloseIdleConnections()
|
||||||
tr.Proxy = a.getProxyFunc()
|
tr.Proxy = a.getProxyFunc()
|
||||||
|
Loading…
Reference in New Issue
Block a user