Handle IPv4-mapped IPv6 addresses
Some reverse proxy configurations pass REMOTE_ADDR as a IPv4-mapped IPv6 address when listening on a IPv6 socket. This patch converts such a mapped address into a IPv4 address at all usages of REMOTE_ADDR. It handles both, the ::ffff:192.0.2.128 format as well as the deprecated ::192.0.2.128 format.
This commit is contained in:
parent
f47af7998f
commit
5e637b14c9
@ -22,6 +22,7 @@ from ..utils import log, ddns_client
|
||||
from ..main.models import Host
|
||||
from ..main.dnstools import (FQDN, update, delete, check_ip, put_ip_into_session,
|
||||
SameIpError, DnsUpdateError, NameServerNotAvailable)
|
||||
from ..main.iptools import normalize_ip
|
||||
|
||||
|
||||
def Response(content):
|
||||
@ -44,7 +45,7 @@ def myip_view(request, logger=None):
|
||||
"""
|
||||
# Note: keeping this as a function-based view, as it is frequently used -
|
||||
# maybe it is slightly more efficient than class-based.
|
||||
ipaddr = request.META['REMOTE_ADDR']
|
||||
ipaddr = normalize_ip(request.META['REMOTE_ADDR'])
|
||||
logger.debug("detected remote ip address: %s" % ipaddr)
|
||||
return Response(ipaddr)
|
||||
|
||||
@ -64,7 +65,7 @@ class DetectIpView(View):
|
||||
# so the session cookie is not received here - thus we access it via
|
||||
# the sessionid:
|
||||
s = SessionStore(session_key=sessionid)
|
||||
ipaddr = request.META['REMOTE_ADDR']
|
||||
ipaddr = normalize_ip(request.META['REMOTE_ADDR'])
|
||||
# as this is NOT the session automatically established and
|
||||
# also saved by the framework, we need to use save=True here
|
||||
put_ip_into_session(s, ipaddr, save=True)
|
||||
@ -225,7 +226,7 @@ class NicUpdateView(View):
|
||||
return Response('badagent')
|
||||
ipaddr = request.GET.get('myip')
|
||||
if not ipaddr: # None or ''
|
||||
ipaddr = request.META.get('REMOTE_ADDR')
|
||||
ipaddr = normalize_ip(request.META.get('REMOTE_ADDR'))
|
||||
secure = request.is_secure()
|
||||
if delete:
|
||||
return _delete(host, ipaddr, secure, logger=logger)
|
||||
@ -283,7 +284,7 @@ class AuthorizedNicUpdateView(View):
|
||||
# and logged-in usage - thus misbehaved user agents are no problem.
|
||||
ipaddr = request.GET.get('myip')
|
||||
if not ipaddr: # None or empty string
|
||||
ipaddr = request.META.get('REMOTE_ADDR')
|
||||
ipaddr = normalize_ip(request.META.get('REMOTE_ADDR'))
|
||||
secure = request.is_secure()
|
||||
if delete:
|
||||
return _delete(host, ipaddr, secure, logger=logger)
|
||||
|
@ -10,6 +10,7 @@ logger = logging.getLogger(__name__)
|
||||
import time
|
||||
|
||||
from .main.dnstools import put_ip_into_session
|
||||
from .main.iptools import normalize_ip
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
@ -36,7 +37,7 @@ def update_ips(request):
|
||||
s = request.session
|
||||
t_now = int(time.time())
|
||||
# update and keep fresh using info from the request we have anyway:
|
||||
ipaddr = request.META['REMOTE_ADDR']
|
||||
ipaddr = normalize_ip(request.META['REMOTE_ADDR'])
|
||||
put_ip_into_session(s, ipaddr, max_age=MAX_IP_AGE / 2)
|
||||
# remove stale data to not show outdated IPs (e.g. after losing IPv6 connectivity):
|
||||
for key in ['ipv4', 'ipv6', ]:
|
||||
|
17
nsupdate/main/iptools.py
Normal file
17
nsupdate/main/iptools.py
Normal file
@ -0,0 +1,17 @@
|
||||
"""
|
||||
Misc. IP tools: normalize, handle mapped addresses
|
||||
"""
|
||||
|
||||
from netaddr import IPAddress
|
||||
|
||||
def normalize_ip(ipaddr):
|
||||
ipaddr = normalize_mapped_address(ipaddr)
|
||||
return ipaddr
|
||||
|
||||
def normalize_mapped_address(ipaddr):
|
||||
ipaddr = IPAddress(ipaddr)
|
||||
|
||||
if ipaddr.is_ipv4_compat() or ipaddr.is_ipv4_mapped():
|
||||
ipaddr = ipaddr.ipv4()
|
||||
|
||||
return str(ipaddr)
|
@ -19,6 +19,7 @@ from django.core.exceptions import PermissionDenied
|
||||
from django.utils.timezone import now
|
||||
|
||||
from . import dnstools
|
||||
from .iptools import normalize_ip
|
||||
|
||||
from .forms import (CreateHostForm, EditHostForm, CreateRelatedHostForm, EditRelatedHostForm,
|
||||
CreateDomainForm, EditDomainForm, CreateUpdaterHostConfigForm, EditUpdaterHostConfigForm)
|
||||
@ -210,7 +211,7 @@ class AddHostView(CreateView):
|
||||
def form_valid(self, form):
|
||||
self.object = form.save(commit=False)
|
||||
try:
|
||||
dnstools.add(self.object.get_fqdn(), self.request.META['REMOTE_ADDR'])
|
||||
dnstools.add(self.object.get_fqdn(), normalize_ip(self.request.META['REMOTE_ADDR']))
|
||||
except dnstools.Timeout:
|
||||
success, level, msg = False, messages.ERROR, 'Timeout - communicating to name server failed.'
|
||||
except dnstools.NameServerNotAvailable:
|
||||
@ -265,7 +266,7 @@ class HostView(UpdateView):
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
context = super(HostView, self).get_context_data(*args, **kwargs)
|
||||
context['nav_overview'] = True
|
||||
context['remote_addr'] = self.request.META['REMOTE_ADDR']
|
||||
context['remote_addr'] = normalize_ip(self.request.META['REMOTE_ADDR'])
|
||||
return context
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user