ExtractIPFromXFFHeader extracts IP address using `x-forwarded-for` header. Use this if you put proxy which uses this header. This returns nearest untrustable IP. If all IPs are trustable, returns furthest one (i.e.: XFF[0]).
(options ...TrustOption)
| 240 | // Use this if you put proxy which uses this header. |
| 241 | // This returns nearest untrustable IP. If all IPs are trustable, returns furthest one (i.e.: XFF[0]). |
| 242 | func ExtractIPFromXFFHeader(options ...TrustOption) IPExtractor { |
| 243 | checker := newIPChecker(options) |
| 244 | return func(req *http.Request) string { |
| 245 | directIP := extractIP(req) |
| 246 | xffs := req.Header[HeaderXForwardedFor] |
| 247 | if len(xffs) == 0 { |
| 248 | return directIP |
| 249 | } |
| 250 | ips := append(strings.Split(strings.Join(xffs, ","), ","), directIP) |
| 251 | for i := len(ips) - 1; i >= 0; i-- { |
| 252 | ips[i] = strings.TrimSpace(ips[i]) |
| 253 | ips[i] = strings.TrimPrefix(ips[i], "[") |
| 254 | ips[i] = strings.TrimSuffix(ips[i], "]") |
| 255 | ip := net.ParseIP(ips[i]) |
| 256 | if ip == nil { |
| 257 | // Unable to parse IP; cannot trust entire records |
| 258 | return directIP |
| 259 | } |
| 260 | if !checker.trust(ip) { |
| 261 | return ip.String() |
| 262 | } |
| 263 | } |
| 264 | // All of the IPs are trusted; return first element because it is furthest from server (best effort strategy). |
| 265 | return strings.TrimSpace(ips[0]) |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | // LegacyIPExtractor returns an IPExtractor that derives the client IP address |
| 270 | // from common proxy headers, falling back to the request's remote address. |
searching dependent graphs…