Files
ntfywui/internal/security/realip.go
2026-01-12 13:51:52 +01:00

54 lines
1.1 KiB
Go

package security
import (
"net"
"net/http"
"strings"
)
type RealIPConfig struct {
TrustedProxies []*net.IPNet
}
func (c RealIPConfig) IsTrusted(remoteAddr string) bool {
host, _, err := net.SplitHostPort(remoteAddr)
if err != nil {
host = remoteAddr
}
ip := net.ParseIP(host)
if ip == nil {
return false
}
for _, n := range c.TrustedProxies {
if n.Contains(ip) {
return true
}
}
return false
}
// RealIP returns the best-effort client IP.
// It only honors X-Forwarded-For when the direct peer is in TrustedProxies.
func RealIP(r *http.Request, cfg RealIPConfig) string {
if cfg.IsTrusted(r.RemoteAddr) {
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
// First IP is original client
parts := strings.Split(xff, ",")
if len(parts) > 0 {
ip := strings.TrimSpace(parts[0])
if net.ParseIP(ip) != nil {
return ip
}
}
}
if xrip := strings.TrimSpace(r.Header.Get("X-Real-IP")); xrip != "" && net.ParseIP(xrip) != nil {
return xrip
}
}
host, _, err := net.SplitHostPort(r.RemoteAddr)
if err == nil && net.ParseIP(host) != nil {
return host
}
return r.RemoteAddr
}