summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--roles/dyndns/server/tasks/main.yml5
-rwxr-xr-xroles/dyndns/server/templates/dyndns.py.j241
2 files changed, 41 insertions, 5 deletions
diff --git a/roles/dyndns/server/tasks/main.yml b/roles/dyndns/server/tasks/main.yml
index 304a2473..06ef6c47 100644
--- a/roles/dyndns/server/tasks/main.yml
+++ b/roles/dyndns/server/tasks/main.yml
@@ -19,3 +19,8 @@
src: dyndns.py.j2
dest: /usr/local/bin/dyndns.py
mode: 0755
+
+- name: install script dependency
+ apt:
+ name: python-easyzone
+ state: present
diff --git a/roles/dyndns/server/templates/dyndns.py.j2 b/roles/dyndns/server/templates/dyndns.py.j2
index fbbd4f1a..eb5e7ab5 100755
--- a/roles/dyndns/server/templates/dyndns.py.j2
+++ b/roles/dyndns/server/templates/dyndns.py.j2
@@ -33,13 +33,37 @@ import re
domain = '{{ dyndns.domain }}.'
zonefile = '{{ dyndns.zone_file }}'
rndc = '/usr/sbin/rndc'
-###
+
+#
+# this is from: https://gist.github.com/dfee/6ed3a4b05cfe7a6faf40a2102408d5d8
+IPV4SEG = r'(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])'
+IPV4ADDR = r'(?:(?:' + IPV4SEG + r'\.){3,3}' + IPV4SEG + r')'
+IPV6SEG = r'(?:(?:[0-9a-fA-F]){1,4})'
+IPV6GROUPS = (
+ r'(?:' + IPV6SEG + r':){7,7}' + IPV6SEG, # 1:2:3:4:5:6:7:8
+ r'(?:' + IPV6SEG + r':){1,7}:', # 1:: 1:2:3:4:5:6:7::
+ r'(?:' + IPV6SEG + r':){1,6}:' + IPV6SEG, # 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8
+ r'(?:' + IPV6SEG + r':){1,5}(?::' + IPV6SEG + r'){1,2}', # 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8
+ r'(?:' + IPV6SEG + r':){1,4}(?::' + IPV6SEG + r'){1,3}', # 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8
+ r'(?:' + IPV6SEG + r':){1,3}(?::' + IPV6SEG + r'){1,4}', # 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8
+ r'(?:' + IPV6SEG + r':){1,2}(?::' + IPV6SEG + r'){1,5}', # 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8
+ IPV6SEG + r':(?:(?::' + IPV6SEG + r'){1,6})', # 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8
+ r':(?:(?::' + IPV6SEG + r'){1,7}|:)', # ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::
+ r'fe80:(?::' + IPV6SEG + r'){0,4}%[0-9a-zA-Z]{1,}', # fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index)
+ r'::(?:ffff(?::0{1,4}){0,1}:){0,1}[^\s:]' + IPV4ADDR,
+ # ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
+ r'(?:' + IPV6SEG + r':){1,4}:[^\s:]' + IPV4ADDR, # 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
+)
+IPV6ADDR = '|'.join(['(?:{})'.format(g) for g in IPV6GROUPS[::-1]]) # Reverse rows for greedy match
+#
+
+#
# add this to the authorized key file of a system user
# the user needs to be a member of the bind group and must
# have write permissions to the zone file
# no-agent-forwarding,no-port-forwarding,no-pty,no-X11-forwarding,no-user-rc,command="/usr/local/bin/dyndns.py <allowed names>" ssh-rsa ...
-###
+#
if ('SSH_CLIENT' in os.environ) and ('SSH_ORIGINAL_COMMAND' in os.environ):
sshclient = os.environ['SSH_CLIENT']
@@ -54,14 +78,21 @@ if name not in set(sys.argv[1:]):
sys.exit(1)
ip = sshclient.split()[0]
-if not re.match(r'^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$', ip):
- sys.stdout.write("Error: not a valid IPv4 address\n")
+record_type = ''
+if re.match(IPV4ADDR, ip):
+ record_type = 'A'
+if re.match(IPV6ADDR, ip):
+# record_type = 'AAAA'
+ sys.stdout.write("Error: Sorry no IPv6 support yet!\n")
+ sys.exit(1)
+if record_type == '':
+ sys.stdout.write("Error: not a valid IPv4/IPv6 address\n")
sys.exit(1)
name = name + '.' + domain
zone = easyzone.zone_from_file(domain, zonefile)
zone.add_name(name)
-records = zone.names[name].records('A', create=True, ttl=60)
+records = zone.names[name].records(record_type, create=True, ttl=60)
for item in records.get_items():
if item == ip:
sys.stdout.write("Ok: nothing changed\n")