mirror of
https://github.com/kataras/iris.git
synced 2026-01-04 02:37:14 +00:00
improve remote addr parsing as requested at: https://github.com/kataras/iris/issues/1453
Former-commit-id: e5fde988eda9bf582b04285a1c77ba123910a699
This commit is contained in:
59
core/netutil/ip.go
Normal file
59
core/netutil/ip.go
Normal file
@@ -0,0 +1,59 @@
|
||||
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
|
||||
*/
|
||||
|
||||
//IPRange is a structure that holds the start and end of a range of IP Addresses.
|
||||
type IPRange struct {
|
||||
Start net.IP `json:"start" yaml:"Start" toml"Start"`
|
||||
End net.IP `json:"end" yaml:"End" toml"End"`
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
62
core/netutil/ip_test.go
Normal file
62
core/netutil/ip_test.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIP(t *testing.T) {
|
||||
privateRanges := []IPRange{
|
||||
{
|
||||
Start: net.ParseIP("10.0.0.0"),
|
||||
End: net.ParseIP("10.255.255.255"),
|
||||
},
|
||||
{
|
||||
Start: net.ParseIP("100.64.0.0"),
|
||||
End: net.ParseIP("100.127.255.255"),
|
||||
},
|
||||
{
|
||||
Start: net.ParseIP("172.16.0.0"),
|
||||
End: net.ParseIP("172.31.255.255"),
|
||||
},
|
||||
{
|
||||
Start: net.ParseIP("192.0.0.0"),
|
||||
End: net.ParseIP("192.0.0.255"),
|
||||
},
|
||||
{
|
||||
Start: net.ParseIP("192.168.0.0"),
|
||||
End: net.ParseIP("192.168.255.255"),
|
||||
},
|
||||
{
|
||||
Start: net.ParseIP("198.18.0.0"),
|
||||
End: net.ParseIP("198.19.255.255"),
|
||||
},
|
||||
}
|
||||
|
||||
addresses := []string{
|
||||
"201.37.138.59",
|
||||
"159.117.3.153",
|
||||
"166.192.97.84",
|
||||
"225.181.213.210",
|
||||
"124.50.84.134",
|
||||
"87.53.250.102",
|
||||
"106.79.33.62",
|
||||
"242.120.17.144",
|
||||
"131.179.101.254",
|
||||
"103.11.11.174",
|
||||
"115.97.0.114",
|
||||
"219.202.120.251",
|
||||
"37.72.123.120",
|
||||
"154.94.78.101",
|
||||
"126.105.144.250",
|
||||
}
|
||||
|
||||
got, ok := GetIPAddress(addresses, privateRanges)
|
||||
if !ok {
|
||||
t.Logf("expected addr to be matched")
|
||||
}
|
||||
|
||||
if expected := "126.105.144.250"; expected != got {
|
||||
t.Logf("expected addr to be found: %s but got: %s", expected, got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user