Files
telemt-api/internal/server/clientip.go
T
Denozordec 91f289c647
ci / test (push) Successful in 1m15s
ci / docker (push) Successful in 1m8s
Init
2026-03-29 22:51:02 +07:00

66 lines
1.3 KiB
Go

package server
import (
"net"
"net/http"
"net/netip"
"strings"
)
// ClientIP returns the client address for access control, using X-Forwarded-For /
// X-Real-IP only when the direct peer is in trusted CIDRs.
func ClientIP(r *http.Request, trusted []netip.Prefix) netip.Addr {
host, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
host = r.RemoteAddr
}
peer, err := netip.ParseAddr(host)
if err != nil {
return netip.Addr{}
}
if !containsIP(trusted, peer) {
return peer
}
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
parts := strings.Split(xff, ",")
for _, p := range parts {
p = strings.TrimSpace(p)
if p == "" {
continue
}
if a, err := netip.ParseAddr(p); err == nil {
return a
}
}
}
if xr := strings.TrimSpace(r.Header.Get("X-Real-IP")); xr != "" {
if a, err := netip.ParseAddr(xr); err == nil {
return a
}
}
return peer
}
func containsIP(prefixes []netip.Prefix, addr netip.Addr) bool {
for _, p := range prefixes {
if p.Contains(addr) {
return true
}
}
return false
}
// Allowed reports whether addr matches whitelist rules.
func Allowed(addr netip.Addr, allowAll bool, whitelist []netip.Prefix) bool {
if !addr.IsValid() {
return false
}
if allowAll {
return true
}
if len(whitelist) == 0 {
return false
}
return containsIP(whitelist, addr)
}