2020-04-20 09:43:45 +02:00
|
|
|
package netutil
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"net"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
*/
|
|
|
|
|
2020-04-21 08:27:28 +02:00
|
|
|
// IPRange is a structure that holds the start and end of a range of IP Addresses.
|
2020-04-20 09:43:45 +02:00
|
|
|
type IPRange struct {
|
2020-09-15 22:37:11 +02:00
|
|
|
Start net.IP `ini:"start" json:"start" yaml:"Start" toml:"Start"`
|
|
|
|
End net.IP `ini:"end" json:"end" yaml:"End" toml:"End"`
|
2020-04-20 09:43:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// IPInRange reports whether a given IP Address is within a range given.
|
|
|
|
func IPInRange(r IPRange, ipAddress net.IP) bool {
|
|
|
|
return bytes.Compare(ipAddress, r.Start) >= 0 && bytes.Compare(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
|
|
|
|
}
|