mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-12 05:37:32 +00:00
cmd/tailscale/cli, ipn/localapi: add funnel status to status command (#6402)
Fixes #6400 open up GETs for localapi serve-config to allow read-only access to ServeConfig `tailscale status` will include "Funnel on" status when Funnel is configured. Prints nothing if Funnel is not running. Example: $ tailscale status <nodes redacted> # Funnel on: # - https://node-name.corp.ts.net # - https://node-name.corp.ts.net:8443 # - tcp://node-name.corp.ts.net:10000 Signed-off-by: Shayne Sweeney <shayne@tailscale.com>
This commit is contained in:
@@ -540,37 +540,32 @@ func (h *Handler) servePprof(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (h *Handler) serveServeConfig(w http.ResponseWriter, r *http.Request) {
|
||||
if !h.PermitWrite {
|
||||
http.Error(w, "serve config denied", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
if !h.PermitRead {
|
||||
http.Error(w, "serve config denied", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
config := h.b.ServeConfig()
|
||||
json.NewEncoder(w).Encode(config)
|
||||
case "POST":
|
||||
configIn := new(ipn.ServeConfig)
|
||||
if err := json.NewDecoder(r.Body).Decode(configIn); err != nil {
|
||||
json.NewEncoder(w).Encode(struct {
|
||||
Error error
|
||||
}{
|
||||
Error: fmt.Errorf("decoding config: %w", err),
|
||||
})
|
||||
if !h.PermitWrite {
|
||||
http.Error(w, "serve config denied", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
err := h.b.SetServeConfig(configIn)
|
||||
if err != nil {
|
||||
json.NewEncoder(w).Encode(struct {
|
||||
Error error
|
||||
}{
|
||||
Error: fmt.Errorf("updating config: %w", err),
|
||||
})
|
||||
configIn := new(ipn.ServeConfig)
|
||||
if err := json.NewDecoder(r.Body).Decode(configIn); err != nil {
|
||||
writeErrorJSON(w, fmt.Errorf("decoding config: %w", err))
|
||||
return
|
||||
}
|
||||
if err := h.b.SetServeConfig(configIn); err != nil {
|
||||
writeErrorJSON(w, fmt.Errorf("updating config: %w", err))
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
default:
|
||||
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
|
29
ipn/serve.go
29
ipn/serve.go
@@ -81,15 +81,18 @@ func (sc *ServeConfig) WebHandlerExists(hp HostPort, mount string) bool {
|
||||
// GetWebHandler returns the HTTPHandler for the given host:port and mount point.
|
||||
// Returns nil if the handler does not exist.
|
||||
func (sc *ServeConfig) GetWebHandler(hp HostPort, mount string) *HTTPHandler {
|
||||
if sc.Web[hp] != nil {
|
||||
return sc.Web[hp].Handlers[mount]
|
||||
if sc == nil || sc.Web[hp] == nil {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
return sc.Web[hp].Handlers[mount]
|
||||
}
|
||||
|
||||
// GetTCPPortHandler returns the TCPPortHandler for the given port.
|
||||
// If the port is not configured, nil is returned.
|
||||
func (sc *ServeConfig) GetTCPPortHandler(port uint16) *TCPPortHandler {
|
||||
if sc == nil {
|
||||
return nil
|
||||
}
|
||||
return sc.TCP[port]
|
||||
}
|
||||
|
||||
@@ -97,7 +100,7 @@ func (sc *ServeConfig) GetTCPPortHandler(port uint16) *TCPPortHandler {
|
||||
// in TCPForward mode on any port.
|
||||
// This is exclusive of Web/HTTPS serving.
|
||||
func (sc *ServeConfig) IsTCPForwardingAny() bool {
|
||||
if len(sc.TCP) == 0 {
|
||||
if sc == nil || len(sc.TCP) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, h := range sc.TCP {
|
||||
@@ -112,7 +115,7 @@ func (sc *ServeConfig) IsTCPForwardingAny() bool {
|
||||
// in TCPForward mode on the given port.
|
||||
// This is exclusive of Web/HTTPS serving.
|
||||
func (sc *ServeConfig) IsTCPForwardingOnPort(port uint16) bool {
|
||||
if sc.TCP[port] == nil {
|
||||
if sc == nil || sc.TCP[port] == nil {
|
||||
return false
|
||||
}
|
||||
return !sc.TCP[port].HTTPS
|
||||
@@ -122,14 +125,22 @@ func (sc *ServeConfig) IsTCPForwardingOnPort(port uint16) bool {
|
||||
// Web/HTTPS on the given port.
|
||||
// This is exclusive of TCPForwarding.
|
||||
func (sc *ServeConfig) IsServingWeb(port uint16) bool {
|
||||
if sc.TCP[port] == nil {
|
||||
if sc == nil || sc.TCP[port] == nil {
|
||||
return false
|
||||
}
|
||||
return sc.TCP[port].HTTPS
|
||||
}
|
||||
|
||||
// IsFunnelOn checks if ServeConfig is currently allowing
|
||||
// funnel traffic on for the given host:port.
|
||||
func (sc *ServeConfig) IsFunnelOn(hp HostPort) bool {
|
||||
return sc.AllowFunnel[hp]
|
||||
// funnel traffic for any host:port.
|
||||
func (sc *ServeConfig) IsFunnelOn() bool {
|
||||
if sc == nil {
|
||||
return false
|
||||
}
|
||||
for _, b := range sc.AllowFunnel {
|
||||
if b {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
Reference in New Issue
Block a user