xref: /unit/test/test_client_ip.py (revision 2171:20f712007059)
11937So.canty@f5.comfrom unit.applications.lang.python import TestApplicationPython
2*2171Szelenkov@nginx.comfrom unit.option import option
31937So.canty@f5.com
41937So.canty@f5.com
51937So.canty@f5.comclass TestClientIP(TestApplicationPython):
61937So.canty@f5.com    prerequisites = {'modules': {'python': 'any'}}
71937So.canty@f5.com
81937So.canty@f5.com    def client_ip(self, options):
91937So.canty@f5.com        assert 'success' in self.conf(
101937So.canty@f5.com            {
112066Szelenkov@nginx.com                "127.0.0.1:7081": {
122066Szelenkov@nginx.com                    "client_ip": options,
132066Szelenkov@nginx.com                    "pass": "applications/client_ip",
142066Szelenkov@nginx.com                },
152066Szelenkov@nginx.com                "[::1]:7082": {
162066Szelenkov@nginx.com                    "client_ip": options,
172066Szelenkov@nginx.com                    "pass": "applications/client_ip",
182066Szelenkov@nginx.com                },
19*2171Szelenkov@nginx.com                "unix:"
20*2171Szelenkov@nginx.com                + option.temp_dir
21*2171Szelenkov@nginx.com                + "/sock": {
22*2171Szelenkov@nginx.com                    "client_ip": options,
23*2171Szelenkov@nginx.com                    "pass": "applications/client_ip",
24*2171Szelenkov@nginx.com                },
251937So.canty@f5.com            },
261937So.canty@f5.com            'listeners',
271937So.canty@f5.com        ), 'listeners configure'
281937So.canty@f5.com
291937So.canty@f5.com    def get_xff(self, xff, sock_type='ipv4'):
30*2171Szelenkov@nginx.com        address = {
31*2171Szelenkov@nginx.com            'ipv4': ('127.0.0.1', 7081),
32*2171Szelenkov@nginx.com            'ipv6': ('::1', 7082),
33*2171Szelenkov@nginx.com            'unix': (option.temp_dir + '/sock', None),
34*2171Szelenkov@nginx.com        }
35*2171Szelenkov@nginx.com        (addr, port) = address[sock_type]
361937So.canty@f5.com
371937So.canty@f5.com        return self.get(
381937So.canty@f5.com            sock_type=sock_type,
39*2171Szelenkov@nginx.com            addr=addr,
401937So.canty@f5.com            port=port,
411937So.canty@f5.com            headers={'Connection': 'close', 'X-Forwarded-For': xff},
421937So.canty@f5.com        )['body']
431937So.canty@f5.com
441937So.canty@f5.com    def setup_method(self):
451937So.canty@f5.com        self.load('client_ip')
461937So.canty@f5.com
472130Sz.hong@f5.com    def test_client_ip_single_ip(self):
481937So.canty@f5.com        self.client_ip(
491937So.canty@f5.com            {'header': 'X-Forwarded-For', 'source': '123.123.123.123'}
501937So.canty@f5.com        )
511937So.canty@f5.com
521937So.canty@f5.com        assert self.get(port=7081)['body'] == '127.0.0.1', 'ipv4 default'
531937So.canty@f5.com        assert (
541937So.canty@f5.com            self.get(sock_type='ipv6', port=7082)['body'] == '::1'
551937So.canty@f5.com        ), 'ipv6 default'
561937So.canty@f5.com        assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source'
571937So.canty@f5.com        assert self.get_xff('blah') == '127.0.0.1', 'bad header'
581937So.canty@f5.com        assert self.get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6'
591937So.canty@f5.com
601937So.canty@f5.com        self.client_ip({'header': 'X-Forwarded-For', 'source': '127.0.0.1'})
611937So.canty@f5.com
621937So.canty@f5.com        assert self.get(port=7081)['body'] == '127.0.0.1', 'ipv4 default 2'
631937So.canty@f5.com        assert (
641937So.canty@f5.com            self.get(sock_type='ipv6', port=7082)['body'] == '::1'
651937So.canty@f5.com        ), 'ipv6 default 2'
661937So.canty@f5.com        assert self.get_xff('1.1.1.1') == '1.1.1.1', 'replace'
671937So.canty@f5.com        assert self.get_xff('blah') == '127.0.0.1', 'bad header 2'
682066Szelenkov@nginx.com        assert self.get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6 2'
691937So.canty@f5.com
701937So.canty@f5.com        self.client_ip({'header': 'X-Forwarded-For', 'source': '!127.0.0.1'})
711937So.canty@f5.com
721937So.canty@f5.com        assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source 3'
731937So.canty@f5.com        assert self.get_xff('1.1.1.1', 'ipv6') == '1.1.1.1', 'replace 2'
741937So.canty@f5.com
752130Sz.hong@f5.com    def test_client_ip_ipv4(self):
761937So.canty@f5.com        self.client_ip({'header': 'X-Forwarded-For', 'source': '127.0.0.1'})
771937So.canty@f5.com
781937So.canty@f5.com        assert (
791937So.canty@f5.com            self.get_xff('8.8.8.8, 84.23.23.11') == '84.23.23.11'
801937So.canty@f5.com        ), 'xff replace'
811937So.canty@f5.com        assert (
821937So.canty@f5.com            self.get_xff('8.8.8.8, 84.23.23.11, 127.0.0.1') == '127.0.0.1'
831937So.canty@f5.com        ), 'xff replace 2'
841937So.canty@f5.com        assert (
851937So.canty@f5.com            self.get_xff(['8.8.8.8', '127.0.0.1, 10.0.1.1']) == '10.0.1.1'
861937So.canty@f5.com        ), 'xff replace multi'
871937So.canty@f5.com
882130Sz.hong@f5.com    def test_client_ip_ipv6(self):
891937So.canty@f5.com        self.client_ip({'header': 'X-Forwarded-For', 'source': '::1'})
901937So.canty@f5.com
911937So.canty@f5.com        assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source ipv4'
921937So.canty@f5.com
931937So.canty@f5.com        for ip in [
941937So.canty@f5.com            'f607:7403:1e4b:6c66:33b2:843f:2517:da27',
951937So.canty@f5.com            '2001:db8:3c4d:15::1a2f:1a2b',
961937So.canty@f5.com            '2001::3c4d:15:1a2f:1a2b',
971937So.canty@f5.com            '::11.22.33.44',
981937So.canty@f5.com        ]:
991937So.canty@f5.com            assert self.get_xff(ip, 'ipv6') == ip, 'replace'
1001937So.canty@f5.com
101*2171Szelenkov@nginx.com    def test_client_ip_unix(self, temp_dir):
102*2171Szelenkov@nginx.com        self.client_ip({'header': 'X-Forwarded-For', 'source': 'unix'})
103*2171Szelenkov@nginx.com
104*2171Szelenkov@nginx.com        assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source ipv4'
105*2171Szelenkov@nginx.com        assert self.get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6'
106*2171Szelenkov@nginx.com
107*2171Szelenkov@nginx.com        for ip in [
108*2171Szelenkov@nginx.com            '1.1.1.1',
109*2171Szelenkov@nginx.com            '::11.22.33.44',
110*2171Szelenkov@nginx.com        ]:
111*2171Szelenkov@nginx.com            assert self.get_xff(ip, 'unix') == ip, 'replace'
112*2171Szelenkov@nginx.com
1132130Sz.hong@f5.com    def test_client_ip_recursive(self):
1141937So.canty@f5.com        self.client_ip(
1151937So.canty@f5.com            {
1161937So.canty@f5.com                'header': 'X-Forwarded-For',
1171937So.canty@f5.com                'recursive': True,
1181937So.canty@f5.com                'source': ['127.0.0.1', '10.50.0.17', '10.5.2.1'],
1191937So.canty@f5.com            }
1201937So.canty@f5.com        )
1211937So.canty@f5.com
1221937So.canty@f5.com        assert self.get_xff('1.1.1.1') == '1.1.1.1', 'xff chain'
1231937So.canty@f5.com        assert self.get_xff('1.1.1.1, 10.5.2.1') == '1.1.1.1', 'xff chain 2'
1241937So.canty@f5.com        assert (
1251937So.canty@f5.com            self.get_xff('8.8.8.8, 1.1.1.1, 10.5.2.1') == '1.1.1.1'
1261937So.canty@f5.com        ), 'xff chain 3'
1271937So.canty@f5.com        assert (
1281937So.canty@f5.com            self.get_xff('10.50.0.17, 10.5.2.1, 10.5.2.1') == '10.50.0.17'
1291937So.canty@f5.com        ), 'xff chain 4'
1301937So.canty@f5.com        assert (
1311937So.canty@f5.com            self.get_xff(['8.8.8.8', '1.1.1.1, 127.0.0.1']) == '1.1.1.1'
1321937So.canty@f5.com        ), 'xff replace multi'
1331937So.canty@f5.com        assert (
1341937So.canty@f5.com            self.get_xff(['8.8.8.8', '1.1.1.1, 127.0.0.1', '10.5.2.1'])
1351937So.canty@f5.com            == '1.1.1.1'
1361937So.canty@f5.com        ), 'xff replace multi 2'
1371937So.canty@f5.com        assert (
1381937So.canty@f5.com            self.get_xff(['10.5.2.1', '10.50.0.17, 1.1.1.1', '10.5.2.1'])
1391937So.canty@f5.com            == '1.1.1.1'
1401937So.canty@f5.com        ), 'xff replace multi 3'
1411937So.canty@f5.com        assert (
1421937So.canty@f5.com            self.get_xff('8.8.8.8, 2001:db8:3c4d:15::1a2f:1a2b, 127.0.0.1')
1431937So.canty@f5.com            == '2001:db8:3c4d:15::1a2f:1a2b'
1441937So.canty@f5.com        ), 'xff chain ipv6'
1451937So.canty@f5.com
1462130Sz.hong@f5.com    def test_client_ip_case_insensitive(self):
1472130Sz.hong@f5.com        self.client_ip({'header': 'x-forwarded-for', 'source': '127.0.0.1'})
1482130Sz.hong@f5.com
1492130Sz.hong@f5.com        assert self.get_xff('1.1.1.1') == '1.1.1.1', 'case insensitive'
1502130Sz.hong@f5.com
1512130Sz.hong@f5.com    def test_client_ip_empty_source(self):
1522130Sz.hong@f5.com        self.client_ip({'header': 'X-Forwarded-For', 'source': []})
1532130Sz.hong@f5.com
1542130Sz.hong@f5.com        assert self.get_xff('1.1.1.1') == '127.0.0.1', 'empty source'
1552130Sz.hong@f5.com
1562130Sz.hong@f5.com    def test_client_ip_invalid(self):
1571937So.canty@f5.com        assert 'error' in self.conf(
1582066Szelenkov@nginx.com            {
1592130Sz.hong@f5.com                "127.0.0.1:7081": {
1602130Sz.hong@f5.com                    "client_ip": {"source": '127.0.0.1'},
1612130Sz.hong@f5.com                    "pass": "applications/client_ip",
1622066Szelenkov@nginx.com                }
1632066Szelenkov@nginx.com            },
1642130Sz.hong@f5.com            'listeners',
1652130Sz.hong@f5.com        ), 'invalid header'
1662130Sz.hong@f5.com
1672130Sz.hong@f5.com        def check_invalid_source(source):
1682130Sz.hong@f5.com            assert 'error' in self.conf(
1692130Sz.hong@f5.com                {
1702130Sz.hong@f5.com                    "127.0.0.1:7081": {
1712130Sz.hong@f5.com                        "client_ip": {
1722130Sz.hong@f5.com                            "header": "X-Forwarded-For",
1732130Sz.hong@f5.com                            "source": source,
1742130Sz.hong@f5.com                        },
1752130Sz.hong@f5.com                        "pass": "applications/client_ip",
1762130Sz.hong@f5.com                    }
1772130Sz.hong@f5.com                },
1782130Sz.hong@f5.com                'listeners',
1792130Sz.hong@f5.com            ), 'invalid source'
1802130Sz.hong@f5.com
1812130Sz.hong@f5.com        check_invalid_source(None)
1822130Sz.hong@f5.com        check_invalid_source('a')
1832130Sz.hong@f5.com        check_invalid_source(['a'])
184