@ -32,6 +32,7 @@ import (
"tailscale.com/clientupdate"
"tailscale.com/clientupdate"
"tailscale.com/drive"
"tailscale.com/drive"
"tailscale.com/envknob"
"tailscale.com/envknob"
"tailscale.com/health/healthmsg"
"tailscale.com/hostinfo"
"tailscale.com/hostinfo"
"tailscale.com/ipn"
"tailscale.com/ipn"
"tailscale.com/ipn/ipnauth"
"tailscale.com/ipn/ipnauth"
@ -82,71 +83,72 @@ var handler = map[string]LocalAPIHandler{
// The other /localapi/v0/NAME handlers are exact matches and contain only NAME
// The other /localapi/v0/NAME handlers are exact matches and contain only NAME
// without a trailing slash:
// without a trailing slash:
"alpha-set-device-attrs" : ( * Handler ) . serveSetDeviceAttrs , // see tailscale/corp#24690
"alpha-set-device-attrs" : ( * Handler ) . serveSetDeviceAttrs , // see tailscale/corp#24690
"bugreport" : ( * Handler ) . serveBugReport ,
"bugreport" : ( * Handler ) . serveBugReport ,
"check-ip-forwarding" : ( * Handler ) . serveCheckIPForwarding ,
"check-ip-forwarding" : ( * Handler ) . serveCheckIPForwarding ,
"check-prefs" : ( * Handler ) . serveCheckPrefs ,
"check-prefs" : ( * Handler ) . serveCheckPrefs ,
"check-udp-gro-forwarding" : ( * Handler ) . serveCheckUDPGROForwarding ,
"check-reverse-path-filtering" : ( * Handler ) . serveCheckReversePathFiltering ,
"component-debug-logging" : ( * Handler ) . serveComponentDebugLogging ,
"check-udp-gro-forwarding" : ( * Handler ) . serveCheckUDPGROForwarding ,
"debug" : ( * Handler ) . serveDebug ,
"component-debug-logging" : ( * Handler ) . serveComponentDebugLogging ,
"debug-derp-region" : ( * Handler ) . serveDebugDERPRegion ,
"debug" : ( * Handler ) . serveDebug ,
"debug-dial-types" : ( * Handler ) . serveDebugDialTypes ,
"debug-derp-region" : ( * Handler ) . serveDebugDERPRegion ,
"debug-log" : ( * Handler ) . serveDebugLog ,
"debug-dial-types" : ( * Handler ) . serveDebugDialTypes ,
"debug-packet-filter-matches" : ( * Handler ) . serveDebugPacketFilterMatches ,
"debug-log" : ( * Handler ) . serveDebugLog ,
"debug-packet-filter-rules" : ( * Handler ) . serveDebugPacketFilterRules ,
"debug-packet-filter-matches" : ( * Handler ) . serveDebugPacketFilterMatches ,
"debug-peer-endpoint-changes" : ( * Handler ) . serveDebugPeerEndpointChanges ,
"debug-packet-filter-rules" : ( * Handler ) . serveDebugPacketFilterRules ,
"debug-portmap" : ( * Handler ) . serveDebugPortmap ,
"debug-peer-endpoint-changes" : ( * Handler ) . serveDebugPeerEndpointChanges ,
"derpmap" : ( * Handler ) . serveDERPMap ,
"debug-portmap" : ( * Handler ) . serveDebugPortmap ,
"dev-set-state-store" : ( * Handler ) . serveDevSetStateStore ,
"derpmap" : ( * Handler ) . serveDERPMap ,
"dial" : ( * Handler ) . serveDial ,
"dev-set-state-store" : ( * Handler ) . serveDevSetStateStore ,
"disconnect-control" : ( * Handler ) . disconnectControl ,
"dial" : ( * Handler ) . serveDial ,
"dns-osconfig" : ( * Handler ) . serveDNSOSConfig ,
"disconnect-control" : ( * Handler ) . disconnectControl ,
"dns-query" : ( * Handler ) . serveDNSQuery ,
"dns-osconfig" : ( * Handler ) . serveDNSOSConfig ,
"drive/fileserver-address" : ( * Handler ) . serveDriveServerAddr ,
"dns-query" : ( * Handler ) . serveDNSQuery ,
"drive/shares" : ( * Handler ) . serveShares ,
"drive/fileserver-address" : ( * Handler ) . serveDriveServerAddr ,
"goroutines" : ( * Handler ) . serveGoroutines ,
"drive/shares" : ( * Handler ) . serveShares ,
"handle-push-message" : ( * Handler ) . serveHandlePushMessage ,
"goroutines" : ( * Handler ) . serveGoroutines ,
"id-token" : ( * Handler ) . serveIDToken ,
"handle-push-message" : ( * Handler ) . serveHandlePushMessage ,
"login-interactive" : ( * Handler ) . serveLoginInteractive ,
"id-token" : ( * Handler ) . serveIDToken ,
"logout" : ( * Handler ) . serveLogout ,
"login-interactive" : ( * Handler ) . serveLoginInteractive ,
"logtap" : ( * Handler ) . serveLogTap ,
"logout" : ( * Handler ) . serveLogout ,
"metrics" : ( * Handler ) . serveMetrics ,
"logtap" : ( * Handler ) . serveLogTap ,
"ping" : ( * Handler ) . servePing ,
"metrics" : ( * Handler ) . serveMetrics ,
"pprof" : ( * Handler ) . servePprof ,
"ping" : ( * Handler ) . servePing ,
"prefs" : ( * Handler ) . servePrefs ,
"pprof" : ( * Handler ) . servePprof ,
"query-feature" : ( * Handler ) . serveQueryFeature ,
"prefs" : ( * Handler ) . servePrefs ,
"reload-config" : ( * Handler ) . reloadConfig ,
"query-feature" : ( * Handler ) . serveQueryFeature ,
"reset-auth" : ( * Handler ) . serveResetAuth ,
"reload-config" : ( * Handler ) . reloadConfig ,
"serve-config" : ( * Handler ) . serveServeConfig ,
"reset-auth" : ( * Handler ) . serveResetAuth ,
"set-dns" : ( * Handler ) . serveSetDNS ,
"serve-config" : ( * Handler ) . serveServeConfig ,
"set-expiry-sooner" : ( * Handler ) . serveSetExpirySooner ,
"set-dns" : ( * Handler ) . serveSetDNS ,
"set-gui-visible" : ( * Handler ) . serveSetGUIVisible ,
"set-expiry-sooner" : ( * Handler ) . serveSetExpirySooner ,
"set-push-device-token" : ( * Handler ) . serveSetPushDeviceToken ,
"set-gui-visible" : ( * Handler ) . serveSetGUIVisible ,
"set-udp-gro-forwarding" : ( * Handler ) . serveSetUDPGROForwarding ,
"set-push-device-token" : ( * Handler ) . serveSetPushDeviceToken ,
"set-use-exit-node-enabled" : ( * Handler ) . serveSetUseExitNodeEnabled ,
"set-udp-gro-forwarding" : ( * Handler ) . serveSetUDPGROForwarding ,
"start" : ( * Handler ) . serveStart ,
"set-use-exit-node-enabled" : ( * Handler ) . serveSetUseExitNodeEnabled ,
"status" : ( * Handler ) . serveStatus ,
"start" : ( * Handler ) . serveStart ,
"suggest-exit-node" : ( * Handler ) . serveSuggestExitNode ,
"status" : ( * Handler ) . serveStatus ,
"tka/affected-sigs" : ( * Handler ) . serveTKAAffectedSigs ,
"suggest-exit-node" : ( * Handler ) . serveSuggestExitNode ,
"tka/cosign-recovery-aum" : ( * Handler ) . serveTKACosignRecoveryAUM ,
"tka/affected-sigs" : ( * Handler ) . serveTKAAffectedSigs ,
"tka/disable" : ( * Handler ) . serveTKADisable ,
"tka/cosign-recovery-aum" : ( * Handler ) . serveTKACosignRecoveryAUM ,
"tka/force-local-disable" : ( * Handler ) . serveTKALocalDisable ,
"tka/disable" : ( * Handler ) . serveTKADisable ,
"tka/generate-recovery-aum" : ( * Handler ) . serveTKAGenerateRecoveryAUM ,
"tka/force-local-disable" : ( * Handler ) . serveTKALocalDisable ,
"tka/init" : ( * Handler ) . serveTKAInit ,
"tka/generate-recovery-aum" : ( * Handler ) . serveTKAGenerateRecoveryAUM ,
"tka/log" : ( * Handler ) . serveTKALog ,
"tka/init" : ( * Handler ) . serveTKAInit ,
"tka/modify" : ( * Handler ) . serveTKAModify ,
"tka/log" : ( * Handler ) . serveTKALog ,
"tka/sign" : ( * Handler ) . serveTKASign ,
"tka/modify" : ( * Handler ) . serveTKAModify ,
"tka/status" : ( * Handler ) . serveTKAStatus ,
"tka/sign" : ( * Handler ) . serveTKASign ,
"tka/submit-recovery-aum" : ( * Handler ) . serveTKASubmitRecoveryAUM ,
"tka/status" : ( * Handler ) . serveTKAStatus ,
"tka/verify-deeplink" : ( * Handler ) . serveTKAVerifySigningDeeplink ,
"tka/submit-recovery-aum" : ( * Handler ) . serveTKASubmitRecoveryAUM ,
"tka/wrap-preauth-key" : ( * Handler ) . serveTKAWrapPreauthKey ,
"tka/verify-deeplink" : ( * Handler ) . serveTKAVerifySigningDeeplink ,
"update/check" : ( * Handler ) . serveUpdateCheck ,
"tka/wrap-preauth-key" : ( * Handler ) . serveTKAWrapPreauthKey ,
"update/install" : ( * Handler ) . serveUpdateInstall ,
"update/check" : ( * Handler ) . serveUpdateCheck ,
"update/progress" : ( * Handler ) . serveUpdateProgress ,
"update/install" : ( * Handler ) . serveUpdateInstall ,
"upload-client-metrics" : ( * Handler ) . serveUploadClientMetrics ,
"update/progress" : ( * Handler ) . serveUpdateProgress ,
"usermetrics" : ( * Handler ) . serveUserMetrics ,
"upload-client-metrics" : ( * Handler ) . serveUploadClientMetrics ,
"watch-ipn-bus" : ( * Handler ) . serveWatchIPNBus ,
"usermetrics" : ( * Handler ) . serveUserMetrics ,
"whois" : ( * Handler ) . serveWhoIs ,
"watch-ipn-bus" : ( * Handler ) . serveWatchIPNBus ,
"whois" : ( * Handler ) . serveWhoIs ,
}
}
// Register registers a new LocalAPI handler for the given name.
// Register registers a new LocalAPI handler for the given name.
@ -1175,6 +1177,32 @@ func (h *Handler) serveCheckIPForwarding(w http.ResponseWriter, r *http.Request)
} )
} )
}
}
func ( h * Handler ) serveCheckReversePathFiltering ( w http . ResponseWriter , r * http . Request ) {
if ! h . PermitRead {
http . Error ( w , "reverse path filtering check access denied" , http . StatusForbidden )
return
}
var warning string
state := h . b . Sys ( ) . NetMon . Get ( ) . InterfaceState ( )
warn , err := netutil . CheckReversePathFiltering ( state )
if err == nil && len ( warn ) > 0 {
var msg strings . Builder
msg . WriteString ( healthmsg . WarnExitNodeUsage + ":\n" )
for _ , w := range warn {
msg . WriteString ( "- " + w + "\n" )
}
msg . WriteString ( healthmsg . DisableRPFilter )
warning = msg . String ( )
}
w . Header ( ) . Set ( "Content-Type" , "application/json" )
json . NewEncoder ( w ) . Encode ( struct {
Warning string
} {
Warning : warning ,
} )
}
func ( h * Handler ) serveCheckUDPGROForwarding ( w http . ResponseWriter , r * http . Request ) {
func ( h * Handler ) serveCheckUDPGROForwarding ( w http . ResponseWriter , r * http . Request ) {
if ! h . PermitRead {
if ! h . PermitRead {
http . Error ( w , "UDP GRO forwarding check access denied" , http . StatusForbidden )
http . Error ( w , "UDP GRO forwarding check access denied" , http . StatusForbidden )