diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 7433e0821..e352beba1 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -678,6 +678,7 @@ func peerAPIRequestShouldGetSecurityHeaders(r *http.Request) bool { func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if err := h.validatePeerAPIRequest(r); err != nil { + metricInvalidRequests.Add(1) h.logf("invalid request from %v: %v", h.remoteAddr, err) http.Error(w, "invalid peerapi request", http.StatusForbidden) return @@ -688,10 +689,12 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Content-Type-Options", "nosniff") } if strings.HasPrefix(r.URL.Path, "/v0/put/") { + metricPutCalls.Add(1) h.handlePeerPut(w, r) return } if strings.HasPrefix(r.URL.Path, "/dns-query") { + metricDNSCalls.Add(1) h.handleDNSQuery(w, r) return } @@ -712,12 +715,14 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { h.handleServeDNSFwd(w, r) return case "/v0/wol": + metricWakeOnLANCalls.Add(1) h.handleWakeOnLAN(w, r) return case "/v0/interfaces": h.handleServeInterfaces(w, r) return case "/v0/ingress": + metricIngressCalls.Add(1) h.handleServeIngress(w, r) return } @@ -1441,3 +1446,13 @@ func (fl *fakePeerAPIListener) Accept() (net.Conn, error) { } 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") +) diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index e2d281be5..32fe7f29f 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -146,6 +146,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } if r.Referer() != "" || r.Header.Get("Origin") != "" || !validHost(r.Host) { + metricInvalidRequests.Add(1) http.Error(w, "invalid localapi request", http.StatusForbidden) return } @@ -156,10 +157,12 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if h.RequiredPassword != "" { _, pass, ok := r.BasicAuth() if !ok { + metricInvalidRequests.Add(1) http.Error(w, "auth required", http.StatusUnauthorized) return } if pass != h.RequiredPassword { + metricInvalidRequests.Add(1) http.Error(w, "bad password", http.StatusForbidden) return } @@ -895,6 +898,8 @@ func (h *Handler) serveFileTargets(w http.ResponseWriter, r *http.Request) { // // - PUT /localapi/v0/file-put/:stableID/:escaped-filename func (h *Handler) serveFilePut(w http.ResponseWriter, r *http.Request) { + metricFilePutCalls.Add(1) + if !h.PermitWrite { http.Error(w, "file access denied", http.StatusForbidden) return @@ -1425,3 +1430,10 @@ func defBool(a string, def bool) bool { } return v } + +var ( + metricInvalidRequests = clientmetric.NewCounter("localapi_invalid_requests") + + // User-visible LocalAPI endpoints. + metricFilePutCalls = clientmetric.NewCounter("localapi_file_put") +)