import pytest from django.test import RequestFactory, override_settings from portal.accounts.clientip import client_ip, parse_networks from portal.accounts.middleware import ClientIpMiddleware PROXY = parse_networks(["192.168.180.150"]) def test_without_a_trusted_proxy_the_peer_is_the_client_and_the_header_is_ignored(): assert client_ip("203.0.113.9", "1.2.3.4", []) == "203.0.113.9" def test_a_peer_that_is_not_a_trusted_proxy_cannot_set_the_address(): assert client_ip("203.0.113.9", "1.2.3.4", PROXY) == "203.0.113.9" def test_behind_a_trusted_proxy_the_last_entry_is_used(): assert client_ip("192.168.180.150", "9.9.9.9, 198.51.100.7", PROXY) == "198.51.100.7" def test_entries_before_the_last_cannot_be_forged_by_the_client(): assert client_ip("192.168.180.150", "6.6.6.6, 7.7.7.7, 198.51.100.7", PROXY) == "198.51.100.7" @pytest.mark.parametrize("header", ["", "not-an-ip", "198.51.100.7, garbage"]) def test_a_missing_or_malformed_header_falls_back_to_the_proxy_address(header): assert client_ip("192.168.180.150", header, PROXY) == "192.168.180.150" def test_networks_work_and_ipv6_is_handled(): nets = parse_networks(["10.0.0.0/8", "fd00::/8"]) assert client_ip("10.1.2.3", "198.51.100.7", nets) == "198.51.100.7" assert client_ip("fd00::1", "2001:db8::5", nets) == "2001:db8::5" def test_a_missing_peer_gives_no_address(): assert client_ip("", "1.2.3.4", PROXY) == "" def test_x_real_ip_is_never_used(): request = RequestFactory().get( "/", REMOTE_ADDR="192.168.180.150", HTTP_X_REAL_IP="6.6.6.6" ) with override_settings(TRUSTED_PROXIES=["192.168.180.150"]): middleware = ClientIpMiddleware(lambda r: r) assert middleware(request).client_ip == "192.168.180.150" def test_the_middleware_applies_the_rule(): request = RequestFactory().get( "/", REMOTE_ADDR="192.168.180.150", HTTP_X_FORWARDED_FOR="6.6.6.6, 198.51.100.7" ) with override_settings(TRUSTED_PROXIES=["192.168.180.150"]): middleware = ClientIpMiddleware(lambda r: r) assert middleware(request).client_ip == "198.51.100.7"