Refactored the GetIpddressFromRequest function to support ipv4 as well as ipv6 addresses (#3496)

This commit is contained in:
Aziz Rmadi 2024-01-03 13:07:11 -06:00 committed by GitHub
parent 468e32a2f0
commit bc1f66c858
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 23 deletions

View File

@ -23,24 +23,20 @@ func GenerateClientIDFromRequest(req *http.Request) string {
// GetIPAddressFromRequest returns the IP address from a http request.
func GetIPAddressFromRequest(req *http.Request) string {
ipAddressString := req.RemoteAddr
xForwardedFor := req.Header.Get("X-FORWARDED-FOR")
if xForwardedFor != "" {
clientIpString := strings.Split(xForwardedFor, ", ")[0]
// If the IP has a prefix of ::ffff: then it's an IPv4 address.
// Strip the prefix so we can parse it as an IPv4 address.
clientIpString = strings.TrimPrefix(clientIpString, "::ffff:")
if strings.Contains(clientIpString, ":") {
ip, _, err := net.SplitHostPort(clientIpString)
if err != nil {
log.Errorln(err)
return ""
}
return ip
}
return clientIpString
ipAddressString = strings.Split(xForwardedFor, ", ")[0]
}
if !strings.Contains(ipAddressString, ":") {
return ipAddressString
}
if isIPv6(ipAddressString) && !strings.Contains(ipAddressString, "[") {
return ipAddressString
}
ip, _, err := net.SplitHostPort(ipAddressString)
if err != nil {
log.Errorln(err)
@ -49,3 +45,7 @@ func GetIPAddressFromRequest(req *http.Request) string {
return ip
}
func isIPv6(address string) bool {
return strings.Count(address, ":") >= 2
}

View File

@ -7,21 +7,82 @@ import (
func TestGetIPAddressFromRequest(t *testing.T) {
expectedResult := "203.0.113.195"
expectedIpv4Result := "203.0.113.195"
expectedIpv6Result := "2001:9e8:5221:4201:5221:7dff:fe53"
request := httptest.NewRequest("GET", "/", nil)
//Test ipv4 address without X-FORWARDED-FOR header (With Port set up)
request.RemoteAddr = "203.0.113.195:41237"
//First Test without X-FORWARDED-FOR header
result := GetIPAddressFromRequest(request)
if result != expectedResult {
t.Errorf("Remote address only test failed: Expected %s, got %s", expectedResult, result)
if result != expectedIpv4Result {
t.Errorf("IPV4 Remote address only (with Port) test failed: Expected %s, got %s", expectedIpv4Result, result)
}
//Test with X-FORWARDED-FOR header
request.Header.Set("X-FORWARDED-FOR header", "203.0.113.195:41237, 198.51.100.100:38523, 140.248.67.176:12345")
//Test ipv4 without X-FORWARDED-FOR header (Without Port set up)
request.RemoteAddr = "203.0.113.195"
result = GetIPAddressFromRequest(request)
if result != expectedResult {
t.Errorf("X-FORWARD-FOR header test failed: Expected %s, got %s", expectedResult, result)
if result != expectedIpv4Result {
t.Errorf("IPV4 Remote address only (without Port) test failed: Expected %s, got %s", expectedIpv4Result, result)
}
//Test ipv4 with X-FORWARDED-FOR header (With Port SetUp)
request.Header.Set("X-FORWARDED-FOR", "203.0.113.195:41237, 198.51.100.100:38523, 140.248.67.176:12345")
result = GetIPAddressFromRequest(request)
if result != expectedIpv4Result {
t.Errorf("IPV4 X-FORWARDED-FOR header (With Port) test failed: Expected %s, got %s", expectedIpv4Result, result)
}
//Test ipv4 with X-FORWARDED-FOR header (Without Port SetUp)
request.Header.Set("X-FORWARDED-FOR", "203.0.113.195, 198.51.100.100, 140.248.67.176")
result = GetIPAddressFromRequest(request)
if result != expectedIpv4Result {
t.Errorf("IPV4 X-FORWARDED-FOR header (Without Port) test failed: Expected %s, got %s", expectedIpv4Result, result)
}
//Reset X-FORWARDED-FOR Header
request.Header.Set("X-FORWARDED-FOR", "")
//Test ipv6 address without X-FORWARDED-FOR header (With Port Set Up)
request.RemoteAddr = "[2001:9e8:5221:4201:5221:7dff:fe53]:9080"
result = GetIPAddressFromRequest(request)
if result != expectedIpv6Result {
t.Errorf("IPV6 Remote address only (with Port) test failed: Expected %s, got %s", expectedIpv6Result, result)
}
//Test ipv6 address without X-FORWARDED-FOR header (Without Port Set Up)
request.RemoteAddr = "2001:9e8:5221:4201:5221:7dff:fe53"
result = GetIPAddressFromRequest(request)
if result != expectedIpv6Result {
t.Errorf("IPV6 Remote address only (with Port) test failed: Expected %s, got %s", expectedIpv6Result, result)
}
//Test ipv6 with X-FORWARDED-FOR header (Without Port SetUp)
request.Header.Set("X-FORWARDED-FOR", "2001:9e8:5221:4201:5221:7dff:fe53, 2002:9e7:5231:4211:5211:7eff:ee53, 2003:7e8:5221:4231:5221:7dff:ff53")
result = GetIPAddressFromRequest(request)
if result != expectedIpv6Result {
t.Errorf("IPV6 X-FORWARDED-FOR header (Without Port) test failed: Expected %s, got %s", expectedIpv6Result, result)
}
//Test ipv6 with X-FORWARDED-FOR header (With Port SetUp)
request.Header.Set("X-FORWARDED-FOR", "[2001:9e8:5221:4201:5221:7dff:fe53]:9080, [2002:9e7:5231:4211:5211:7eff:ee53]:9080, [2003:7e8:5221:4231:5221:7dff:ff53]:9080")
result = GetIPAddressFromRequest(request)
if result != expectedIpv6Result {
t.Errorf("IPV6 X-FORWARDED-FOR header (Without Port) test failed: Expected %s, got %s", expectedIpv6Result, result)
}
}
func TestIsIpv6(t *testing.T) {
ipv6AddressWithoutPort := "2001:9e8:5221:4201:5221:7dff:fe53"
ipv6AddressWithPort := "[2001:9e8:5221:4201:5221:7dff:fe53]:9080"
ipv4AddressWithoutPort := "203.0.113.195"
ipv4AddressWithPort := "203.0.113.195:9080"
if !isIPv6(ipv6AddressWithPort) || !isIPv6(ipv6AddressWithoutPort) {
t.Error("IPV6 format test returned false on a valid ipv6 address")
}
if isIPv6(ipv4AddressWithPort) || isIPv6(ipv4AddressWithoutPort) {
t.Error("IPV6 format test returned true on an invalid ipv6 address")
}
}