xref: /unit/test/test_client_ip.py (revision 1937:0791ba191da0)
1import pytest
2
3from unit.applications.lang.python import TestApplicationPython
4
5
6class TestClientIP(TestApplicationPython):
7    prerequisites = {'modules': {'python': 'any'}}
8
9    def client_ip(self, options):
10        assert 'success' in self.conf(
11            {
12                "127.0.0.1:7081":
13                    {"client_ip": options, "pass": "applications/client_ip"},
14                "[::1]:7082":
15                    {"client_ip": options, "pass": "applications/client_ip"},
16            },
17            'listeners',
18        ), 'listeners configure'
19
20    def get_xff(self, xff, sock_type='ipv4'):
21        port = 7081 if sock_type == 'ipv4' else 7082
22
23        return self.get(
24            sock_type=sock_type,
25            port=port,
26            headers={'Connection': 'close', 'X-Forwarded-For': xff},
27        )['body']
28
29    def setup_method(self):
30        self.load('client_ip')
31
32    def test_settings_client_ip_single_ip(self):
33        self.client_ip(
34            {'header': 'X-Forwarded-For', 'source': '123.123.123.123'}
35        )
36
37        assert self.get(port=7081)['body'] == '127.0.0.1', 'ipv4 default'
38        assert (
39            self.get(sock_type='ipv6', port=7082)['body'] == '::1'
40        ), 'ipv6 default'
41        assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source'
42        assert self.get_xff('blah') == '127.0.0.1', 'bad header'
43        assert self.get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6'
44
45        self.client_ip({'header': 'X-Forwarded-For', 'source': '127.0.0.1'})
46
47        assert self.get(port=7081)['body'] == '127.0.0.1', 'ipv4 default 2'
48        assert (
49            self.get(sock_type='ipv6', port=7082)['body'] == '::1'
50        ), 'ipv6 default 2'
51        assert self.get_xff('1.1.1.1') == '1.1.1.1', 'replace'
52        assert self.get_xff('blah') == '127.0.0.1', 'bad header 2'
53        assert (
54            self.get_xff('1.1.1.1', 'ipv6') == '::1'
55        ), 'bad source ipv6 2'
56
57        self.client_ip({'header': 'X-Forwarded-For', 'source': '!127.0.0.1'})
58
59        assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source 3'
60        assert self.get_xff('1.1.1.1', 'ipv6') == '1.1.1.1', 'replace 2'
61
62    def test_settings_client_ip_ipv4(self):
63        self.client_ip({'header': 'X-Forwarded-For', 'source': '127.0.0.1'})
64
65        assert (
66            self.get_xff('8.8.8.8, 84.23.23.11') == '84.23.23.11'
67        ), 'xff replace'
68        assert (
69            self.get_xff('8.8.8.8, 84.23.23.11, 127.0.0.1') == '127.0.0.1'
70        ), 'xff replace 2'
71        assert (
72            self.get_xff(['8.8.8.8', '127.0.0.1, 10.0.1.1']) == '10.0.1.1'
73        ), 'xff replace multi'
74
75    def test_settings_client_ip_ipv6(self):
76        self.client_ip({'header': 'X-Forwarded-For', 'source': '::1'})
77
78        assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source ipv4'
79
80        for ip in [
81            'f607:7403:1e4b:6c66:33b2:843f:2517:da27',
82            '2001:db8:3c4d:15::1a2f:1a2b',
83            '2001::3c4d:15:1a2f:1a2b',
84            '::11.22.33.44',
85        ]:
86            assert self.get_xff(ip, 'ipv6') == ip, 'replace'
87
88    def test_settings_client_ip_recursive(self):
89        self.client_ip(
90            {
91                'header': 'X-Forwarded-For',
92                'recursive': True,
93                'source': ['127.0.0.1', '10.50.0.17', '10.5.2.1'],
94            }
95        )
96
97        assert self.get_xff('1.1.1.1') == '1.1.1.1', 'xff chain'
98        assert self.get_xff('1.1.1.1, 10.5.2.1') == '1.1.1.1', 'xff chain 2'
99        assert (
100            self.get_xff('8.8.8.8, 1.1.1.1, 10.5.2.1') == '1.1.1.1'
101        ), 'xff chain 3'
102        assert (
103            self.get_xff('10.50.0.17, 10.5.2.1, 10.5.2.1') == '10.50.0.17'
104        ), 'xff chain 4'
105        assert (
106            self.get_xff(['8.8.8.8', '1.1.1.1, 127.0.0.1']) == '1.1.1.1'
107        ), 'xff replace multi'
108        assert (
109            self.get_xff(['8.8.8.8', '1.1.1.1, 127.0.0.1', '10.5.2.1'])
110            == '1.1.1.1'
111        ), 'xff replace multi 2'
112        assert (
113            self.get_xff(['10.5.2.1', '10.50.0.17, 1.1.1.1', '10.5.2.1'])
114            == '1.1.1.1'
115        ), 'xff replace multi 3'
116        assert (
117            self.get_xff('8.8.8.8, 2001:db8:3c4d:15::1a2f:1a2b, 127.0.0.1')
118            == '2001:db8:3c4d:15::1a2f:1a2b'
119        ), 'xff chain ipv6'
120
121    def test_settings_client_ip_invalid(self):
122        assert 'error' in self.conf(
123            {"http": {"client_ip": {'header': 'X-Forwarded-For', 'source': []}}},
124            'settings',
125        ), 'empty array source'
126        assert 'error' in self.conf(
127            {"http":{"client_ip": {'header': 'X-Forwarded-For', 'source': 'a'}}},
128            'settings',
129        ), 'empty source invalid'
130