11937So.canty@f5.comfrom unit.applications.lang.python import TestApplicationPython 21937So.canty@f5.com 31937So.canty@f5.com 41937So.canty@f5.comclass TestClientIP(TestApplicationPython): 51937So.canty@f5.com prerequisites = {'modules': {'python': 'any'}} 61937So.canty@f5.com 71937So.canty@f5.com def client_ip(self, options): 81937So.canty@f5.com assert 'success' in self.conf( 91937So.canty@f5.com { 102066Szelenkov@nginx.com "127.0.0.1:7081": { 112066Szelenkov@nginx.com "client_ip": options, 122066Szelenkov@nginx.com "pass": "applications/client_ip", 132066Szelenkov@nginx.com }, 142066Szelenkov@nginx.com "[::1]:7082": { 152066Szelenkov@nginx.com "client_ip": options, 162066Szelenkov@nginx.com "pass": "applications/client_ip", 172066Szelenkov@nginx.com }, 181937So.canty@f5.com }, 191937So.canty@f5.com 'listeners', 201937So.canty@f5.com ), 'listeners configure' 211937So.canty@f5.com 221937So.canty@f5.com def get_xff(self, xff, sock_type='ipv4'): 231937So.canty@f5.com port = 7081 if sock_type == 'ipv4' else 7082 241937So.canty@f5.com 251937So.canty@f5.com return self.get( 261937So.canty@f5.com sock_type=sock_type, 271937So.canty@f5.com port=port, 281937So.canty@f5.com headers={'Connection': 'close', 'X-Forwarded-For': xff}, 291937So.canty@f5.com )['body'] 301937So.canty@f5.com 311937So.canty@f5.com def setup_method(self): 321937So.canty@f5.com self.load('client_ip') 331937So.canty@f5.com 34*2130Sz.hong@f5.com def test_client_ip_single_ip(self): 351937So.canty@f5.com self.client_ip( 361937So.canty@f5.com {'header': 'X-Forwarded-For', 'source': '123.123.123.123'} 371937So.canty@f5.com ) 381937So.canty@f5.com 391937So.canty@f5.com assert self.get(port=7081)['body'] == '127.0.0.1', 'ipv4 default' 401937So.canty@f5.com assert ( 411937So.canty@f5.com self.get(sock_type='ipv6', port=7082)['body'] == '::1' 421937So.canty@f5.com ), 'ipv6 default' 431937So.canty@f5.com assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source' 441937So.canty@f5.com assert self.get_xff('blah') == '127.0.0.1', 'bad header' 451937So.canty@f5.com assert self.get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6' 461937So.canty@f5.com 471937So.canty@f5.com self.client_ip({'header': 'X-Forwarded-For', 'source': '127.0.0.1'}) 481937So.canty@f5.com 491937So.canty@f5.com assert self.get(port=7081)['body'] == '127.0.0.1', 'ipv4 default 2' 501937So.canty@f5.com assert ( 511937So.canty@f5.com self.get(sock_type='ipv6', port=7082)['body'] == '::1' 521937So.canty@f5.com ), 'ipv6 default 2' 531937So.canty@f5.com assert self.get_xff('1.1.1.1') == '1.1.1.1', 'replace' 541937So.canty@f5.com assert self.get_xff('blah') == '127.0.0.1', 'bad header 2' 552066Szelenkov@nginx.com assert self.get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6 2' 561937So.canty@f5.com 571937So.canty@f5.com self.client_ip({'header': 'X-Forwarded-For', 'source': '!127.0.0.1'}) 581937So.canty@f5.com 591937So.canty@f5.com assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source 3' 601937So.canty@f5.com assert self.get_xff('1.1.1.1', 'ipv6') == '1.1.1.1', 'replace 2' 611937So.canty@f5.com 62*2130Sz.hong@f5.com def test_client_ip_ipv4(self): 631937So.canty@f5.com self.client_ip({'header': 'X-Forwarded-For', 'source': '127.0.0.1'}) 641937So.canty@f5.com 651937So.canty@f5.com assert ( 661937So.canty@f5.com self.get_xff('8.8.8.8, 84.23.23.11') == '84.23.23.11' 671937So.canty@f5.com ), 'xff replace' 681937So.canty@f5.com assert ( 691937So.canty@f5.com self.get_xff('8.8.8.8, 84.23.23.11, 127.0.0.1') == '127.0.0.1' 701937So.canty@f5.com ), 'xff replace 2' 711937So.canty@f5.com assert ( 721937So.canty@f5.com self.get_xff(['8.8.8.8', '127.0.0.1, 10.0.1.1']) == '10.0.1.1' 731937So.canty@f5.com ), 'xff replace multi' 741937So.canty@f5.com 75*2130Sz.hong@f5.com def test_client_ip_ipv6(self): 761937So.canty@f5.com self.client_ip({'header': 'X-Forwarded-For', 'source': '::1'}) 771937So.canty@f5.com 781937So.canty@f5.com assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source ipv4' 791937So.canty@f5.com 801937So.canty@f5.com for ip in [ 811937So.canty@f5.com 'f607:7403:1e4b:6c66:33b2:843f:2517:da27', 821937So.canty@f5.com '2001:db8:3c4d:15::1a2f:1a2b', 831937So.canty@f5.com '2001::3c4d:15:1a2f:1a2b', 841937So.canty@f5.com '::11.22.33.44', 851937So.canty@f5.com ]: 861937So.canty@f5.com assert self.get_xff(ip, 'ipv6') == ip, 'replace' 871937So.canty@f5.com 88*2130Sz.hong@f5.com def test_client_ip_recursive(self): 891937So.canty@f5.com self.client_ip( 901937So.canty@f5.com { 911937So.canty@f5.com 'header': 'X-Forwarded-For', 921937So.canty@f5.com 'recursive': True, 931937So.canty@f5.com 'source': ['127.0.0.1', '10.50.0.17', '10.5.2.1'], 941937So.canty@f5.com } 951937So.canty@f5.com ) 961937So.canty@f5.com 971937So.canty@f5.com assert self.get_xff('1.1.1.1') == '1.1.1.1', 'xff chain' 981937So.canty@f5.com assert self.get_xff('1.1.1.1, 10.5.2.1') == '1.1.1.1', 'xff chain 2' 991937So.canty@f5.com assert ( 1001937So.canty@f5.com self.get_xff('8.8.8.8, 1.1.1.1, 10.5.2.1') == '1.1.1.1' 1011937So.canty@f5.com ), 'xff chain 3' 1021937So.canty@f5.com assert ( 1031937So.canty@f5.com self.get_xff('10.50.0.17, 10.5.2.1, 10.5.2.1') == '10.50.0.17' 1041937So.canty@f5.com ), 'xff chain 4' 1051937So.canty@f5.com assert ( 1061937So.canty@f5.com self.get_xff(['8.8.8.8', '1.1.1.1, 127.0.0.1']) == '1.1.1.1' 1071937So.canty@f5.com ), 'xff replace multi' 1081937So.canty@f5.com assert ( 1091937So.canty@f5.com self.get_xff(['8.8.8.8', '1.1.1.1, 127.0.0.1', '10.5.2.1']) 1101937So.canty@f5.com == '1.1.1.1' 1111937So.canty@f5.com ), 'xff replace multi 2' 1121937So.canty@f5.com assert ( 1131937So.canty@f5.com self.get_xff(['10.5.2.1', '10.50.0.17, 1.1.1.1', '10.5.2.1']) 1141937So.canty@f5.com == '1.1.1.1' 1151937So.canty@f5.com ), 'xff replace multi 3' 1161937So.canty@f5.com assert ( 1171937So.canty@f5.com self.get_xff('8.8.8.8, 2001:db8:3c4d:15::1a2f:1a2b, 127.0.0.1') 1181937So.canty@f5.com == '2001:db8:3c4d:15::1a2f:1a2b' 1191937So.canty@f5.com ), 'xff chain ipv6' 1201937So.canty@f5.com 121*2130Sz.hong@f5.com def test_client_ip_case_insensitive(self): 122*2130Sz.hong@f5.com self.client_ip({'header': 'x-forwarded-for', 'source': '127.0.0.1'}) 123*2130Sz.hong@f5.com 124*2130Sz.hong@f5.com assert self.get_xff('1.1.1.1') == '1.1.1.1', 'case insensitive' 125*2130Sz.hong@f5.com 126*2130Sz.hong@f5.com def test_client_ip_empty_source(self): 127*2130Sz.hong@f5.com self.client_ip({'header': 'X-Forwarded-For', 'source': []}) 128*2130Sz.hong@f5.com 129*2130Sz.hong@f5.com assert self.get_xff('1.1.1.1') == '127.0.0.1', 'empty source' 130*2130Sz.hong@f5.com 131*2130Sz.hong@f5.com def test_client_ip_invalid(self): 1321937So.canty@f5.com assert 'error' in self.conf( 1332066Szelenkov@nginx.com { 134*2130Sz.hong@f5.com "127.0.0.1:7081": { 135*2130Sz.hong@f5.com "client_ip": {"source": '127.0.0.1'}, 136*2130Sz.hong@f5.com "pass": "applications/client_ip", 1372066Szelenkov@nginx.com } 1382066Szelenkov@nginx.com }, 139*2130Sz.hong@f5.com 'listeners', 140*2130Sz.hong@f5.com ), 'invalid header' 141*2130Sz.hong@f5.com 142*2130Sz.hong@f5.com def check_invalid_source(source): 143*2130Sz.hong@f5.com assert 'error' in self.conf( 144*2130Sz.hong@f5.com { 145*2130Sz.hong@f5.com "127.0.0.1:7081": { 146*2130Sz.hong@f5.com "client_ip": { 147*2130Sz.hong@f5.com "header": "X-Forwarded-For", 148*2130Sz.hong@f5.com "source": source, 149*2130Sz.hong@f5.com }, 150*2130Sz.hong@f5.com "pass": "applications/client_ip", 151*2130Sz.hong@f5.com } 152*2130Sz.hong@f5.com }, 153*2130Sz.hong@f5.com 'listeners', 154*2130Sz.hong@f5.com ), 'invalid source' 155*2130Sz.hong@f5.com 156*2130Sz.hong@f5.com check_invalid_source(None) 157*2130Sz.hong@f5.com check_invalid_source('a') 158*2130Sz.hong@f5.com check_invalid_source(['a']) 159