-
Notifications
You must be signed in to change notification settings - Fork 0
/
user_ip.go
106 lines (89 loc) · 2.33 KB
/
user_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
package user_ip
import (
"bytes"
"net"
"net/http"
"strings"
"unicode"
)
type PrivateAddressesRange struct {
start net.IP
end net.IP
}
var privateIpAddresses = []PrivateAddressesRange{
PrivateAddressesRange{
start: net.IPv4(10, 0, 0, 0),
end: net.IPv4(10, 255, 255, 255),
},
PrivateAddressesRange{
start: net.IPv4(100, 64, 0, 0),
end: net.IPv4(100, 127, 255, 255),
},
PrivateAddressesRange{
start: net.IPv4(172, 16, 0, 0),
end: net.IPv4(172, 31, 255, 255),
},
PrivateAddressesRange{
start: net.IPv4(192, 0, 0, 0),
end: net.IPv4(192, 0, 0, 255),
},
PrivateAddressesRange{
start: net.IPv4(192, 168, 0, 0),
end: net.IPv4(192, 168, 255, 255),
},
PrivateAddressesRange{
start: net.IPv4(198, 18, 0, 0),
end: net.IPv4(198, 19, 255, 255),
},
PrivateAddressesRange{
start: net.ParseIP("fc00::"),
end: net.ParseIP("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
},
}
var HEADER_IP_KEYS = []string{"X-Forwarded-For", "X-Real-Ip"}
const MAX_IP_SEARCH int = 4
// =====================================================================================
func removeWhiteSpaces(str string) string {
return strings.Map(func(char rune) rune {
if unicode.IsSpace(char) {
return -1
}
return char
}, str)
}
func isPrivateAddress(ip net.IP) bool {
for _, privateIpRange := range privateIpAddresses {
if bytes.Compare(ip, privateIpRange.start) >= 0 && bytes.Compare(ip, privateIpRange.end) <= 0 {
return true
}
}
return false
}
func ignoreIp(ip net.IP) bool {
return !ip.IsGlobalUnicast() || isPrivateAddress(ip)
}
func findRealIP(ipAddress *string, availableIps []string) {
if len(availableIps) >= MAX_IP_SEARCH {
availableIps = availableIps[:MAX_IP_SEARCH]
}
for _, ip := range availableIps {
ip = removeWhiteSpaces(ip)
userIp := net.ParseIP(ip)
if ignoreIp(userIp) {
continue
} else {
*ipAddress = ip
}
}
}
// =====================================================================================
func Get(req *http.Request) string {
var ipAddress string
for _, headerProperty := range HEADER_IP_KEYS {
// We will only search through up to MAX_IP_SEARCH, we should not be looking
// for all of them, since client may be playing with X-Forwarded-For
availableIps := strings.Split(req.Header.Get(headerProperty), ",")
findRealIP(&ipAddress, availableIps)
}
return ipAddress
}