ProxyAwareRemote return the most likely remote address
(r *http.Request)
| 67 | |
| 68 | // ProxyAwareRemote return the most likely remote address |
| 69 | func ProxyAwareRemote(r *http.Request) string { |
| 70 | // if we get the content via a proxy, try to extract the |
| 71 | // ip from the usual headers |
| 72 | for _, h := range []string{"X-Forwarded-For", "X-Real-Ip"} { |
| 73 | addresses := strings.Split(r.Header.Get(h), ",") |
| 74 | for i := len(addresses) - 1; i >= 0; i-- { |
| 75 | ip := strings.TrimSpace(addresses[i]) |
| 76 | realIP := net.ParseIP(ip) |
| 77 | if !realIP.IsGlobalUnicast() || isPrivate(realIP) { |
| 78 | continue // bad address, go to next |
| 79 | } |
| 80 | return ip |
| 81 | } |
| 82 | } |
| 83 | // if no proxy header is present return the |
| 84 | // regular remote address |
| 85 | host, _, err := net.SplitHostPort(r.RemoteAddr) |
| 86 | if err != nil { |
| 87 | log.Ctx(r.Context()).Warn().Err(err).Msg("failed to decode the remote address") |
| 88 | return "" |
| 89 | } |
| 90 | return host |
| 91 | } |
| 92 | |
| 93 | // isPrivate reports whether `ip' is a local address, according to |
| 94 | // RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses). |