Merge branch 'master' of github.com:asmaps/nsupdate.info

This commit is contained in:
Fabian Faessler 2013-09-29 22:56:25 +02:00
commit 5b02e52794
5 changed files with 188 additions and 17 deletions

View File

@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'Domain.nameserver_ip'
db.add_column(u'main_domain', 'nameserver_ip',
self.gf('django.db.models.fields.IPAddressField')(default='85.10.192.104', max_length=15),
keep_default=False)
# Adding field 'Domain.nameserver_update_key'
db.add_column(u'main_domain', 'nameserver_update_key',
self.gf('django.db.models.fields.CharField')(default='YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYQ==', max_length=256),
keep_default=False)
def backwards(self, orm):
# Deleting field 'Domain.nameserver_ip'
db.delete_column(u'main_domain', 'nameserver_ip')
# Deleting field 'Domain.nameserver_update_key'
db.delete_column(u'main_domain', 'nameserver_update_key')
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'main.blacklisteddomain': {
'Meta': {'object_name': 'BlacklistedDomain'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'domain': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_update': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
u'main.domain': {
'Meta': {'object_name': 'Domain'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'domain': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_update': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'nameserver_ip': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),
'nameserver_update_key': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'main.host': {
'Meta': {'unique_together': "(('subdomain', 'domain'),)", 'object_name': 'Host'},
'comment': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts'", 'to': u"orm['auth.User']"}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['main.Domain']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_api_update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'last_update': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'subdomain': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
'update_secret': ('django.db.models.fields.CharField', [], {'max_length': '256'})
}
}
complete_apps = ['main']

View File

@ -34,6 +34,9 @@ def domain_blacklist_validator(value):
class Domain(models.Model):
domain = models.CharField(max_length=256, unique=True)
nameserver_ip = models.IPAddressField(max_length=256,
help_text="An IP where the nsupdates for this domain will be sent to")
nameserver_update_key = models.CharField(max_length=256)
last_update = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)

View File

@ -2,12 +2,20 @@
{% load bootstrap %}
{% block content %}
<div class="row">
<h3>Host Secret Generated <small><a href="{% url 'overview' %}"><i class="icon-double-angle-left"></i> back to overview</a></small></h3>
<p>New secret generated for you. We store it hashed, so save it now, or you have to generate a new one again.</p>
<p>secret: <b>{{ update_secret }}</b></p>
<div class="row">
<div class="col-lg-4">
<div class="well">
<h3>Host Secret Generated <small><br>
<a href="{% url 'overview' %}"><i class="icon-double-angle-left"></i> back to overview</a></small></h3>
<p>New secret generated for you. We store it hashed, so save it now, or you have to generate a new one again. Everytime you visit this page a new secret will be generated and the old one becomes invalid.</p>
<p>Secret: <b>{{ update_secret }}</b></p>
</div>
</div>
<div class="col-lg-8">
<div class="well">
<h3>How to configure your router?</h3>
{% include "main/includes/tabbed_router_configuration.html" with host=object %}
</div>
</div>
</div>
{% endblock %}

View File

@ -6,8 +6,8 @@
<div class="row">
<div class="col-lg-4">
<h3>Edit Horst <small><a href="{% url 'overview' %}"><i class="icon-double-angle-left"></i> back to overview</a></small></h3>
<p>You can only change the comment. If you want to have another domain name, you have to delete this host and create a new one.</p>
<h3>Edit Host <small><a href="{% url 'overview' %}"><i class="icon-double-angle-left"></i> back to overview</a></small></h3>
<p>You can only change the comment. If you want to have another host name, you have to delete this host and create a new one.</p>
<form method="post" action="">
{% csrf_token %}
{{ form|bootstrap }}
@ -16,15 +16,14 @@
</div>
<div class="col-lg-4">
<h3>Generate new secret</h3>
<p>We store your update secret hashed, so if you forgot or lost it you have to create a new one.</p>
<p>We store your update secret salted and hashed, so if you forget or lose it you will have to create a new one.</p>
<form action="{% url 'generate_secret_view' host.pk %}" method="get">
<button type="submit" class="btn btn-primary">Generate New</button>
</form>
</div>
<div class="col-lg-4">
<h3>Update Nameserver Entry</h3>
<p>Usually you configure your router to follow the dyndns protocol. But if you know what you are doing, and you want to update it by hand, you can do it here.</p>
<p>Usually you configure your router to follow the dyndns2 protocol. But if you know what you are doing, and you want to update it by hand, you can do it here.</p>
<form method="get" action="{% url 'nic_update_authorized' %}">
<input type="hidden" name="hostname" value="{{ host.get_fqdn }}">
<div class="form-group">
@ -41,17 +40,17 @@
<div class="row">
<div class="col-lg-6">
<h3>General Information</h3>
<p>We try to get your IP addresses through a trick. We host two fake images on a IPv4 and IPv6 domain and we can associate those with your session. If we find an IP address, we will update this information accordingly. This allows us to get your IPv4 address even when you are using your IPv6 and vice versa.</p>
<b>your IPv4:</b> <span class="ipv4adr">{{ request.session.ipv4 }}</span> <br>
<b>your IPv6:</b> <span class="ipv6adr">{{ request.session.ipv6 }}</span>
<p>We try to get your IP addresses through a trick. We host two fake images on a IPv4-only and a IPv6-only host and we can associate those with your session.
If we find an IP address, we will update this information accordingly. This allows us to get your IPv4 address even when you are using IPv6 and vice versa.</p>
<b>Your IPv4:</b> <span class="ipv4adr">{{ request.session.ipv4 }}</span> <br>
<b>Your IPv6:</b> <span class="ipv6adr">{{ request.session.ipv6 }}</span>
</div>
<div class="col-lg-6">
<h3>Host Information</h3>
<p>This information comes directly from the name server and shows the current IPs set for your domain.</p>
<p>This information comes directly from the name server and shows the current IPs set for your host.</p>
<b>Host IPv4:</b> <span class="ipv4adr">{{ host.getIPv4 }}</span> <br>
<b>Host IPv6:</b> <span class="ipv6adr">{{ host.getIPv6 }}</span>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,62 @@
<ul class="nav nav-tabs" id="myTab">
<li class="active"><a href="#generic" data-toggle="tab">Generic</a></li>
<li><a href="#avm" data-toggle="tab">AVM Fritz!Box</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="generic">
<h4>Generic configuration hints</h4>
<hr>
Your router/script needs to call the following url for IPv4-Updates:
<div class="well well-sm">
<a href="http://{{ host.get_fqdn|default:"&lt;your fqdn&gt;" }}:{{ update_secret|default:"&lt;your secret&gt;" }}@ipv4.nsupdate.info/nic/update">http://{{ host.get_fqdn|default:"&lt;your fqdn&gt;" }}:{{ update_secret|default:"&lt;your secret&gt;" }}@ipv4.nsupdate.info/nic/update</a>
</div>
For IPv6-Updates:
<div class="well well-sm">
<a href="http://{{ host.get_fqdn|default:'&lt;your fqdn&gt;' }}:{{ update_secret|default:'&lt;your secret&gt;' }}@ipv6.nsupdate.info/nic/update">http://{{ host.get_fqdn|default:'&lt;your fqdn&gt;' }}:{{ update_secret|default:'&lt;your secret&gt;' }}@ipv6.nsupdate.info/nic/update</a>
</div>
The IPs will be determined automatically.
<hr>
Briefly your router/script has to do the following steps:
<ul>
<li>visit http://ipv4.nsupdate.info/nic/update (to update A (IPv4) record)</li>
<li>visit http://ipv6.nsupdate.info/nic/update (to update AAAA (IPv6) record)</li>
<li>Do HTTP BasicAuth with:
<ul>
<li>Username: {{ host.get_fqdn|default:"&lt;your fqdn&gt;" }}</li>
<li>Password: {{ update_secret|default:"&lt;your secret&gt;" }}</li>
</ul>
</li>
<li>The response will look like this:
<ul>
<li>"good &lt;your fqdn&gt;" <i class="icon-long-arrow-right"></i> new IP accepted</li>
<li>"nochg &lt;your fqdn&gt;" <i class="icon-long-arrow-right"></i> IP accepted, but did not change since last update</li>
<li>Code 401: Authorization Required <i class="icon-long-arrow-right"></i> Incorrect or no authentication data</li>
</ul>
</ul>
</div>
<div class="tab-pane" id="avm">
<h4>Fritz!Box 7390 (and maybe others):</h4>
<hr>
<h5>Go to:</h5>
<div class="well well-sm">
Internet <i class="icon-long-arrow-right"></i>
Permit Access <i class="icon-long-arrow-right"></i>
Dynamic DNS
</div>
<h5>Enter the following data</h5>
<table class="table">
<thead><th>Setting</th><th>Value</th></thead>
<tr><td>Dynamic DNS provider</td><td>Custom</td></tr>
<tr><td>Update-URL</td><td>http://nsupdate.info/nic/update</td></tr>
<tr><td>Domain Name</td><td>{{ host.get_fqdn|default:"&lt;your fqdn&gt;" }}</td></tr>
<tr><td>User name</td><td>{{ host.get_fqdn|default:"&lt;your fqdn&gt;" }}</td></tr>
<tr><td>Password</td><td>{{ update_secret|default:"&lt;your secret&gt;" }}</td></tr>
</table>
<h5>If you also have IPv6 (Dual Stack)</h5>
Set Update-URL to the following (two links, separated by space)
<div class="well well-sm">
http://ipv4.nsupdate.info/nic/update http://ipv6.nsupdate.info/nic/update
</div>
</div>
</div>