From bc1f66c858adeb551cbb868be43c9455e09ec53a Mon Sep 17 00:00:00 2001 From: Aziz Rmadi <46684200+armadi1809@users.noreply.github.com> Date: Wed, 3 Jan 2024 13:07:11 -0600 Subject: [PATCH] Refactored the GetIpddressFromRequest function to support ipv4 as well as ipv6 addresses (#3496) --- utils/clientId.go | 30 ++++++++-------- utils/clientId_test.go | 77 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 84 insertions(+), 23 deletions(-) diff --git a/utils/clientId.go b/utils/clientId.go index 0b9c7f16c..05255d0eb 100644 --- a/utils/clientId.go +++ b/utils/clientId.go @@ -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 +} diff --git a/utils/clientId_test.go b/utils/clientId_test.go index 9af802828..a134f2b52 100644 --- a/utils/clientId_test.go +++ b/utils/clientId_test.go @@ -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") + } }