Instrument mc-proxy with prometheus/client_golang. New internal/metrics/ package defines counters, gauges, and histograms for connection totals, active connections, firewall blocks by reason, backend dial latency, bytes transferred, L7 HTTP status codes, and L7 policy blocks. Optional [metrics] config section starts a scrape endpoint. Firewall gains BlockedWithReason() to report block cause. L7 handler wraps ResponseWriter to record status codes per hostname. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
43 lines
1.1 KiB
Go
43 lines
1.1 KiB
Go
package l7
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"git.wntrmute.dev/kyle/mc-proxy/internal/metrics"
|
|
)
|
|
|
|
// PolicyRule defines an L7 blocking policy.
|
|
type PolicyRule struct {
|
|
Type string // "block_user_agent" or "require_header"
|
|
Value string
|
|
}
|
|
|
|
// PolicyMiddleware returns an http.Handler that evaluates L7 policies
|
|
// before delegating to next. Returns HTTP 403 if any policy blocks.
|
|
// If policies is empty, returns next unchanged.
|
|
func PolicyMiddleware(policies []PolicyRule, hostname string, next http.Handler) http.Handler {
|
|
if len(policies) == 0 {
|
|
return next
|
|
}
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
for _, p := range policies {
|
|
switch p.Type {
|
|
case "block_user_agent":
|
|
if strings.Contains(r.UserAgent(), p.Value) {
|
|
metrics.L7PolicyBlocksTotal.WithLabelValues(hostname, "block_user_agent").Inc()
|
|
w.WriteHeader(http.StatusForbidden)
|
|
return
|
|
}
|
|
case "require_header":
|
|
if r.Header.Get(p.Value) == "" {
|
|
metrics.L7PolicyBlocksTotal.WithLabelValues(hostname, "require_header").Inc()
|
|
w.WriteHeader(http.StatusForbidden)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|