ascension

Migrate DNS zones to the GNU Name System
Log | Files | Refs | README | LICENSE

commit 72effbd4ed90c004b216e8085d59d8dd827d3328
parent 03360197bbb34602309fed8b3633a9fc4d8d1c63
Author: rexxnor <rexxnor+gnunet@brief.li>
Date:   Wed,  6 Mar 2019 20:37:53 +0100

added DNSCurve, added CIscript, build deb and manpage, improved tests

Diffstat:
M.gitignore | 5+++++
A.gitlab-ci.yml | 29+++++++++++++++++++++++++++++
Mascension/ascension.py | 62++++++++++++++++++++++++++++++++++----------------------------
Mascension/test/basic_named.conf | 4----
Mascension/test/gnunet.zone | 2++
Dascension/test/managed-keys.bind | 33---------------------------------
Dascension/test/managed-keys.bind.jnl | 0
Mascension/test/test_ascension_simple.sh | 32+++++++++++++++++++++-----------
Aascension/test/test_ascension_sophisticated.sh | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahelpers/ascension.1 | 45+++++++++++++++++++++++++++++++++++++++++++++
Ahelpers/ciscript.sh | 21+++++++++++++++++++++
Ahelpers/gnunet-installer-0.11-debian.sh | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msetup.py | 2--
13 files changed, 380 insertions(+), 78 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -96,4 +96,9 @@ ENV/ # mkdocs documentation /site .idea/ + +# bind stuff +managed-keys.bind managed-keys.bind.jnl +ascension/test/managed-keys.bind +ascension/test/managed-keys.bind.jnl diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml @@ -0,0 +1,29 @@ +--- +image: debian + +stages: + - build_deb + +run-build_deb: + stage: build_deb + script: + - apt update + - apt install -y python-all python3-stdeb git + - python3 setup.py --command-package=stdeb.command sdist_dsc + - cd deb_dist/*/ || exit + - cp ../../helpers/ascension.1 debian/ascension.1 + - echo "debian/ascension.1" > debian/python3-ascension.manpages + - dh_installman + - dpkg-buildpackage -rfakeroot -uc -us + - cd ../../ || exit + - apt install -y ./deb_dist/python3-ascension*.deb + - ascension -h + - bash helpers/gnunet-installer-0.11-debian.sh Production + - apt install -y bind9 dnsutils procps + - gnunet-arm -Esq + - cd ascension/test/ + - bash test_ascension_simple.sh + - gnunet-arm -e + artifacts: + paths: + - deb_dist/python3-ascension*.deb diff --git a/ascension/ascension.py b/ascension/ascension.py @@ -20,22 +20,24 @@ # Author rexxnor """ Usage: - ascension <domain> [-d] [-p] - ascension <domain> <port> [-d] [-p] - ascension <domain> -n <transferns> [-d] [-p] - ascension <domain> -n <transferns> <port> [-d] [-p] + ascension <domain> [-d] [-p] [-s] + ascension <domain> <port> [-d] [-p] [-s] + ascension <domain> -n <transferns> [-d] [-p] [-s] + ascension <domain> -n <transferns> <port> [-d] [-p] [-s] ascension -p | --public + ascension -s | --standalone ascension -h | --help ascension -v | --version Options: - <domain> Domain to migrate - <port> Port for zone transfer - <transferns> DNS Server that does the zone transfer - -p --public Make records public on the DHT - -d --debug Enable debugging - -h --help Show this screen. - -v --version Show version. + <domain> Domain to migrate + <port> Port for zone transfer + <transferns> DNS Server that does the zone transfer + -p --public Make records public on the DHT + -s --standalone Run ascension once + -d --debug Enable debugging + -h --help Show this screen. + -v --version Show version. """ # imports @@ -208,15 +210,6 @@ class Ascender(): # execute thing to run on item label, listofrdatasets = labelrecords - # TODO Add the not-in-bailiwick case - # subzones = label.split('.') - # elif len(subzones) > 1: - # ttl = cls.soa[1] - # cls.create_zone_hierarchy(subzones, ttl) - # label = subzones[0] - # subdomains = ".".join(subzones[1:]) - # domain = "%s.%s" % (subdomains, cls.domain) - for rdataset in listofrdatasets: for record in rdataset: rdtype = dns.rdatatype.to_text(record.rdtype) @@ -275,6 +268,21 @@ class Ascender(): taskqueue.task_done() + # Check if there is zone has already been migrated + nsrecords = cls.zone.iterate_rdatas(dns.rdatatype.NS) + # + gnspkey = list(filter(lambda record: str(record[2]).startswith('gns--pkey--'), nsrecords)) + if gnspkey: + label = str(gnspkey[0][0]) + ttl = gnspkey[0][1] + pkey = str(gnspkey[0][2]) + # TODO Check this check + if not cls.transferns in ['127.0.0.1', '::1', 'localhost']: + print("zone exists in GNS, adding it to local store") + cls.add_pkey_record_to_zone(pkey[11:], cls.domain, + label, ttl) + return + # Create one thread thread = threading.Thread(target=worker) thread.start() @@ -370,11 +378,6 @@ class Ascender(): value = value[:-1] elif rdtype == 'NS': nameserver = str(record) - if nameserver[0:2] == 'uz5': - logging.info("zone has a dnscurve record") - # TODO extract public key from NS record (dnscurve) - # encoded_pkey = nameserver[2:].split('.')[0] - # pkey = if value[-1] == ".": value = value[:-1] else: @@ -611,25 +614,25 @@ class Ascender(): :param pkey: the public key of the child zone :param domain: the name of the parent zone :param label: the label under which to add the pkey + :param ttl: the time to live the record should have """ debug = " ".join([GNUNET_NAMESTORE_COMMAND, '-z', domain, '-a', '-n', label, '-t', 'PKEY', '-V', pkey, - '-e', "%s" % ttl]) + '-e', "%ds" % ttl]) ret = sp.run([GNUNET_NAMESTORE_COMMAND, '-z', domain, '-a', '-n', label, '-t', 'PKEY', '-V', pkey, - '-e', "%s" % ttl]) + '-e', "%ds" % ttl]) logging.info("executed command: %s", debug) if ret.returncode != 0: logging.warning("failed to add PKEY record %s to %s", label, domain) - @classmethod def create_zone_hierarchy(cls, labels, ttl): """ @@ -657,6 +660,7 @@ def main(): transferns = args['<transferns>'] if args['<transferns>'] else None port = args['<port>'] if args['<port>'] else 53 flags = "p" if args.get('--public') else "n" + standalone = bool(args.get('--standalone')) # Change logging severity to debug if debug: @@ -682,6 +686,8 @@ def main(): logging.info("Finished migrating of the zone %s", ascender.domain) refresh = int(ascender.get_zone_refresh_time()) retry = int(ascender.get_zone_retry_time()) + if standalone: + return 0 if refresh == 0: logging.info("unable to refresh zone, retrying in %ds", retry) time.sleep(retry) diff --git a/ascension/test/basic_named.conf b/ascension/test/basic_named.conf @@ -8,10 +8,6 @@ options { // Add this for no IPv4: // listen-on { none; }; - allow-recursion { 127.0.0.1; }; - allow-transfer { 127.0.0.1; }; - allow-update { none; }; - version none; hostname none; server-id none; diff --git a/ascension/test/gnunet.zone b/ascension/test/gnunet.zone @@ -6,7 +6,9 @@ $TTL 3600 604800 ; Expire 3600 ) ; Negative Cache TTL @ IN NS ns1.gnunet.org. +@ IN NS gns--pkey--7h4hfww26fmdamt243dhssens2w5qevphbm9bhv54sz3cz1053ng.gnunet.org. @ IN A 127.0.0.1 +gns--pkey--7h4hfww26fmdamt243dhssens2w5qevphbm9bhv54sz3cz1053ng IN A 0.0.0.0 www IN A 127.0.0.1 owncloud IN A 127.0.0.1 nextcloud IN A 127.0.0.1 diff --git a/ascension/test/managed-keys.bind b/ascension/test/managed-keys.bind @@ -1,33 +0,0 @@ -$ORIGIN . -$TTL 0 ; 0 seconds -@ IN SOA . . ( - 24 ; serial - 0 ; refresh (0 seconds) - 0 ; retry (0 seconds) - 0 ; expire (0 seconds) - 0 ; minimum (0 seconds) - ) - KEYDATA 20181113222352 20181020181422 19700101000000 257 3 8 ( - AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQ - bSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh - /RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWA - JQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXp - oY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3 - LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGO - Yl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGc - LmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0= - ) ; KSK; alg = RSASHA256; key id = 19036 - ; next refresh: Tue, 13 Nov 2018 22:23:52 GMT - ; trusted since: Sat, 20 Oct 2018 18:14:22 GMT - KEYDATA 20181113222352 20181020181422 19700101000000 257 3 8 ( - AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTO - iW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN - 7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5 - LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8 - efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7 - pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLY - A4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws - 9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU= - ) ; KSK; alg = RSASHA256; key id = 20326 - ; next refresh: Tue, 13 Nov 2018 22:23:52 GMT - ; trusted since: Sat, 20 Oct 2018 18:14:22 GMT diff --git a/ascension/test/managed-keys.bind.jnl b/ascension/test/managed-keys.bind.jnl Binary files differ. diff --git a/ascension/test/test_ascension_simple.sh b/ascension/test/test_ascension_simple.sh @@ -12,8 +12,7 @@ # Shutdown named function cleanup { pkill named - gnunet-identity -D gnunet - gnunet-identity -D org + gnunet-identity -D gnunet.org } # Check for required packages @@ -28,6 +27,17 @@ if ! [ -x "$(command -v ascension)" ]; then exit 1 fi +if ! [ -x "$(command -v gnunet-arm)" ]; then + echo 'gnunet is not installed' >&2 + exit 1 +fi + +gnunet-arm -T 1s -I -q 2>&1 /dev/null +if [ "$?" -ne 0 ]; then + echo "The gnunet peer is not running" >&2 + exit 1 +fi + # Start named with a simple zone named -c basic_named.conf -p 5000 @@ -40,7 +50,7 @@ if [ "$?" -ne 0 ]; then fi # Let ascension run on gnunet.org test domain -ascension gnunet.org -ns 127.0.0.1 -p 5000 +ascension gnunet.org -n 127.0.0.1 -p 5000 -s -d if [ "$?" -ne 0 ]; then echo "ascension failed adding the records!" cleanup @@ -64,23 +74,23 @@ function checkfailimp { } # TESTING explicit records -gnunet-gns -t CNAME -u asdf.gnunet +gnunet-gns -t CNAME -u asdf.gnunet.org checkfailexp -gnunet-gns -t AAAA -u foo.gnunet +gnunet-gns -t AAAA -u foo.gnunet.org checkfailexp -gnunet-gns -t A -u mail.gnunet +gnunet-gns -t A -u mail.gnunet.org checkfailexp -gnunet-gns -t A -u ns1.gnunet +gnunet-gns -t A -u ns1.gnunet.org checkfailexp -gnunet-gns -t A -u ns2.gnunet +gnunet-gns -t A -u ns2.gnunet.org checkfailexp gnunet-gns -t A -u ns2.gnunet.org checkfailexp -gnunet-gns -t MX -u mail.gnunet +gnunet-gns -t MX -u mail.gnunet.org checkfailexp -gnunet-gns -t A -u nextcloud.gnunet +gnunet-gns -t A -u nextcloud.gnunet.org checkfailexp -gnunet-gns -t SOA -u @.gnunet +gnunet-gns -t SOA -u @.gnunet.org checkfailexp # cleanup if we get this far diff --git a/ascension/test/test_ascension_sophisticated.sh b/ascension/test/test_ascension_sophisticated.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Copyright (C) 2019 rexxnor +# License AGPLv3+: GNU AGPL version 3 or later <https://www.gnu.org/licenses/agpl.html> +# This is free software: you are free to change and redistribute it. +# There is NO WARRANTY, to the extent permitted by law. +# +# Returns 1 on basic error +# Returns 2 on explicit test case errors +# Returns 3 on implicit test case errors + +# Shutdown named +function cleanup { + pkill named + gnunet-identity -D gnunet.org +} + +# Check for required packages +if ! [ -x "$(command -v named)" ]; then + echo 'bind/named is not installed' >&2 + exit 1 +fi + +if ! [ -x "$(command -v ascension)" ]; then + echo 'ascension is not installed' >&2 + exit 1 +fi + +if ! [ -x "$(command -v gnunet-arm)" ]; then + echo 'gnunet is not installed' >&2 + exit 1 +fi + +gnunet-arm -T 1s -I +if [ "$?" -ne 0 ]; then + echo "The gnunet peer is not running" >&2 + exit 1 +fi + +# Get the hostname to simulate external host +myhostname=$(echo -n "$(hostname)") + +# Start named with a simple zone +named -c basic_named.conf -p 5000 + +# Check if domain resolves +nslookup gnunet.org "$myhostname" -port=5000 +if [ "$?" -ne 0 ]; then + echo "Something went wrong with named" + cleanup + exit 1 +fi + +# Let ascension run on gnunet.org test domain +ascension gnunet.org -n "$myhostname" -p 5000 -s -d +if [ "$?" -ne 0 ]; then + echo "ascension failed adding the records!" + cleanup + exit 1 +fi + +function checkfailexp { + if [ "$?" -ne 0 ]; then + echo "required record not present" + cleanup + exit 2 + fi +} + +function checkfailimp { + if [ "$?" -ne 0 ]; then + echo "implied record not present" + cleanup + exit 3 + fi +} + +# TESTING explicit records +gnunet-gns -t PKEY -u @.gnunet.org +checkfailexp + +# cleanup if we get this far +cleanup + +# finish +echo "All records added successfully!!" diff --git a/helpers/ascension.1 b/helpers/ascension.1 @@ -0,0 +1,45 @@ +.TH ASCENSION "1" "February 2019" "Ascension 0.5.0" "User Commands" +.SH NAME +Ascension \- continuous migration of DNS zones to GNS +.SH USAGE +.IP +ascension <domain> [\-d] [\-p] [\-s] +.IP +ascension <domain> <port> [\-d] [\-p] [\-s] +.IP +ascension <domain> \fB\-n\fR <transferns> [\-d] [\-p] [\-s] +.IP +ascension <domain> \fB\-n\fR <transferns> <port> [\-d] [\-p] [\-s] +.IP +ascension \fB\-p\fR | \fB\-\-public\fR +.IP +ascension \fB\-s\fR | \fB\-\-standalone\fR +.IP +ascension \fB\-h\fR | \fB\-\-help\fR +.IP +ascension \fB\-v\fR | \fB\-\-version\fR +.SH OPTIONS +.TP +<domain> +Domain to migrate +.TP +<port> +Port for zone transfer +.TP +<transferns> +DNS Server that does the zone transfer +.TP +\fB\-p\fR \fB\-\-public\fR +Make records public on the DHT +.TP +\fB\-s\fR \fB\-\-standalone\fR +Run ascension once +.TP +\fB\-d\fR \fB\-\-debug\fR +Enable debugging +.TP +\fB\-h\fR \fB\-\-help\fR +Show this screen. +.TP +\fB\-v\fR \fB\-\-version\fR +Show version. diff --git a/helpers/ciscript.sh b/helpers/ciscript.sh @@ -0,0 +1,21 @@ +# Copyright (C) 2019 rexxnor +# License AGPLv3+: GNU AGPL version 3 or later <https://www.gnu.org/licenses/agpl.html> +# This is free software: you are free to change and redistribute it. +# There is NO WARRANTY, to the extent permitted by law. +apt update +apt install -y python-all python3-stdeb git +python3 setup.py --command-package=stdeb.command sdist_dsc +cd deb_dist/*/ || exit +cp ../../helpers/ascension.1 debian/ascension.1 +echo "debian/ascension.1" > debian/python3-ascension.manpages +dh_installman +dpkg-buildpackage -rfakeroot -uc -us +cd ../../ || exit +apt install -y ./deb_dist/python3-ascension*.deb +ascension -h +bash helpers/gnunet-installer-0.11-debian.sh Production +apt install -y bind9 dnsutils procps +gnunet-arm -Esq +cd ascension/test/ +bash test_ascension_simple.sh +gnunet-arm -e diff --git a/helpers/gnunet-installer-0.11-debian.sh b/helpers/gnunet-installer-0.11-debian.sh @@ -0,0 +1,138 @@ +#!/bin/bash +# Written by Torsten Grothoff +# Licensed under GPLv3+ +# Updated by rexxnor +# SPDX-License-Identifier: GPL3.0-or-later + +export bold="\e[1m" +export dim="\e[2m" +export underlined="\e[4m" +export blink="\e[5m" +export inverted="\e[7m" +export hidden="\e[8m" +export resetall="\e[0m" #All +export resetbold="\e[21m" #Bold +export resetdim="\e[22m" #Dim +export resetunderlined="\e[24m" #Underlined +export resetblink="\e[25m" #Blink +export resetinverted="\e[27m" #Inverted +export resethidden="\e[28m" #Hidden +export defaultcolor="\e[39m" +export black="\e[30m" +export red="\e[31m" +export green="\e[32m" +export yellow="\e[33m" +export blue="\e[34m" +export magenta="\e[35m" +export cyan="\e[36m" +export lightgray="\e[37m" +export darkgray="\e[90m" +export lightred="\e[91m" +export lightgreen="\e[92m" +export lightyellow="\e[93m" +export lightblue="\e[94m" +export lightmagenta="\e[95m" +export lightcyan="\e[96m" +export white="\e[97m" +export default +export blackbg="\e[30m" +export redbg="\e[31m" +export greenbg="\e[42m" +export yellowbg="\e[43m" +export bluebg="\e[44m" +export magentabg="\e[45m" +export cyanbg="\e[46m" +export lightgraybg="\e[47m" +export darkgraybg="\e[100m" +export lightredbg="\e[101m" +export lightgreenbg="\e[102m" +export lightyellowbg="\e[103m" +export lightbluebg="\e[104m" +export lightmagentabg="\e[105m" +export lightcyanbg="\e[106m" +export whitebg="\e[107m" +function errorhandler { + errorcode=$? + if [[ "$errorcode" != "0" ]]; then + echo "An Error has Occured [Error Code: $errorcode]." + if [[ "$errorcode" == "127" ]]; then + echo "Potential Fatal Error; Exiting" + exit 127 + fi + fi +} +if [[ "$UID" -ne 0 ]]; then + if [[ "$1" == "--ignore-root-check" ]]; then + echo "Warning: You are not running this file as root; As such, this installer will probabally not work. Expect Errors" + else + echo "You must run this program as root that way it can work\nIf you are sure you want to continue without root[will most likely not work]; run this file with --ignore-root-check" + exit 1 + fi +fi +apt install --yes --fix-missing git libtool autoconf autopoint build-essential libgcrypt-dev libidn11-dev zlib1g-dev libunistring-dev libglpk-dev miniupnpc libextractor-dev libjansson-dev libcurl4-gnutls-dev libsqlite3-dev openssl libnss3-tools +apt install --yes git libtool autoconf autopoint \ +build-essential libgcrypt-dev libidn11-dev zlib1g-dev \ +libunistring-dev libglpk-dev miniupnpc libextractor-dev \ +libjansson-dev libcurl4-gnutls-dev libsqlite3-dev openssl \ +libnss3-tools libmicrohttpd-dev libgnutls28-dev libp11-kit-dev libp11-kit0 dialog +errorhandler +mkdir ~/gnunet_installation +cd ~/gnunet_installation +git clone --depth 1 https://gnunet.org/git/gnunet.git +git clone --depth 1 https://gnunet.org/git/libmicrohttpd.git +cd ~/gnunet_installation/libmicrohttpd +autoreconf -fi +apt install -y libgnutls28-dev +./configure --disable-doc --prefix=/opt/libmicrohttpd +make -j$(nproc || echo -n 1) +make install +# +if [[ "$1" == "Production" || "$1" == "Development" ]]; then + echo "$1" > ./result.txt +fi + +if [[ ! -f ./result.txt ]]; then + dialog --menu Production\ Or\ Developement? -1 -1 2 Production 1 Development 2 2> ./result.txt +fi +if [[ `cat ./result.txt` == Production ]]; then + cd ~/gnunet_installation/gnunet + ./bootstrap + export GNUNET_PREFIX=/usr + ./configure --prefix=$GNUNET_PREFIX --disable-documentation --with-microhttpd=/opt/libmicrohttpd + addgroup gnunetdns + adduser --system --group --disabled-login --home /var/lib/gnunet gnunet + make -j$(nproc || echo -n 1) + make install +else + if [[ `cat ./result.txt` == Developement ]]; then + cd ~/gnunet_installation/gnunet + ./bootstrap + export GNUNET_PREFIX=/usr + export CFLAGS="-g -Wall -O0" + ./configure --prefix=$GNUNET_PREFIX --disable-documentation --enable-logging=verbose --with-microhttpd=/opt/libmicrohttpd + make -j$(nproc || echo -n 1) + make install + fi +fi +rm ~/gnunet_installation/libmicrohttpd/result.txt +touch ~/.config/gnunet.conf +echo -e "Associating ${green}gnunet://${resetall} with gnunet" +for n in `cat /etc/passwd | awk '{print $6}' FS=:`; do + dir=`echo $n/.local/share/applications` + echo "[Added Associations] + x-scheme-handler/gnunet=gnunet.desktop" >> $dir/mimeapps.list + echo "[Desktop Entry] +Version=1.0 +Type=Application +Exec=sh -c \"gnunet-uri $@\" +Icon=/usr/share/gnunet/gnunet-logo-color.png +StartupNotify=false +Terminal=false +Categories=Internet +MimeType=x-scheme-handler/gnunet +Name=GNUNet +Comment=GNUNet Protocol Executer +GenericName=GNUNet Protocol Executer[Created By Gnunet Installer; by TStudios]" > $dir/gnunet.desktop + chmod 644 gnunet.desktop +done +echo -e "To start GNUNet Services: ${green}gnunet-arm -s${resetall}\nTo view GNUNet Services: ${green}gnunet-arm -I${resetall}\nTo Stop GNUNet Services: ${green}gnunet-arm -e${resetall}\n\n${red}NOTE: This GNUNet Installation Might only be available as ${green}ROOT${resetall}\n${lightgreen}For more info: https://gnunet.org/en/tutorial-debian9.html${resetall}" diff --git a/setup.py b/setup.py @@ -45,8 +45,6 @@ setuptools.setup( }, install_requires=[ 'coverage', - 'daemon', - 'daemonize', 'dnspython', 'docopt', 'mock',