From 6eb0073866b99de5dda595af0ef88fbe958e87ac Mon Sep 17 00:00:00 2001 From: yuekui Date: Wed, 24 Jul 2024 18:21:43 -0700 Subject: [PATCH 1/4] Fix edge cases with unknown IP addres --- rest_framework_tracking/base_mixins.py | 19 +++++++++++-------- tests/test_mixins.py | 8 ++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/rest_framework_tracking/base_mixins.py b/rest_framework_tracking/base_mixins.py index a4725a5..e33c789 100644 --- a/rest_framework_tracking/base_mixins.py +++ b/rest_framework_tracking/base_mixins.py @@ -111,11 +111,8 @@ def _get_path(self, request): def _get_ip_address(self, request): """Get the remote ip address the request was generated from.""" - ipaddr = request.META.get("HTTP_X_FORWARDED_FOR", None) - if ipaddr: - ipaddr = ipaddr.split(",")[0] - else: - ipaddr = request.META.get("REMOTE_ADDR", "").split(",")[0] + raw_possibles = request.META.get("HTTP_X_FORWARDED_FOR", "").split(",") + raw_possibles += request.META.get("REMOTE_ADDR", "").split(",") # Account for IPv4 and IPv6 addresses, each possibly with port appended. Possibilities are: # @@ -123,15 +120,21 @@ def _get_ip_address(self, request): # :port # []:port # Note that ipv6 addresses are colon separated hex numbers - possibles = (ipaddr.lstrip("[").split("]")[0], ipaddr.split(":")[0]) - + possibles = [ + i.strip() + for sublist in [ + (ipaddr.lstrip("[").split("]")[0], ipaddr.split(":")[0]) + for ipaddr in raw_possibles + ] + for i in sublist + ] for addr in possibles: try: return str(ipaddress.ip_address(addr)) except ValueError: pass - return ipaddr + return raw_possibles[0] def _get_view_name(self, request): """Get view name.""" diff --git a/tests/test_mixins.py b/tests/test_mixins.py index a9eb79f..3696439 100644 --- a/tests/test_mixins.py +++ b/tests/test_mixins.py @@ -105,6 +105,14 @@ def test_log_ip_xforwarded_list(self): log = APIRequestLog.objects.first() self.assertEqual(log.remote_addr, "127.0.0.8") + def test_log_ip_xforwarded_list_with_unkown_ip(self): + request = APIRequestFactory().get("/logging") + request.META["HTTP_X_FORWARDED_FOR"] = "unknown, 128.1.1.9" + + MockLoggingView.as_view()(request).render() + log = APIRequestLog.objects.first() + self.assertEqual(log.remote_addr, "128.1.1.9") + def test_log_host(self): self.client.get("/logging") log = APIRequestLog.objects.first() From aeade52e1294ecf5066bbd718e83b8082c0ef15e Mon Sep 17 00:00:00 2001 From: yuekui Date: Wed, 24 Jul 2024 18:21:58 -0700 Subject: [PATCH 2/4] Fix allowlist_externals error --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index c171b37..9a2a23c 100644 --- a/tox.ini +++ b/tox.ini @@ -19,7 +19,7 @@ tox_pyenv_fallback = True commands = python -V pip install --upgrade pip pipenv pipenv install --skip-lock - ./runtests.py --fast + python runtests.py --fast passenv = DATABASE_URL PYTHON_VERSION From b255ab7b8c129497ed8528ebf887f7326eb1f887 Mon Sep 17 00:00:00 2001 From: yuekui Date: Wed, 24 Jul 2024 18:57:17 -0700 Subject: [PATCH 3/4] Fix typo --- tests/test_mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_mixins.py b/tests/test_mixins.py index 3696439..7dbb9e1 100644 --- a/tests/test_mixins.py +++ b/tests/test_mixins.py @@ -105,7 +105,7 @@ def test_log_ip_xforwarded_list(self): log = APIRequestLog.objects.first() self.assertEqual(log.remote_addr, "127.0.0.8") - def test_log_ip_xforwarded_list_with_unkown_ip(self): + def test_log_ip_xforwarded_list_with_unknown_ip(self): request = APIRequestFactory().get("/logging") request.META["HTTP_X_FORWARDED_FOR"] = "unknown, 128.1.1.9" From 994c8ee616807963b917975de7a03a3bdb6751f2 Mon Sep 17 00:00:00 2001 From: yuekui Date: Fri, 26 Jul 2024 16:30:44 -0700 Subject: [PATCH 4/4] Refine IP address selecting --- rest_framework_tracking/base_mixins.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/rest_framework_tracking/base_mixins.py b/rest_framework_tracking/base_mixins.py index e33c789..0ab2a4e 100644 --- a/rest_framework_tracking/base_mixins.py +++ b/rest_framework_tracking/base_mixins.py @@ -120,14 +120,18 @@ def _get_ip_address(self, request): # :port # []:port # Note that ipv6 addresses are colon separated hex numbers - possibles = [ - i.strip() - for sublist in [ - (ipaddr.lstrip("[").split("]")[0], ipaddr.split(":")[0]) - for ipaddr in raw_possibles - ] - for i in sublist - ] + raw_possibles = [addr.strip() for addr in raw_possibles] + possibles = [] + for possible_addr in raw_possibles: + if '[' in possible_addr: + # IPv6 with port + possibles.append(possible_addr.rsplit(":", 1)[0].strip("[]")) + elif possible_addr.count(":") == 1: + # IPv4 with port + possibles.append(possible_addr.split(":")[0]) + else: + # IPv4/IPv6 without port and others + possibles.append(possible_addr) for addr in possibles: try: return str(ipaddress.ip_address(addr))