From 443cc77dbe758209d5871c04fd52fbe357a3adb2 Mon Sep 17 00:00:00 2001 From: Yun Date: Sun, 3 May 2026 23:41:50 +0800 Subject: [PATCH] commit --- get_ip.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 3 +++ ipx.go | 48 ++++++++++++++++++++++++++++++++++++++++++ ipx_test.go | 17 +++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 get_ip.go create mode 100644 go.mod create mode 100644 ipx.go create mode 100644 ipx_test.go diff --git a/get_ip.go b/get_ip.go new file mode 100644 index 0000000..5261c0e --- /dev/null +++ b/get_ip.go @@ -0,0 +1,60 @@ +package tools + +import ( + "net" + "net/http" + "strings" +) + +// ClientIP 首先读取 X-Forwarded-For header 中用 , 分隔的第一个ip地址, +// 如果这个地址不存在,就会从 X-Real-Ip header 中获取,如果还是不存在, +// 说明流量并非是由反向代理转发而来,而是客户端直接请求服务,这时通过 http.Request.RemoteAddr 字段 +// 截取除去端口号的 ip 地址。 +func ClientPublicIp(r *http.Request) string { + var ip string + for _, ip = range strings.Split(r.Header.Get("X-Forwarded-For"), ",") { + ip = strings.TrimSpace(ip) + if ip != "" && !HasLocalIPaddr(ip) { + return ip + } + } + + ip = strings.TrimSpace(r.Header.Get("X-Real-Ip")) + if ip != "" && !HasLocalIPaddr(ip) { + return ip + } + + if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil { + if !HasLocalIPaddr(ip) { + return ip + } + } + return "" +} + +// 判断是地址是否来自代理 +func RemoteIp(r *http.Request) string { + if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil { + return ip + } + return "" +} + +// 检测IP地址字符串是否内网地址 +func HasLocalIPaddr(ip string) bool { + return HasLocalIP(net.ParseIP(ip)) +} + +// 检测IP地址是否内网地址 +// tcp/ip协议中,专门保留了三个IP地址区域作为私有地址,其地址范围如下: +// 10.0.0.0/8:10.0.0.0~10.255.255.255 +// 172.16.0.0/12:172.16.0.0~172.31.255.255 +// 192.168.0.0/16:192.168.0.0~192.168.255.255 +func HasLocalIP(ip net.IP) bool { + // for _, network := range localNetworks { + // if network.Contains(ip) { + // return true + // } + // } + return ip.IsLoopback() +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c980563 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module code.yun.ink/pkg/ipx + +go 1.20 diff --git a/ipx.go b/ipx.go new file mode 100644 index 0000000..0371ca7 --- /dev/null +++ b/ipx.go @@ -0,0 +1,48 @@ +package ipx + +import ( + "fmt" + "net" + "strings" +) + +// TODO:不符合预期 + +// 获取本机的公网IP +func GetPublicIP() string { + + conn, err := net.Dial("udp", "114.114.114.114:53") + if err != nil { + fmt.Println(err) + return "" + } + + defer conn.Close() + + remoteAddr := conn.RemoteAddr().(*net.UDPAddr) + fmt.Println("remote:", remoteAddr.String()) + localAddr := conn.LocalAddr().(*net.UDPAddr) + fmt.Println("local:", localAddr.String()) + ip := strings.Split(localAddr.String(), ":")[0] + return ip +} + +// 获取本机的内网IP +func GetLocalIP() string { + addrs, err := net.InterfaceAddrs() + if err != nil { + fmt.Println(err) + return "" + } + fmt.Println(addrs) + for _, address := range addrs { + // 检查ip地址判断是否回环地址 + if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + ip := ipnet.IP.String() + return ip + } + } + } + return "" +} diff --git a/ipx_test.go b/ipx_test.go new file mode 100644 index 0000000..b145b47 --- /dev/null +++ b/ipx_test.go @@ -0,0 +1,17 @@ +package ipx_test + +import ( + "testing" + + "code.yun.ink/pkg/ipx" +) + +func TestPublicIP(t *testing.T) { + ip := ipx.GetPublicIP() + t.Log(ip) +} + +func TestLocalIP(t *testing.T) { + ip := ipx.GetLocalIP() + t.Log(ip) +}