通过消息传递头部信息获取IP
获取公网IP
// HasLocalIPAddr 检测 IP 地址字符串是否是内网地址
func HasLocalIPAddr(ip string) bool {
return HasLocalIP(net.ParseIP(ip))
}
// HasLocalIP 检测 IP 地址是否是内网地址
// 通过直接对比ip段范围效率更高
func HasLocalIP(ip net.IP) bool {
if ip.IsLoopback() {
return true
}
ip4 := ip.To4()
if ip4 == nil {
return false
}
return ip4[0] == 10 || // 10.0.0.0/8
(ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) || // 172.16.0.0/12
(ip4[0] == 169 && ip4[1] == 254) || // 169.254.0.0/16
(ip4[0] == 192 && ip4[1] == 168) // 192.168.0.0/16
}
// ClientPublicIP 尽最大努力实现获取客户端公网 IP 的算法。
// 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。
func ClientPublicIP(r *http.Request) string {
var ip string
for _, ip = range strings.Split(r.Header.Get("X-Forwarded-For"), ",") {
if ip = strings.TrimSpace(ip); ip != "" && !HasLocalIPAddr(ip) {
return ip
}
}
if ip = strings.TrimSpace(r.Header.Get("X-Real-Ip")); ip != "" && !HasLocalIPAddr(ip) {
return ip
}
if ip = RemoteIP(r); !HasLocalIPAddr(ip) {
return ip
}
return ""
}
// RemoteIP 通过 RemoteAddr 获取 IP 地址, 只是一个快速解析方法。
func RemoteIP(r *http.Request) string {
ip, _, _ := net.SplitHostPort(r.RemoteAddr)
return ip
}