import re import socket from django.conf import settings from django.http import HttpResponse def is_valid_ipv6(ip_address): try: socket.inet_pton(socket.AF_INET6, ip_address) return True except socket.error: return False def is_ipv6_exempt(path): return any(re.match(m, path) for m in settings.IPV6_EXEMPT_URLS) def block_ipv4(get_response): ''' block IPv4 requests except if the url is in IPV6_EXEMPT_URLS''' def middleware(request): if getattr(settings, 'DISABLE_IPV4_BLOCK', False): return get_response(request) path = request.path_info.lstrip('/') real_ip_headers = ['HTTP_X_REAL_IP', 'REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR'] client_ip = None for header in real_ip_headers: client_ip = request.META.get(header) if client_ip: break if is_valid_ipv6(client_ip) or is_ipv6_exempt(path): return get_response(request) else: return HttpResponse('Sorry, only reachable by IPv6') return middleware