ipn/ipnlocal: add a few metrics for PeerAPI and LocalAPI

Mainly motivated by wanting to know how much Taildrop is used, but
also useful when tracking down how many invalid requests are
generated.

Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This commit is contained in:
Mihai Parparita 2022-12-09 14:21:53 -08:00 committed by Mihai Parparita
parent 53e2010b8a
commit 47002d93a3
2 changed files with 27 additions and 0 deletions

View File

@ -678,6 +678,7 @@ func peerAPIRequestShouldGetSecurityHeaders(r *http.Request) bool {
func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := h.validatePeerAPIRequest(r); err != nil { if err := h.validatePeerAPIRequest(r); err != nil {
metricInvalidRequests.Add(1)
h.logf("invalid request from %v: %v", h.remoteAddr, err) h.logf("invalid request from %v: %v", h.remoteAddr, err)
http.Error(w, "invalid peerapi request", http.StatusForbidden) http.Error(w, "invalid peerapi request", http.StatusForbidden)
return return
@ -688,10 +689,12 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("X-Content-Type-Options", "nosniff")
} }
if strings.HasPrefix(r.URL.Path, "/v0/put/") { if strings.HasPrefix(r.URL.Path, "/v0/put/") {
metricPutCalls.Add(1)
h.handlePeerPut(w, r) h.handlePeerPut(w, r)
return return
} }
if strings.HasPrefix(r.URL.Path, "/dns-query") { if strings.HasPrefix(r.URL.Path, "/dns-query") {
metricDNSCalls.Add(1)
h.handleDNSQuery(w, r) h.handleDNSQuery(w, r)
return return
} }
@ -712,12 +715,14 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.handleServeDNSFwd(w, r) h.handleServeDNSFwd(w, r)
return return
case "/v0/wol": case "/v0/wol":
metricWakeOnLANCalls.Add(1)
h.handleWakeOnLAN(w, r) h.handleWakeOnLAN(w, r)
return return
case "/v0/interfaces": case "/v0/interfaces":
h.handleServeInterfaces(w, r) h.handleServeInterfaces(w, r)
return return
case "/v0/ingress": case "/v0/ingress":
metricIngressCalls.Add(1)
h.handleServeIngress(w, r) h.handleServeIngress(w, r)
return return
} }
@ -1441,3 +1446,13 @@ func (fl *fakePeerAPIListener) Accept() (net.Conn, error) {
} }
func (fl *fakePeerAPIListener) Addr() net.Addr { return fl.addr } func (fl *fakePeerAPIListener) Addr() net.Addr { return fl.addr }
var (
metricInvalidRequests = clientmetric.NewCounter("peerapi_invalid_requests")
// Non-debug PeerAPI endpoints.
metricPutCalls = clientmetric.NewCounter("peerapi_put")
metricDNSCalls = clientmetric.NewCounter("peerapi_dns")
metricWakeOnLANCalls = clientmetric.NewCounter("peerapi_wol")
metricIngressCalls = clientmetric.NewCounter("peerapi_ingress")
)

View File

@ -146,6 +146,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return return
} }
if r.Referer() != "" || r.Header.Get("Origin") != "" || !validHost(r.Host) { if r.Referer() != "" || r.Header.Get("Origin") != "" || !validHost(r.Host) {
metricInvalidRequests.Add(1)
http.Error(w, "invalid localapi request", http.StatusForbidden) http.Error(w, "invalid localapi request", http.StatusForbidden)
return return
} }
@ -156,10 +157,12 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if h.RequiredPassword != "" { if h.RequiredPassword != "" {
_, pass, ok := r.BasicAuth() _, pass, ok := r.BasicAuth()
if !ok { if !ok {
metricInvalidRequests.Add(1)
http.Error(w, "auth required", http.StatusUnauthorized) http.Error(w, "auth required", http.StatusUnauthorized)
return return
} }
if pass != h.RequiredPassword { if pass != h.RequiredPassword {
metricInvalidRequests.Add(1)
http.Error(w, "bad password", http.StatusForbidden) http.Error(w, "bad password", http.StatusForbidden)
return return
} }
@ -895,6 +898,8 @@ func (h *Handler) serveFileTargets(w http.ResponseWriter, r *http.Request) {
// //
// - PUT /localapi/v0/file-put/:stableID/:escaped-filename // - PUT /localapi/v0/file-put/:stableID/:escaped-filename
func (h *Handler) serveFilePut(w http.ResponseWriter, r *http.Request) { func (h *Handler) serveFilePut(w http.ResponseWriter, r *http.Request) {
metricFilePutCalls.Add(1)
if !h.PermitWrite { if !h.PermitWrite {
http.Error(w, "file access denied", http.StatusForbidden) http.Error(w, "file access denied", http.StatusForbidden)
return return
@ -1425,3 +1430,10 @@ func defBool(a string, def bool) bool {
} }
return v return v
} }
var (
metricInvalidRequests = clientmetric.NewCounter("localapi_invalid_requests")
// User-visible LocalAPI endpoints.
metricFilePutCalls = clientmetric.NewCounter("localapi_file_put")
)