From 2165a23c49fd69d9adbbaf34899003aa1bc72039 Mon Sep 17 00:00:00 2001 From: Scott Adams Date: Wed, 13 Aug 2014 11:22:29 +0200 Subject: [PATCH] Improve get_ip to try for real ip address --- axes/decorators.py | 48 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/axes/decorators.py b/axes/decorators.py index afc8f36..9060e46 100644 --- a/axes/decorators.py +++ b/axes/decorators.py @@ -1,4 +1,5 @@ import logging +import socket from datetime import timedelta @@ -77,9 +78,54 @@ if BEHIND_REVERSE_PROXY: log.debug('Axes is configured to be behind reverse proxy...looking for header value %s', REVERSE_PROXY_HEADER) +def is_valid_ip(ip_address): + """ Check Validity of an IP address """ + valid = True + try: + socket.inet_aton(ip_address.strip()) + except: + valid = False + return valid + + +def get_ip_address_from_request(request): + """ Makes the best attempt to get the client's real IP or return the loopback """ + PRIVATE_IPS_PREFIX = ('10.', '172.', '192.', '127.') + ip_address = '' + x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '') + if x_forwarded_for and ',' not in x_forwarded_for: + if not x_forwarded_for.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(x_forwarded_for): + ip_address = x_forwarded_for.strip() + else: + ips = [ip.strip() for ip in x_forwarded_for.split(',')] + for ip in ips: + if ip.startswith(PRIVATE_IPS_PREFIX): + continue + elif not is_valid_ip(ip): + continue + else: + ip_address = ip + break + if not ip_address: + x_real_ip = request.META.get('HTTP_X_REAL_IP', '') + if x_real_ip: + if not x_real_ip.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(x_real_ip): + ip_address = x_real_ip.strip() + if not ip_address: + remote_addr = request.META.get('REMOTE_ADDR', '') + if remote_addr: + if not remote_addr.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(remote_addr): + ip_address = remote_addr.strip() + if remote_addr.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(remote_addr): + ip_address = remote_addr.strip() + if not ip_address: + ip_address = '127.0.0.1' + return ip_address + + def get_ip(request): if not BEHIND_REVERSE_PROXY: - ip = request.META.get('REMOTE_ADDR', '') + ip = get_ip_address_from_request(request) else: ip = request.META.get(REVERSE_PROXY_HEADER, '') ip = ip.split(",", 1)[0].strip()