hk-service/pkg/middleware/getRealIP.go
2025-02-20 17:32:53 +08:00

83 lines
1.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package middleware
import (
"errors"
"net"
"net/http"
"strings"
)
// GetRealIP 提取客户端真实 IP 地址
func GetRealIP(r *http.Request) string {
headers := []string{"x-forwarded-for", "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "X-Real-IP"}
// 遍历头信息,找到第一个有效 IP
for _, header := range headers {
ip := extractIP(r.Header.Get(header))
if ip != "" {
return ip
}
}
// 获取 RemoteAddr如果经过代理则是代理 IP
ip, _, err := net.SplitHostPort(r.RemoteAddr)
if err == nil && ip != "" {
return ip
}
// 检查是否是本地地址
if strings.HasPrefix(ip, "127.0.0.1") || strings.HasPrefix(ip, "[::1]") {
if externalIP, err := getExternalIP(); err == nil {
return externalIP.String()
}
}
return ""
}
// 提取 IP 地址并返回第一个非空部分
func extractIP(ips string) string {
if ips == "" || strings.EqualFold(ips, "unknown") {
return ""
}
// 返回第一个有效 IP
return strings.TrimSpace(strings.Split(ips, ",")[0])
}
// 获取非 127.0.0.1 的局域网 IP
func getExternalIP() (net.IP, error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
for _, iface := range ifaces {
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
continue
}
addrs, err := iface.Addrs()
if err != nil {
return nil, err
}
for _, addr := range addrs {
ip := getIPFromAddr(addr)
if ip != nil {
return ip, nil
}
}
}
return nil, errors.New("not connected to the network")
}
func getIPFromAddr(addr net.Addr) net.IP {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}
if ip != nil && !ip.IsLoopback() {
return ip.To4()
}
return nil
}