{"id":255457,"date":"2016-04-08T22:02:56","date_gmt":"2016-04-08T14:02:56","guid":{"rendered":"http:\/\/blog.zhenglei.net\/?p=255457"},"modified":"2016-04-10T21:13:50","modified_gmt":"2016-04-10T13:13:50","slug":"debian-dynamic-dns","status":"publish","type":"post","link":"https:\/\/blog.zhenglei.net\/?p=255457","title":{"rendered":"Debian Dynamic DNS"},"content":{"rendered":"<p><a href=\"http:\/\/perceptionistruth.com\/2013\/05\/running-your-own-dynamic-dns-service-on-debian\/\">http:\/\/perceptionistruth.com\/2013\/05\/running-your-own-dynamic-dns-service-on-debian\/<\/a><\/p>\n<header class=\"entry-header\">\n<h1 class=\"entry-title\">Running your own Dynamic DNS Service (on Debian)<\/h1>\n<div class=\"entry-meta\"><span class=\"entry-date\"><a href=\"http:\/\/perceptionistruth.com\/2013\/05\/running-your-own-dynamic-dns-service-on-debian\/\" rel=\"bookmark\">May 10, 2013<\/a><\/span> <span class=\"byline\"><span class=\"author vcard\"><a class=\"url fn n\" href=\"http:\/\/perceptionistruth.com\/author\/tony\/\" rel=\"author\">tony<\/a><\/span><\/span> <span class=\"comments-link\"><a href=\"http:\/\/perceptionistruth.com\/2013\/05\/running-your-own-dynamic-dns-service-on-debian\/#comments\">6 Comments<\/a><\/span><\/div>\n<\/header>\n<div class=\"entry-content\">\n<p>I used to have a static IP address on my home ADSL connection, but then I moved to BT Infinity, and they don\u2019t provide that ability.\u00a0 For whatever reason, my Infinity connection resets a few times a week, and it always results in a new IP address.<\/p>\n<p>Since I wanted to be able to connect to a service on my home IP address, I signed up to dyn.com and used their free service for a while, using a CNAME with my hosting provider (Gandi) so that I could use a single common host, in my own domain, and point it to the dynamic IP host and hence, dynamic IP address.<\/p>\n<p>While this works fine, I\u2019ve had a few e-mails from dyn.com where either the update process hasn\u2019t been enough to prevent the \u201930 day account closure\u2019 process, or in recent times, a mail saying they\u2019re changing that and you now need to log in on the website once every 30 days to keep your account.<\/p>\n<p>I finally decided that since I run a couple of VPSs, and have good control over DNS via Gandi, I may as well run my own bind9 service and use the dynamic update feature to handle my own dynamic DNS needs.\u00a0 Side note: I think Gandi do support DNS changes through their API, but I couldn\u2019t get it working.\u00a0 Also, I wanted something agnostic of my hosting provider in case I ever move DNS in future (I\u2019m not planning to, since I like Gandi very much).<\/p>\n<p>The basic elements of this are,<\/p>\n<ol>\n<li>a bind9 service running somewhere, which can host the domain and accept the updates.<\/li>\n<li>delegation of a subdomain to that bind9 service.\u00a0 Since Gandi runs my top level domain for me, I need to create a subdomain and delegate to it, and then make dynamic updates into that subdomain.\u00a0 I can still use CNAMEs in the top level domain to hide the subdomain if I wish.<\/li>\n<li>configuration of the bind9 service to accept secure updates.<\/li>\n<li>a script to do the updates.<\/li>\n<\/ol>\n<p>In the interests of not re-inventing the wheel, I copied most of the activity from <a href=\"http:\/\/bahut.alma.ch\/2013\/01\/personal-dynamic-dns.html\">this post<\/a>.\u00a0 But I\u2019ll summarise it here in case that ever goes away.<\/p>\n<h4>Installing \/ Configuring bind9<\/h4>\n<p>You\u2019ll need somewhere to run a DNS (bind9 in my case) service.\u00a0 This can\u2019t be on the machine with the dynamic IP address for obvious reasons.\u00a0 If you already have a DNS service somewhere, you can use that, but for me, I installed it on one of my Debian VPS machines.\u00a0 This is of course trivial with Debian (I don\u2019t use sudo, so you\u2019ll need to be running as root to execute these commands),<\/p>\n<pre>apt-get install bind9 bind9-doc<\/pre>\n<p>If the machine you\u2019ve installed bind9 onto has a firewall, don\u2019t forget to open ports 53 (both TCP and UDP).\u00a0 You now need to choose and configure your subdomain.\u00a0 You\u2019ll be creating a single zone, and allowing dynamic updates.<\/p>\n<p>The default config for bind9 on Debian is in \/etc\/bind, and that includes zone files.\u00a0 However, dynamically updated zones need a journal file, and need to be modified by bind.\u00a0 I didn\u2019t even bother trying to put the file into \/etc\/bind, on the assumption bind won\u2019t have write access, so instead, for dynamic zones, I decided to create them in \/var\/lib\/bind.\u00a0 I avoided \/var\/cache\/bind because the cache directory, in theory, is for transient files that applications can recreate.\u00a0 Since bind can\u2019t recreate the zone file entirely, it\u2019s not appropriate to store it there.<\/p>\n<p>I added this section to \/etc\/bind\/named.conf.local,<\/p>\n<pre>\/\/ Dynamic zone\r\n  zone \"home.example.com\" {\r\n    type master;\r\n    file \"\/var\/lib\/bind\/home.example.com\";\r\n    update-policy {\r\n      \/\/ allow host to update themselves with a key having their own name\r\n      grant *.home.example.com self home.example.com.;\r\n    };\r\n  };<\/pre>\n<p>This sets up the basic entry for the master zone on this DNS server.<\/p>\n<h4>Create Keys<\/h4>\n<p>So I\u2019ll be honest, I\u2019m following this section mostly by rote from the article I linked.\u00a0 I\u2019m pretty sure I understand it, but just so you know.\u00a0 There are a few ways of trusting dynamic updates, but since you\u2019ll likely be making them from a host with a changing IP address, the best way is to use a shared secret.\u00a0 That secret is then held on the server and used by the client to identify itself.\u00a0 The configuration above allows hosts in the subdomain to update their own entry, if they have a key (shared secret) that matches the one on the server.\u00a0 This stage creates those keys.<\/p>\n<p>This command creates two files.\u00a0 One will be the server copy of the key file, and can contain multiple keys, the other will be a single file named after the host that we\u2019re going to be updating, and needs to be moved to the host itself, for later use.<\/p>\n<pre>ddns-confgen -r \/dev\/urandom -q -a hmac-md5 -k thehost.home.example.com -s thehost.home.example.com. | tee -a \/etc\/bind\/home.example.com.keys &gt; \/etc\/bind\/key.thehost.home.example.com<\/pre>\n<p>The files will both have the same content, and will look something like this,<\/p>\n<pre>key \"host.home.example.com\" {\r\nalgorithm hmac-md5;\r\nsecret \"somesetofrandomcharacters\";\r\n};<\/pre>\n<p>You should move the file key.thehost.home.example.com to the host which is going to be doing the updating.\u00a0 You should also change the permissions on the home.example.com.keys file,<\/p>\n<pre>chown root:bind \/etc\/bind\/home.example.com.keys\r\nchmod u=rw,g=r,o= \/etc\/bind\/home.example.com.keys<\/pre>\n<p>You should now return to \/etc\/bind\/named.conf.local and add this section (to use the new key you have created),<\/p>\n<pre>\/\/ DDNS keys\r\ninclude \"\/etc\/bind\/home.example.com.keys\";<\/pre>\n<p>With all that done, you\u2019re ready to create the empty zone.<\/p>\n<h4>Creating the empty Zone<\/h4>\n<p>The content of the zone file will vary, depending on what exactly you\u2019re trying to achieve.\u00a0 But this is the one I\u2019m using.\u00a0 This is created in \/var\/lib\/bind\/home.example.com,<\/p>\n<pre>$ORIGIN .\r\n$TTL 300 ; 5 minutes\r\nhome.example.com IN SOA nameserver.example.com. root.example.com. (\r\n    1 ; serial\r\n    3600 ; refresh (1 hour)\r\n    600 ; retry (10 minutes)\r\n    604800 ; expire (1 week)\r\n    300 ; minimum (5 minutes)\r\n    )\r\nNS nameserver.example.com.\r\n$ORIGIN home.example.com.<\/pre>\n<p>In this case, namesever.example.com is the hostname of the server you\u2019ve installed bind9 onto.\u00a0 Unless you\u2019re very careful, you shouldn\u2019t add any static entries to this zone, because it\u2019s always possible they\u2019ll get overwritten, although of course, there\u2019s no technical reason to prevent it.<\/p>\n<p>At this stage, you can recycle the bind9 instance (\/etc\/init.d\/bind9 reload), and resolve any issues (I had plenty, thanks to terrible typos and a bad memory).<\/p>\n<h4>Delegation<\/h4>\n<p>You can now test your nameserver to make sure it responds to queries about the home.example.com domain.\u00a0 In order to properly integrate it though, you\u2019ll need to delegate the zone to it, from the nameserver which handles example.com.\u00a0 With Gandi, this was as simple as adding the necessary NS entry to the top level zone.\u00a0 Obviously, I only have a single DNS server handling this dynamic zone, and that\u2019s a risk, so you\u2019ll need to set up some secondaries, but that\u2019s outside the scope of this post.\u00a0 Once you\u2019ve done the delegation, you can try doing lookups from anywhere on the Internet, to ensure you can get (for example) the SOA for home.example.com.<\/p>\n<h4>Making Updates<\/h4>\n<p>You\u2019re now able to update the target nameserver, from your source host using the nsupdate command.\u00a0 By telling it where your key is (-k filename), and then passing it commands you can make changes to the zone.\u00a0 I\u2019m using exactly the same format presented in the original article I linked above.<\/p>\n<pre>cat &lt;&lt;EOF | nsupdate -k \/path\/to\/key.thehost.home.example.com\r\nserver nameserver.example.com\r\nzone home.example.com.\r\nupdate delete thehost.home.example.com.\r\nupdate add thehost.home.example.com. 60 A 192.168.0.1\r\nupdate add thehost.home.example.com. 60 TXT \"Updated on $(date)\"\r\nsend\r\nEOF<\/pre>\n<p>Obviously, you can change the TTL\u2019s to something other than 60 if you prefer.<\/p>\n<h4>Automating Updates<\/h4>\n<p>The last stage, is automating updates, so that when your local IP address changes, you can update the relevant DNS server.\u00a0 There are a myriad ways of doing this.\u00a0 I\u2019ve opted for a simple shell script which I\u2019ll run every couple of minutes via cron, and have it check and update DNS if required.\u00a0 In my instance, my public IP address is behind a NAT router, so I can\u2019t just look at a local interface, and so I\u2019m using dig to get my IP address from the opendns service.<\/p>\n<p>This is my first stab at the script, and it\u2019s absolutely a work in progress (it\u2019s too noisy at the moment for example),<\/p>\n<p>#!\/bin\/sh<\/p>\n<p># set some variables<br \/>\nhost=thehost<br \/>\nzone=home.example.com<br \/>\ndnsserver=nameserver.example.com<br \/>\nkeyfile=\/home\/bob\/conf\/key.$host.$zone<br \/>\n#<\/p>\n<p># get current external address<br \/>\next_ip=`dig +short @resolver1.opendns.com myip.opendns.com`<\/p>\n<p># get last ip address from the DNS server<br \/>\nlast_ip=`dig +short @$dnsserver $host.$zone`<\/p>\n<p>if [ ! -z \u201c$ext_ip\u201d ]; then<br \/>\nif [ ! -z \u201c$last_ip\u201d ]; then<br \/>\nif [ \u201c$ext_ip\u201d != \u201c$last_ip\u201d ]; then<br \/>\necho \u201cIP addresses do not match (external=$ext_ip, last=$last_ip), sending an update\u201d<\/p>\n<p>cat &lt;<\/p>\n<div class=\"yarpp-related\">\n<p>Related posts:<\/p>\n<ol>\n<li><a title=\"Exim4 (SMTP MTA) + Debian + Masquerading\" href=\"http:\/\/perceptionistruth.com\/2011\/08\/exim4-smtp-mta-debian-masquerading\/\" rel=\"bookmark\">Exim4 (SMTP MTA) + Debian + Masquerading <\/a> <small>I love Debian, and Exim4 seems to \u2018just work\u2019 for&#8230;<\/small><\/li>\n<li><a title=\"Debian \/ IPv6 \/ ip6tables \/ arno-iptables-firewall\" href=\"http:\/\/perceptionistruth.com\/2011\/02\/debian-ipv6-ip6tables-arno-iptables-firewall\/\" rel=\"bookmark\">Debian \/ IPv6 \/ ip6tables \/ arno-iptables-firewall <\/a> <small>Gandi turned IPv6 on, on my virtual host and I\u2019ve&#8230;<\/small><\/li>\n<li><a title=\"Debian, apache2, virtualhosts, FastCGI and PHP5\" href=\"http:\/\/perceptionistruth.com\/2011\/03\/debian-apache2-virtualhosts-fastcgi-and-php5\/\" rel=\"bookmark\">Debian, apache2, virtualhosts, FastCGI and PHP5 <\/a> <small>I\u2019ve spent an amusing evening revisiting FastCGI under Apache2, in&#8230;<\/small><\/li>\n<li><a title=\"Custom Logwatch script for ngIRCd\" href=\"http:\/\/perceptionistruth.com\/2010\/08\/custom-logwatch-script-for-ngircd\/\" rel=\"bookmark\">Custom Logwatch script for ngIRCd <\/a> <small>So before I begin (or technically, just after I\u2019ve begun),&#8230;<\/small><\/li>\n<li><a title=\"Simple Debian Squeeze LAMP Config\" href=\"http:\/\/perceptionistruth.com\/2011\/08\/simple-debian-squeeze-lamp-config\/\" rel=\"bookmark\">Simple Debian Squeeze LAMP Config <\/a> <small>Want the instant gratification solution?\u00a0 Scroll down to \u201cAll In&#8230;<\/small><\/li>\n<\/ol>\n<\/div>\n<\/div>\n<p><a href=\"http:\/\/www.foell.org\/justin\/diy-dynamic-dns-with-openwrt-bind\/\">http:\/\/www.foell.org\/justin\/diy-dynamic-dns-with-openwrt-bind\/<\/a><\/p>\n<p><a href=\"http:\/\/blog.infertux.com\/2012\/11\/25\/your-own-dynamic-dns\/\">http:\/\/blog.infertux.com\/2012\/11\/25\/your-own-dynamic-dns\/<\/a><\/p>\n<p><a href=\"http:\/\/idefix.net\/~koos\/dyndnshowto\/dyndnshowto.html\">http:\/\/idefix.net\/~koos\/dyndnshowto\/dyndnshowto.html<\/a><\/p>\n<p><a href=\"https:\/\/blog.hqcodeshop.fi\/archives\/76-Doing-secure-dynamic-DNS-updates-with-BIND.html\">https:\/\/blog.hqcodeshop.fi\/archives\/76-Doing-secure-dynamic-DNS-updates-with-BIND.html<\/a><\/p>\n<p><a href=\"https:\/\/0x2c.org\/rfc2136-ddns-bind-dnssec-for-home-router-dynamic-dns\/\">https:\/\/0x2c.org\/rfc2136-ddns-bind-dnssec-for-home-router-dynamic-dns\/<\/a><\/p>\n<p><a href=\"http:\/\/agiletesting.blogspot.com\/2014\/12\/dynamic-dns-updates-with-nsupdate-new.html\">http:\/\/agiletesting.blogspot.com\/2014\/12\/dynamic-dns-updates-with-nsupdate-new.html<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>http:\/\/perceptionistruth.com\/2013\/05\/run &hellip; <a href=\"https:\/\/blog.zhenglei.net\/?p=255457\">\u7ee7\u7eed\u9605\u8bfb <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,2,18],"tags":[275,256],"class_list":["post-255457","post","type-post","status-publish","format-standard","hentry","category-internet","category-linux","category-software-download","tag-bind","tag-ddns"],"_links":{"self":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/255457","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=255457"}],"version-history":[{"count":8,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/255457\/revisions"}],"predecessor-version":[{"id":255459,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/255457\/revisions\/255459"}],"wp:attachment":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=255457"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=255457"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=255457"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}