From 256fc969d33a848da9d71f2709e0b8226aab2bb3 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Thu, 22 Aug 2019 21:16:58 +0200 Subject: dyndns role: improve handling of IPv6 (still not supported) --- roles/dyndns/server/tasks/main.yml | 5 ++++ roles/dyndns/server/templates/dyndns.py.j2 | 41 ++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 5 deletions(-) (limited to 'roles/dyndns/server') 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 " 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") -- cgit v1.2.3