From eadb2ffe85c43cf6fc741c9823cd28eedb4a844c Mon Sep 17 00:00:00 2001 From: Chia Date: Wed, 5 Aug 2026 22:01:29 +1200 Subject: feat: harden prepaid billing and commercial operations --- internal/httpapi/proxy.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 internal/httpapi/proxy.go (limited to 'internal/httpapi/proxy.go') diff --git a/internal/httpapi/proxy.go b/internal/httpapi/proxy.go new file mode 100644 index 0000000..3cd2797 --- /dev/null +++ b/internal/httpapi/proxy.go @@ -0,0 +1,44 @@ +package httpapi + +import ( + "net" + "net/http" + "strings" +) + +// TrustProxyHeaders accepts forwarding metadata only from explicitly trusted +// CIDRs. This prevents a direct client from forging HTTPS or audit IP state. +func TrustProxyHeaders(next http.Handler, trustedCIDRs []string, requireHTTPS bool) (http.Handler, error) { + trusted := make([]*net.IPNet, 0, len(trustedCIDRs)) + for _, value := range trustedCIDRs { + _, network, err := net.ParseCIDR(value) + if err != nil { + return nil, err + } + trusted = append(trusted, network) + } + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + host, _, _ := net.SplitHostPort(r.RemoteAddr) + remote := net.ParseIP(host) + trustedPeer := false + for _, network := range trusted { + if remote != nil && network.Contains(remote) { + trustedPeer = true + break + } + } + if !trustedPeer { + for _, header := range []string{"Forwarded", "X-Forwarded-For", "X-Forwarded-Host", "X-Forwarded-Port", "X-Forwarded-Proto", "X-Real-IP"} { + r.Header.Del(header) + } + } else if forwarded := strings.TrimSpace(strings.Split(r.Header.Get("X-Forwarded-For"), ",")[0]); net.ParseIP(forwarded) != nil { + r.RemoteAddr = net.JoinHostPort(forwarded, "0") + } + secure := r.TLS != nil || (trustedPeer && strings.EqualFold(strings.TrimSpace(r.Header.Get("X-Forwarded-Proto")), "https")) + if requireHTTPS && !secure { + http.Error(w, "HTTPS is required", http.StatusUpgradeRequired) + return + } + next.ServeHTTP(w, r) + }), nil +} -- cgit v1.2.3