Merge branch 'master' of github.com:asmaps/nsupdate.info
This commit is contained in:
commit
3e87efa7e7
@ -6,8 +6,8 @@ logger = logging.getLogger(__name__)
|
|||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.hashers import check_password
|
from django.contrib.auth.hashers import check_password
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
from main.forms import *
|
|
||||||
from main.models import Host
|
from main.models import Host
|
||||||
import dns.inet
|
import dns.inet
|
||||||
import os
|
import os
|
||||||
@ -19,12 +19,13 @@ def MyIpView(request):
|
|||||||
return HttpResponse(request.META['REMOTE_ADDR'], content_type="text/plain")
|
return HttpResponse(request.META['REMOTE_ADDR'], content_type="text/plain")
|
||||||
|
|
||||||
|
|
||||||
def UpdateIpView(request):
|
def DetectIpView(request):
|
||||||
ipaddr = request.META['REMOTE_ADDR']
|
ipaddr = request.META['REMOTE_ADDR']
|
||||||
af = dns.inet.af_for_address(ipaddr)
|
af = dns.inet.af_for_address(ipaddr)
|
||||||
key = 'ipv4' if af == dns.inet.AF_INET else 'ipv6'
|
key = 'ipv4' if af == dns.inet.AF_INET else 'ipv6'
|
||||||
request.session[key] = ipaddr
|
request.session[key] = ipaddr
|
||||||
image_data = open(os.path.join(settings.STATIC_ROOT, "1px.gif"), "rb").read()
|
with open(os.path.join(settings.STATIC_ROOT, "1px.gif"), "rb") as f:
|
||||||
|
image_data = f.read()
|
||||||
return HttpResponse(image_data, mimetype="image/png")
|
return HttpResponse(image_data, mimetype="image/png")
|
||||||
|
|
||||||
|
|
||||||
@ -57,7 +58,7 @@ def basic_authenticate(auth):
|
|||||||
return username, password
|
return username, password
|
||||||
|
|
||||||
|
|
||||||
def check_auth(username, password):
|
def check_api_auth(username, password):
|
||||||
"""
|
"""
|
||||||
Check username and password against our database.
|
Check username and password against our database.
|
||||||
|
|
||||||
@ -77,6 +78,24 @@ def check_auth(username, password):
|
|||||||
return check_password(password, password_hash)
|
return check_password(password, password_hash)
|
||||||
|
|
||||||
|
|
||||||
|
def check_session_auth(user, hostname):
|
||||||
|
"""
|
||||||
|
Check our database whether the hostname is owned by the user.
|
||||||
|
|
||||||
|
:param user: django user object
|
||||||
|
:param hostname: fqdn
|
||||||
|
:return: True if hostname is owned by this user, False otherwise.
|
||||||
|
"""
|
||||||
|
hosts = Host.objects.filter(fqdn=hostname, created_by=user)
|
||||||
|
num_hosts = len(hosts)
|
||||||
|
if num_hosts == 0:
|
||||||
|
return False
|
||||||
|
if num_hosts > 1:
|
||||||
|
logging.error("fqdn %s has multiple entries" % fqdn)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def Response(content):
|
def Response(content):
|
||||||
return HttpResponse(content, content_type='text/plain')
|
return HttpResponse(content, content_type='text/plain')
|
||||||
|
|
||||||
@ -106,7 +125,7 @@ def NicUpdateView(request):
|
|||||||
logger.warning('%s - received no auth' % (hostname, ))
|
logger.warning('%s - received no auth' % (hostname, ))
|
||||||
return basic_challenge("authenticate to update DNS", 'noauth')
|
return basic_challenge("authenticate to update DNS", 'noauth')
|
||||||
username, password = basic_authenticate(auth)
|
username, password = basic_authenticate(auth)
|
||||||
if not check_auth(username, password):
|
if not check_api_auth(username, password):
|
||||||
logger.info('%s - received bad credentials, username: %s' % (hostname, username, ))
|
logger.info('%s - received bad credentials, username: %s' % (hostname, username, ))
|
||||||
return basic_challenge("authenticate to update DNS", 'badauth')
|
return basic_challenge("authenticate to update DNS", 'badauth')
|
||||||
if hostname is None:
|
if hostname is None:
|
||||||
@ -119,6 +138,32 @@ def NicUpdateView(request):
|
|||||||
if agent in settings.BAD_AGENTS:
|
if agent in settings.BAD_AGENTS:
|
||||||
logger.info('%s - received update from bad user agent %s' % (hostname, agent, ))
|
logger.info('%s - received update from bad user agent %s' % (hostname, agent, ))
|
||||||
return Response('badagent')
|
return Response('badagent')
|
||||||
|
return _update(hostname, ipaddr)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def AuthorizedNicUpdateView(request):
|
||||||
|
"""
|
||||||
|
similar to NicUpdateView, but the client is not a router or other dyndns client,
|
||||||
|
but the admin browser who is currently logged into the nsupdate.info site.
|
||||||
|
|
||||||
|
Example URLs:
|
||||||
|
|
||||||
|
https://supdate.info/nic/update?hostname=fqdn&myip=1.2.3.4
|
||||||
|
"""
|
||||||
|
hostname = request.GET.get('hostname')
|
||||||
|
if hostname is None:
|
||||||
|
return Response('nohost')
|
||||||
|
if not check_session_auth(request.user, hostname):
|
||||||
|
logger.info('%s - is not owned by user: %s' % (hostname, request.user.username, ))
|
||||||
|
return Response('nohost')
|
||||||
|
ipaddr = request.GET.get('myip')
|
||||||
|
if ipaddr is None:
|
||||||
|
ipaddr = request.META.get('REMOTE_ADDR')
|
||||||
|
return _update(hostname, ipaddr)
|
||||||
|
|
||||||
|
|
||||||
|
def _update(hostname, ipaddr):
|
||||||
ipaddr = str(ipaddr) # XXX bug in dnspython: crashes if ipaddr is unicode, wants a str!
|
ipaddr = str(ipaddr) # XXX bug in dnspython: crashes if ipaddr is unicode, wants a str!
|
||||||
try:
|
try:
|
||||||
update(hostname, ipaddr)
|
update(hostname, ipaddr)
|
||||||
|
@ -21,6 +21,15 @@ class SameIpError(ValueError):
|
|||||||
|
|
||||||
|
|
||||||
def update(fqdn, ipaddr, ttl=60):
|
def update(fqdn, ipaddr, ttl=60):
|
||||||
|
"""
|
||||||
|
intelligent dns updater - first does a lookup on the master server to find
|
||||||
|
the current ip and only sends a dynamic update if we have a different ip.
|
||||||
|
|
||||||
|
:param fqdn: fully qualified domain name (str)
|
||||||
|
:param ipaddr: new ip address
|
||||||
|
:param ttl: time to live, default 60s (int)
|
||||||
|
:raises: SameIpError if new and old IP is the same
|
||||||
|
"""
|
||||||
af = dns.inet.af_for_address(ipaddr)
|
af = dns.inet.af_for_address(ipaddr)
|
||||||
rdtype = 'A' if af == dns.inet.AF_INET else 'AAAA'
|
rdtype = 'A' if af == dns.inet.AF_INET else 'AAAA'
|
||||||
try:
|
try:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from django.conf.urls import patterns, include, url
|
from django.conf.urls import patterns, include, url
|
||||||
from main.views import HomeView, OverviewView, HostView, DeleteHostView
|
from main.views import HomeView, OverviewView, HostView, DeleteHostView
|
||||||
from api.views import MyIpView, UpdateIpView, NicUpdateView
|
from api.views import MyIpView, DetectIpView, NicUpdateView, AuthorizedNicUpdateView
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns(
|
urlpatterns = patterns(
|
||||||
@ -10,6 +10,7 @@ urlpatterns = patterns(
|
|||||||
url(r'^host/(?P<pk>\d+)/$', HostView.as_view(), name='host_view'),
|
url(r'^host/(?P<pk>\d+)/$', HostView.as_view(), name='host_view'),
|
||||||
url(r'^host/(?P<pk>\d+)/delete/$', DeleteHostView.as_view(), name='delete_host'),
|
url(r'^host/(?P<pk>\d+)/delete/$', DeleteHostView.as_view(), name='delete_host'),
|
||||||
url(r'^myip$', MyIpView),
|
url(r'^myip$', MyIpView),
|
||||||
url(r'^updateip$', UpdateIpView),
|
url(r'^detectip/$', DetectIpView),
|
||||||
url(r'^nic/update$', NicUpdateView),
|
url(r'^nic/update$', NicUpdateView),
|
||||||
|
url(r'^nic/update_authorized$', AuthorizedNicUpdateView),
|
||||||
)
|
)
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" href="{% url 'home' %}">nsupdate.info</a>
|
<a class="navbar-brand" href="{% url 'home' %}"><span style="color: #00ba00">⬥</span> nsupdate.info</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
@ -68,7 +68,7 @@
|
|||||||
<div class="row" style="background-color: #DDDDDD">
|
<div class="row" style="background-color: #DDDDDD">
|
||||||
<div class="col-sm-4" style="text-align: center">
|
<div class="col-sm-4" style="text-align: center">
|
||||||
<h1><i class="icon-globe icon-4x"></i></h1>
|
<h1><i class="icon-globe icon-4x"></i></h1>
|
||||||
<h3>World wide web</h3>
|
<h3>World Wide Web</h3>
|
||||||
<p>
|
<p>
|
||||||
nsupdate.info is a free and <a href="https://github.com/asmaps/nsupdate.info">open-source</a> dynamic DNS service with IPv4 and IPv6 support.
|
nsupdate.info is a free and <a href="https://github.com/asmaps/nsupdate.info">open-source</a> dynamic DNS service with IPv4 and IPv6 support.
|
||||||
</p>
|
</p>
|
||||||
@ -77,7 +77,7 @@
|
|||||||
<h1><i class="icon-cogs icon-4x"></i></h1>
|
<h1><i class="icon-cogs icon-4x"></i></h1>
|
||||||
<h3>Awesomeness</h3>
|
<h3>Awesomeness</h3>
|
||||||
<p>
|
<p>
|
||||||
Powered by python, the magical pony django and a stupid three columned icon landing page.
|
Powered by python, the magical django pony and a stupid three columned icon landing page.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4" style="text-align: center">
|
<div class="col-sm-4" style="text-align: center">
|
||||||
@ -124,8 +124,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: none">
|
<div style="display: none">
|
||||||
<img src="//{{ WWW_IPV4_HOST }}/updateip" />
|
<img src="//{{ WWW_IPV4_HOST }}/detectip" />
|
||||||
<img src="//{{ WWW_IPV6_HOST }}/updateip" />
|
<img src="//{{ WWW_IPV6_HOST }}/detectip" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
|
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user