-
Notifications
You must be signed in to change notification settings - Fork 0
/
ip.go
178 lines (150 loc) · 3.95 KB
/
ip.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
* @Author: DollarKiller
* @Description: 尽最大可能获取用户ip
* @Github: https://github.com/dollarkillerx
* @Date: Create in 17:01 2019-09-18
*/
package nettool
import (
"errors"
"math"
"net"
"net/http"
"strings"
)
// 收集的内网网络地址 IP 段
var localNetworks []*net.IPNet
func init() {
localNetworks = make([]*net.IPNet, 19)
for i, sNetwork := range []string{
"10.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"172.17.0.0/12",
"172.18.0.0/12",
"172.19.0.0/12",
"172.20.0.0/12",
"172.21.0.0/12",
"172.22.0.0/12",
"172.23.0.0/12",
"172.24.0.0/12",
"172.25.0.0/12",
"172.26.0.0/12",
"172.27.0.0/12",
"172.28.0.0/12",
"172.29.0.0/12",
"172.30.0.0/12",
"172.31.0.0/12",
"192.168.0.0/16",
} {
_, network, _ := net.ParseCIDR(sNetwork)
localNetworks[i] = network
}
}
type AnalysisIp struct {
}
func (a *AnalysisIp) AnalysisIp(r *http.Request) string {
ip := a.ClientPublicIP(r)
if ip == "" {
ip = a.ClientIP(r)
}
return ip
}
// ClientIP 尽最大努力实现获取客户端 IP 的算法。
// 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。
func (a *AnalysisIp) ClientIP(r *http.Request) string {
xForwardedFor := r.Header.Get("X-Forwarded-For")
ip := strings.TrimSpace(strings.Split(xForwardedFor, ",")[0])
if ip != "" {
return ip
}
ip = strings.TrimSpace(r.Header.Get("X-Real-Ip"))
if ip != "" {
return ip
}
if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {
return ip
}
return ""
}
// ClientPublicIP 尽最大努力实现获取客户端公网 IP 的算法。
// 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。
func (a *AnalysisIp) 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 != "" && !a.HasLocalIPddr(ip) {
return ip
}
}
ip = strings.TrimSpace(r.Header.Get("X-Real-Ip"))
if ip != "" && !a.HasLocalIPddr(ip) {
return ip
}
if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {
if !a.HasLocalIPddr(ip) {
return ip
}
}
return ""
}
// HasLocalIPddr 检测 IP 地址字符串是否是内网地址
func (a *AnalysisIp) HasLocalIPddr(ip string) bool {
return a.HasLocalIP(net.ParseIP(ip))
}
// HasLocalIP 检测 IP 地址是否是内网地址
func (a *AnalysisIp) HasLocalIP(ip net.IP) bool {
for _, network := range localNetworks {
if network.Contains(ip) {
return true
}
}
return ip.IsLoopback()
}
// RemoteIP 通过 RemoteAddr 获取 IP 地址, 只是一个快速解析方法。
func (a *AnalysisIp) RemoteIP(r *http.Request) string {
if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {
return ip
}
return ""
}
// IPString2Long 把ip字符串转为数值
func (a *AnalysisIp) IPString2Long(ip string) (uint, error) {
b := net.ParseIP(ip).To4()
if b == nil {
return 0, errors.New("invalid ipv4 format")
}
return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24, nil
}
// Long2IPString 把数值转为ip字符串
func (a *AnalysisIp) Long2IPString(i uint) (string, error) {
if i > math.MaxUint32 {
return "", errors.New("beyond the scope of ipv4")
}
ip := make(net.IP, net.IPv4len)
ip[0] = byte(i >> 24)
ip[1] = byte(i >> 16)
ip[2] = byte(i >> 8)
ip[3] = byte(i)
return ip.String(), nil
}
// IP2Long 把net.IP转为数值
func (a *AnalysisIp) IP2Long(ip net.IP) (uint, error) {
b := ip.To4()
if b == nil {
return 0, errors.New("invalid ipv4 format")
}
return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24, nil
}
// Long2IP 把数值转为net.IP
func (a *AnalysisIp) Long2IP(i uint) (net.IP, error) {
if i > math.MaxUint32 {
return nil, errors.New("beyond the scope of ipv4")
}
ip := make(net.IP, net.IPv4len)
ip[0] = byte(i >> 24)
ip[1] = byte(i >> 16)
ip[2] = byte(i >> 8)
ip[3] = byte(i)
return ip, nil
}