main
go 119 lines 2.5 KB
Raw
1 package policy
2
3 import (
4 "net"
5 "net/http"
6 "strings"
7 )
8
9 var defaultTrustedProxyCIDRs = mustParseTrustedProxyCIDRs(
10 "127.0.0.0/8",
11 "10.0.0.0/8",
12 "172.16.0.0/12",
13 "192.168.0.0/16",
14 "169.254.0.0/16",
15 "100.64.0.0/10",
16 "::1/128",
17 "fc00::/7",
18 "fe80::/10",
19 )
20
21 func isTrustedProxyRemoteAddr(remoteAddr string, trustedProxyCIDRs []*net.IPNet) bool {
22 remoteIP := parseRemoteAddrIP(remoteAddr)
23 if remoteIP == nil {
24 return false
25 }
26
27 networks := trustedProxyCIDRs
28 if len(networks) == 0 {
29 networks = defaultTrustedProxyCIDRs
30 }
31 for _, network := range networks {
32 if network != nil && network.Contains(remoteIP) {
33 return true
34 }
35 }
36 return false
37 }
38
39 func (r *Runtime) ExtractClientIP(req *http.Request) string {
40 if r == nil {
41 return ""
42 }
43 if req == nil {
44 return ""
45 }
46
47 cfg := runtimeConfig{}
48 if r.config != nil {
49 cfg = r.config.Load()
50 }
51 if cfg.trustProxyHeaders && isTrustedProxyRemoteAddr(req.RemoteAddr, cfg.trustedProxyCIDRs) {
52 if xff := req.Header.Get("X-Forwarded-For"); xff != "" {
53 if before, _, ok := strings.Cut(xff, ","); ok {
54 if ip := normalizeClientIPCandidate(before); ip != "" {
55 return ip
56 }
57 } else if ip := normalizeClientIPCandidate(xff); ip != "" {
58 return ip
59 }
60 }
61 if xri := req.Header.Get("X-Real-IP"); xri != "" {
62 if ip := normalizeClientIPCandidate(xri); ip != "" {
63 return ip
64 }
65 }
66 }
67
68 host, _, err := net.SplitHostPort(req.RemoteAddr)
69 if err != nil {
70 return strings.TrimSpace(req.RemoteAddr)
71 }
72 if normalized := normalizeClientIPCandidate(host); normalized != "" {
73 return normalized
74 }
75 return strings.TrimSpace(host)
76 }
77
78 func parseRemoteAddrIP(remoteAddr string) net.IP {
79 remoteAddr = strings.TrimSpace(remoteAddr)
80 if remoteAddr == "" {
81 return nil
82 }
83 host := remoteAddr
84 if parsedHost, _, err := net.SplitHostPort(remoteAddr); err == nil {
85 host = parsedHost
86 }
87 return net.ParseIP(strings.TrimSpace(host))
88 }
89
90 func mustParseTrustedProxyCIDRs(values ...string) []*net.IPNet {
91 cidrs := make([]*net.IPNet, 0, len(values))
92 for _, value := range values {
93 _, network, err := net.ParseCIDR(value)
94 if err != nil {
95 panic(err)
96 }
97 cidrs = append(cidrs, network)
98 }
99 return cidrs
100 }
101
102 func normalizeClientIPCandidate(raw string) string {
103 candidate := strings.TrimSpace(raw)
104 if candidate == "" {
105 return ""
106 }
107 if ip := net.ParseIP(candidate); ip != nil {
108 return candidate
109 }
110 host, _, err := net.SplitHostPort(candidate)
111 if err != nil {
112 return ""
113 }
114 host = strings.TrimSpace(host)
115 if host == "" || net.ParseIP(host) == nil {
116 return ""
117 }
118 return host
119 }