I was on the hunt for a suitable Dynamic DNS solution. There’s a whole bunch of paid and free services that can do this. Although… I’m not too keen on paying or having a free account to some random service. That’d mean making yet another account and then probably updating it every month to keep it active. Instead I can bleed time into setting up and maintaining my own stuff!
Enter ddclient. I stumbled upon this super helpful post written by Jens Segers. As it turns out, there’s this purpose built utility to update Cloudflare DNS entries with dynamic IP addresses, and this purpose built blog post to tell me how to mash everything together and it will work seamlessly.
Just kidding, could you imagine?
At the time of writing:
- Cloudflare uses v4 of their API.
- ddclient updated from Cloudflare’s API v1 to v4 from version 3.8.3.
- The Ubuntu repository will install ddclient version 3.8.3.
- The latest ddclient version is 3.9.0.
Here’s how I got DDNS working on Ubuntu 18.04.1 LTS with Cloudflare and ddclient running as a daemon.
Install ddclient #
Make sure our repository is up to date.
sudo apt update
Download and install ddclient, and all the other pieces we need.
sudo apt install ddclient libdata-validate-ip-perl
While ddclient is getting installed, you’ll get asked a whole host of questions. We mostly don’t care as we’re going to change everything anyway. The point is, installing it this way puts most of the stuff where it needs to be.
- Dynamic DNS service provider: select “other”.
- Dynamic DNS server: leave blank.
- Dynamic DNS update protocol: select “dyndns2” (it just happens to be the first entry).
- Username for dynamic DNS service: leave blank.
- Password for dynamic DNS service: leave blank.
- Re-enter password to verify: leave blank.
- Network interface used for dynamic DNS service: leave blank.
- DynDNS fully qualified domain names: leave blank.
Curiously, there’s some specific options I didn’t get asked until I reconfigured the package. It’ll ask you the same questions as above so just provide the same answers, but the additional questions are what we need to pay attention to.
sudo dpkg-reconfigure ddclient
- Run ddclient on PPP connect?: select “No” (the default is “Yes”).
- Run ddclient as a daemon: select “Yes” (the default is “No”).
- Interval between ddclient runs: leave as “300” (if you want a 5 minute interval).
Just so you know why we’re installing libdata-validate-ip-perl as well as ddclient, it prevents you from doing something like:
sudo ddclient -help
Then witnessing everything immediately detonate inside your shell:
Can't locate Data/Validate/IP.pm in @INC (you may need to install the Data::Validate::IP module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.26.1 /usr/local/share/perl/5.26.1 /usr/lib/x86_64-linux-gnu/perl5/5.26 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.26 /usr/share/perl/5.26 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base) at /usr/sbin/ddclient line 27. BEGIN failed--compilation aborted at /usr/sbin/ddclient line 27.
Update ddclient #
Since the Ubuntu repository will install ddclient version 3.8.3 ( released 2015-05-30), and the latest version is 3.9.0 ( released 2018-08-09), we should probably update it. Strictly speaking, 3.8.3 will work with Cloudflare. However I’ve done this based on 3.9.0, and it’s nice to have the latest software.
The below steps mostly come from the purpose built blog post linked earlier: Dynamic DNS for CloudFlare with ddclient.
Since the latest version isn’t in our standard repositories, we’ll need to download and extract it.
wget https://sourceforge.net/projects/ddclient/files/ddclient/ddclient-3.9.0/ddclient-3.9.0.tar.gz tar -xvf ddclient-3.9.0.tar.gz
Then we overwrite the existing Perl script with the new one.
sudo cp -f ddclient-3.9.0/ddclient /usr/sbin/ddclient
The ddclient.config file location has changed in 3.9.0, so we need to resolve that issue.
sudo mkdir /etc/ddclient sudo mv /etc/ddclient.conf /etc/ddclient
It’s always a good idea to tidy up and remove things we don’t need or that are toxic to us in life.
rm ddclient-3.9.0.tar.gz rm -R ddclient-3.9.0
Configure ddclient #
Since we blazed through our setup phase, our configuration file is mostly empty and completely useless. We can take a peek at the wasteland
# Configuration file for ddclient generated by debconf # # /etc/ddclient.conf protocol=dyndns2 server= login= password=''
Now we need to actually get ddclient to talk to Cloudflare. We have to edit ddclient.conf and put in some useful information. This is where we will deviate as your details are going to be different to mine. If you want more information around what the variables are, there’s a good example file in the 3.9.0 download called sample-etc_ddclient.conf. Additionally, the ddclient usage wiki has some good information around the ddclient options. Between the example configuration file and the ddclient usage wiki, you can find out what all the options actually are in the below ddclient configuration.
You’ll want to update the values on each line that have ## Update Me at the end. The commented out parts naturally don’t actually change anything, but it’s just to keep structure. Design your configuration file such that it brings you joy.
In the below configuration example, we’ve signed up to Cloudflare using the email address “ [email protected]”. We’ve then copied our Cloudflare Global API Key, which happens to be “abcredactedxyz”. Somehow, we own the domain “domain.tld” and we are updating the “sub.domain.tld” A Record with our dynamic IP address.
My redacted working ddclient.conf looks like
# Configuration file for ddclient ## ## Global Config ## daemon=300 ssl=yes ## ## sub.domain.tld - Cloudflare ## Update Me ## protocol=cloudflare use=web [email protected] ## Update Me password=abcredactedxyz ## Update Me zone=domain.tld ## Update Me sub.domain.tld ## Update Me
#1 - Public IP #
Our first test is to see if ddclient is actually able to get our public IP address. First google what your IP is, then run:
sudo ddclient -query
You’ll see your local IP address, your loopback address, and then your public IP address (in this case it’s shown as “220.127.116.11”) from a few different services. You might have some warnings from certain sites not resolving, that’s fine.
use=if, if=ens160 address is 192.168.1.1 use=if, if=lo address is 127.0.0.1 WARNING: cannot connect to ipdetect.dnspark.com:80 socket: IO::Socket::INET: Bad hostname 'ipdetect.dnspark.com' WARNING: found neither ipv4 nor ipv6 address use=web, web=dnspark address is NOT FOUND use=web, web=dyndns address is 18.104.22.168 use=web, web=loopia address is 22.214.171.124
#2 - Connection to Cloudflare #
Our second test is to make sure we can successfully take our public IP and update our Cloudflare A record with it. A quick test which will use our configuration file and attempt to update our IP is basically just running ddclient now and asking for some verbosity. Fair warning, this will literally update your DNS records if it works, so, you know.
sudo ddclient -daemon=0 -verbose -noquiet
We should get something nice and easy to read like:
CONNECT: checkip.dyndns.org CONNECTED: using HTTP SENDING: GET / HTTP/1.0 SENDING: Host: checkip.dyndns.org SENDING: User-Agent: ddclient/3.9.0 SENDING: Connection: close SENDING: SENDING: RECEIVE: HTTP/1.1 200 OK RECEIVE: Content-Type: text/html RECEIVE: Server: DynDNS-CheckIP/1.0.1 RECEIVE: Connection: close RECEIVE: Cache-Control: no-cache RECEIVE: Pragma: no-cache RECEIVE: Content-Length: 107 RECEIVE: RECEIVE: <html><head><title>Current IP Check</title></head><body>Current IP Address: 126.96.36.199</body></html> SUCCESS: sub.domain.tld: skipped: IP address was already set to 188.8.131.52.
The last line there tells us everything we need to know: SUCCESS: sub.domain.tld: skipped: IP address was already set to 184.108.40.206. You might have another message like a failure, or a success in actually updating the IP. As long as it makes the good words.
If you do have problems, you can get a lot more information by running:
sudo ddclient -daemon=0 -debug -verbose -noquiet
#3 - Running Daemon #
Our third test is to make sure that the ddclient daemon is running and actually checking for a changed IP every five minutes. If we run
htop then we should see one process running, and it’ll probably be sleeping. The maximum amount of time it should sleep is 300 seconds, as that’ll be 5 minutes (or whatever threshold you set). You might also see it updating. It also doesn’t hurt to restart the guest to make sure the daemon resumes after a reboot.
PID USER ... CPU MEM TIME Command 1622 root ... 0.0 1.9 0:10.69 ddclient - sleeping for 80 seconds
Bugs and Errors #
PID City #
I noticed a lot of PIDs running while inspecting in
htop which was super odd. I’m not sure what I did that caused this behavior, but this is a known bug that has already been resolved in the
Debian Bug #652298, as well as the related and merged
Debian Bug #761505. I killed all the process with
killall -r ddclient, however I couldn’t intentionally reproduce the issue.
PID USER ... CPU MEM TIME Command 15563 root ... 0.0 4.5 0:00.31 ddclient - sleeping for 300 seconds 15575 root ... 0.0 4.5 0:00.30 ddclient - sleeping for 150 seconds 15607 root ... 0.0 4.5 0:00.31 ddclient - sleeping for 230 seconds 15671 root ... 0.0 3.0 0:00.14 ddclient - sleeping for 280 seconds 15742 root ... 0.0 4.5 0:00.29 ddclient - sleeping for 160 seconds 15745 root ... 0.0 5.1 0:00.43 ddclient - sleeping for 190 seconds 15750 root ... 0.0 3.0 0:00.11 ddclient - sleeping for 230 seconds 16345 root ... 0.0 2.9 0:00.03 ddclient - sleeping for 200 seconds
Literally Nothing #
Swank, now you can run ddclient but… it just runs and then doesn’t actually do anything. That’s likely because it’s actually hitting a 301 and not following the redirect. It’s also likely that is happening because you’re using server=www.cloudflare.com. That server location is the problem as per this link Cloudflare Community - CF Returning 301. You can specify server=api.cloudflare.com/client/v4 instead, however you can just remove the server= variable.
Other Crimes #
Good luck, here’s some other crimes you can solve: mcblum Github - Can’t locate Data/Validate/IP.pm Error.