forked from kataras/iris
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ip.go
65 lines (56 loc) · 1.78 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
package netutil
import (
"bytes"
"net"
"strings"
"unsafe"
)
/* Based on:
https://husobee.github.io/golang/ip-address/2015/12/17/remote-ip-go.html requested at:
https://github.com/kataras/iris/issues/1453
*/
// IPRange is a structure that holds the start and end of a range of IP Addresses.
type IPRange struct {
Start string `ini:"start" json:"start" yaml:"Start" toml:"Start"`
End string `ini:"end" json:"end" yaml:"End" toml:"End"`
}
func unsafeCompare(a []byte, b string) int {
bb := *(*[]byte)(unsafe.Pointer(&b))
return bytes.Compare(a, bb)
}
// IPInRange reports whether a given IP Address is within a range given.
func IPInRange(r IPRange, ipAddress net.IP) bool {
return unsafeCompare(ipAddress, r.Start) >= 0 && unsafeCompare(ipAddress, r.End) < 0
}
// IPIsPrivateSubnet reports whether this "ipAddress" is in a private subnet.
func IPIsPrivateSubnet(ipAddress net.IP, privateRanges []IPRange) bool {
// IPv4 for now.
if ipCheck := ipAddress.To4(); ipCheck != nil {
// iterate over all our ranges.
for _, r := range privateRanges {
// check if this ip is in a private range.
if IPInRange(r, ipAddress) {
return true
}
}
}
return false
}
// GetIPAddress returns a valid public IP Address from a collection of IP Addresses
// and a range of private subnets.
//
// Reports whether a valid IP was found.
func GetIPAddress(ipAddresses []string, privateRanges []IPRange) (string, bool) {
// march from right to left until we get a public address
// that will be the address right before our proxy.
for i := len(ipAddresses) - 1; i >= 0; i-- {
ip := strings.TrimSpace(ipAddresses[i])
realIP := net.ParseIP(ip)
if !realIP.IsGlobalUnicast() || IPIsPrivateSubnet(realIP, privateRanges) {
// bad address, go to next
continue
}
return ip, true
}
return "", false
}