Dynamic DNS with ddclient on Raspberry Pi and Ubuntu

This tutorial will show you how to configure ddclient on Raspbian and Ubuntu. Many tutorials don't explain what to do if your server is behind a router, but this one will.

I recently set up a backup server on an internet connection that has a dynamic IP address. So far, I've been spoiled at home because my ISP (PlusNet) makes switching to a static IP address easy and cheap, so obviously I did that. This time though, I didn't have that option, and I didn't want to configure a dynamic dns client on that router either, so I had to set it up on the server itself.

Installation

Some DNS providers offer their own dynamic DNS clients, but most of them are proprietary. The one I am going to use is called ddclient, it's free and open source, and written in Perl. Use this command to install ddclient:

sudo apt-get install ddclient

Enable dynamic DNS with your DNS provider

If you're not using namecheap, then this section will be different, but the concept is the same regardless of DNS provider.

Log into namecheap and select the relevant domain, then choose "Dynamic DNS" under Miscellaneous settings.

Use the radio buttons to enable dynamic DNS, and then make a note of the password. It should go without saying, but be really careful what you do with this password - anyone with access to it could change any DNS record for your domain that they wanted to. Unfortunately, namecheap doesn't let you restrict the dynamic DNS to just one subdomain.

Next, navigate to "All host records" add a DNS A record for your domain (use the @ symbol for this), or subdomain. Use the dummy IP address 127.0.0.1 for now, the first time we run ddclient this will be updated to your actual Wide Area Network (WAN) IP address.

ddclient configuration

Now you have everything you need to configure ddclient.

The main configuration file for ddclient is at /etc/ddclient.conf, you can open this file to edit it with a text editor of your choice - this command will open it in nano:

sudo nano /etc/ddclient.conf

Here is a sample "normal" configuration file for ddclient:

protocol=namecheap
server=dynamicdns.park-your-domain.com
login=yourdomain.com
password='password'
subdomain
  • protocol is set by your dynamic DNS provider. For namecheap the value is "namecheap"
  • server is the hostname of the dynamic DNS server. The dynamic DNS servers used by namecheap are located at "dynamicdns.park-your-domain.com"
  • login is your domain name
  • password is the string we obtained earlier from the namecheap web interface. Leave the single quotation marks around the string.
  • The last line is the subdomain to be modified. In my case this was backup, for backup.samhobbs.co.uk. If you wanted to update your root domain, you would put an @ symbol on this line instead

WAN IP discovery

The above configuration would work fine if ddclient was installed on a router, since the router knows your WAN IP address. However, it doesn't work if your server is behind a router because the server only knows its Local Area Network (LAN) IP address.

There is a configuration parameter called use, which determines the method ddclient uses to find the WAN IP.

Important! - if you specify this parameter, it must go above the rest of the configuration in the file. If you specify it below, it won't work! This caused me quite a lot of grief.

The default value for use is if, which uses information from the netwrok interface (think ifconfig). If you have multiple network interfaces, you can specify which one like use=if, if=eth0 for ethernet, if=lo for the loopback address, if=wlan0 for wireless LAN etc. However, none of these will work for us because none of them will give the WAN IP.

There are two more types of value you can set: web, and router firmware values like fw and linksys.

Getting your WAN IP from your router's status page

Although I haven't opted for the router firmware method, I think it's quite interesting and worth discussing. Router firmware settings look something like this:

use=fw, fw=192.168.1.1/status.htm, fw-login=admin, fw-password=admin, fw-skip='IP Address'

...where fw= sets the location of the status page for that particular router containing the WAN IP address. If the status page is not available to unauthenticated users, you must set the username and password to allow ddclient to authenticate with the router. fw-skip tells ddclient to ignore any IP address on the status page you specified before a certain string, in this case 'IP Address'.

Some popular router manufacturers have their own settings for ease of use, for example if you have a Linksys router you can use this line:

use=linksys, fw=linksys, fw-login=admin, fw-password=admin

Note that since a lot of routers won't let more than one user log in as admin at a time, you could potentially prevent ddclient from updating your dynamic IP address if you are logged in yourself at the same time.

Getting your WAN IP address from a web service

The web method involves ddclient querying one of the many "what is my ip" type web services on the internet, and extracting your IP address from the page returned. You can tell ddclient to use this method by using this line:

use=web

Similarly to other methods, you can also specify which website to use with the web-skip parameter. Some options with preset values are dnspark, dyndns and loopia, although you can use any site you like. For example, you could use somedomain.com by setting use=somedomain.com, with an appropriate web-skip-pattern=foo to ignore IP addresses before the string "foo" if necessary..

Secure submission

Remember how I said anyone with your dynamic dns password can change your DNS records? Sending your password via http (not https) is a bad idea. This parameter will force https:

ssl=yes

Again, this needs to go above the protocol parameter in your config file.

For this to work, you need a perl library that can use SSL. Install it with this command:

sudo apt-get install libio-socket-ssl-perl

Testing your configuration

You can check if the pre-defined use values can detect your WAN IP by running this command:

sudo ddclient -query

If your server is connected with an ethernet cable, the output should look something like this:

use=if, if=lo address is 127.0.0.1
use=if, if=p2p1 address is 192.168.1.119
use=if, if=wlan0 address is NOT FOUND
use=web, web=dnspark address is 1.2.3.4
use=web, web=dyndns address is 1.2.3.4
use=web, web=loopia address is 1.2.3.4

To test your ddclient configuration with really verbose output, printing all possible configuration parameters and their values, you can use this command:

sudo ddclient -debug -verbose -noquiet

I won't print a sample output because it's too long, but somewhere near the bottom you should see a line like this:

SUCCESS:  updating backup: good: IP address set to 1.2.3.4

While we've got all this information, It's worth checking to make sure you are actually using SSL to connect to your dynamic DNS provider. Look for lines like this:

CONNECT:  dynamicdns.park-your-domain.com
CONNECTED:  using SSL

Run ddclient as a daemon

Since we don't just want the IP address to update once, we still need to set up ddclient to run as a daemon so it can check for a change of IP address periodically and notify the dynamic DNS provider if necessary.

To start the daemon we need to open another configuration file, /etc/default/ddclient and set:

run_daemon="true"

You will notice there is a daemon_interval parameter there too, I think the default value of 300 seconds (5 minutes) is reasonable, so I didn't change it.

Save and close the file, and then run:

sudo service ddclient start

to start the daemon, and:

sudo service ddclient status

to check its status.

ddclient keeps a cache of your IP address, and it will only update the record with your dynamic DNS provider if your IP address hasn't changed. Since some ISPs seem to only allocate new IP addresses when the modem is power cycled, and some dynamic DNS providers will time out if you don't update the record in a while, there is one thing left to do - we need to add a cron job to force an update weekly, just in case.

Choose whether you want to force an update daily or weekly, and then create a file called ddclient in the relevant directory, e.g. /etc/cron.daily or /etc/cron.weekly:

sudo nano /etc/cron.daily/ddclient

Fill in this information:

#!/bin/sh
/usr/sbin/ddclient -force

Then make the script executable:

sudo chmod +x /etc/cron.daily/ddclient

Done :)

Useful links

Type: 

Comments

Let me begin with my compliments for your tutorials. I see that you are trying to explain things instead of (just) writing a cookbook with all the right commands.

I have a question about the last paragraph of your tutorial on ddclient. I think you refer here to the habit of free DNS suppliers (like no-ip in my case) to remove your hosts if there has been no update on that host for over a month (for example). After the "ddclient -force" my DNS supplier comes back with this message:

WARNING: updating rvoosten****.no-ip.org: nochg: No update required; unnecessary attempts to change to the current address are considered abusive

Should I take this message seriously?

Untill now I used to do things with this: "ddclient -ip=66.66.66.66" in a weekly cron file.
Obviously my domain name points to the wrong IP afterwards but that is solved within 5 minutes.
This solution is ofcourse also an unnecessary attempt to change the current address.

Thanks in advance..

Thanks :) that's exactly what I'm going for.

Good question. I guess they just don't want you spamming them with unneccessary requests (if everyone forced an update every hour that would add up to a lot of traffic pretty quickly), but I doubt you'll get in trouble for doing it once a week or month.

They probably have something like fail2ban running to cut down on abusive/poorly configured clients, so the question is what would you set as a limit if you were running a service like that? If you think about it, when you reboot your server ddclient's IP address cache is probably cleared, so it must send a (probably unneccessary) request then. They're not going to ban people for rebooting their servers every week, so running a weekly job is probably fine. Your call, though!

Thanks for the comment :)

Sam

When running sudo ddclient -debug -verbose -noquiet I get the following at the bottom:

DEBUG: get_ip: using ip, ip reports
WARNING: unable to determine IP address

Here is my /etc/ddclient.conf

# Configuration file for ddclient generated by debconf
#
# /etc/ddclient.conf

ssl=yes
protocol=namecheap
server=dynamicdns.park-your-domain.com
login=mydomain.com
password=mypassword
mysubdomain

Any ideas what I am doing wrong?

Hi mate,

This is explained in the WAN IP address discovery section - the default use is if which doesn't work behind a router.

Try use=web, and make sure to put it above the rest of the config.

Sam

Thank you, sorry noob moment. Got everything running smoothly now except SSL. I have ssl=yes at the very top of my conf but verbose output still shows HTTP instead of SSL. I talked to Name Cheap and they advised I buy a SSL. I've went through all the steps to install my .crt's and .key but still the same output. I don't suppose I can hit you up for one more noob support help?

CONNECT: dynamicdns.park-your-domain.com
CONNECTED: using HTTP

Are you sure they told you to buy a certificate? That was terrible advice if so - ddclient is the client in this case so no certificate is required.

Do you have libio-socket-ssl-perl installed? If not, install it and re-test.

Sam

Hey, I have the same problem: I have ssl=yes and it says I'm connected with HTTP instead of SSL. I also have libio-socket-ssl-perl installed but still no success. Any advice?

Btw, really nice guide good job!

I had installed that but after I installed ddclient. I tried from the beginning and installed it before ddclient, this time it works! Thank you! Yeah, I didn't think I had to buy a SSL cert but I wanted one for other purposes anyways so it will be used. Again, thank you. Your site has helped me a lot.

Strange, it shouldn't make any difference which order you install the packages in - did you get an error during installation the first time?

You're welcome as always :)

Sam

No I got no errors before. My second RPi is doing the same thing. l had that package installed, installed ddclient, and my config looks good but it only connects to HTTP. I think they are possessed.

ssl=yes
protocol=namecheap
use=web, web=dynamicdns.park-your-domain.com/getip
server=dynamicdns.park-your-domain.com
login=domain.com
password='password'
subdomain

I'm Having the same problem.

Here is my conf:

use=web, web=dynamicdns.park-your-domain.com/getip
ssl=yes
protocol=namecheap
server=dynamicdns.park-your-domain.com
login=coolurl.com
password='notmyactualpassword'
@

Hey Amigo,

try deleting the cache, or changing the ip in the cache.

sudo rm /var/cache/ddclient/ddclient.cache

Maybe make a backup because it's good practice but probably unecessary. I had the same problem.

You'll still see the password in the sending, but it should be okay because it will say using SSL before it.

Thanks!
I was having the same problem and this worked!

Hey, nice laid out tutorial ! well done =)

I have installed ddclient on my raspbianpi but wasn't sure how ddclient works. wether as a standalone program or as a daemon

back and forth I had to run ddclient manually whenever my ISP changes my public ip

wasn't aware of the trick to set up cron daily untill I came across your tutorial !

now i can connect to my raspbianpi vpn server smoothly, without the need to first run ddclient manually

Thank you for this guide. Being new to Rpi and struggling a bit to find my way around linux, guides like these help me see things coming together. This was easy and makes sense.

Hello Sam,

First off thanks for those tutorials, they're incredibly useful for a new (or rather born-again) Linux user!

I'm using your DDNS instructions as part of setting up my own email server, and I'm beginning to think there's a ghost in that cutiepi of mine... It's driving me potty! I've registered my FQDN (therminology.net) with Dynu.com, nameservers have propagated, all is dandy. But when it comes to installing ddclient, there's some oddity going on (actually two):

When doing a fresh setup of ddclient and on entering my details (FQDN, DDNS server, username, password) the automated script invariably tells me to re-enter my pwd, although I have taken every care to enter them exactly the same both time around. That's not too big a deal since I've got to manually check and edit ddclient.conf anyway. However, when it comes to the crunch and the server connects, it only seems to do so through SSL the first time around! Any subsequent attempts are sent unencrypted. That's especially annoying when I want to go back to change my Dynu.com password for security reasons (in case it got sent out unencrypted already).

I've pasted redacted ddclient output here and content of my /etc/ddclient.conf here so as not to spam your message board.
http://pastebin.com/ziMMuX92

I've even tried giving the argument ssl=required in ddclient.conf, but it didn't seem to make any difference.
Would you be able to take a quick look? It might actually be fine, and DNS updating is working anyway. I just like to be sure it's secure before I continue setting up my mailserver.

Many, many thanks!

Jay

Hi,

I can't think why it wouldn't be working, sorry!

Try moving ssl=yes right at the top above use=web? I don't know why the order should matter, but it does seem to make a difference sometimes.

Sam

Hi Sam,

Thanks for your reply! I have tried the order proposed in the tutorial. Come to think of it, isn't it possible the last entries of the ddclient output actually refer not to the login credentials, but to the 'check ip' portion?


CONNECT: checkip.dynu.com
CONNECTED: using HTTP

This is not the API server that checks my login credentials; it's just their 'Find out my IP' server.

SENDING: GET / HTTP/1.0
SENDING: Host: checkip.dynu.com
SENDING: User-Agent: ddclient/3.8.2
SENDING: Connection: close
SENDING:
RECEIVE: HTTP/1.1 200 OK
RECEIVE: Date: Sun, 24 Jan 2016 23:27:21 GMT
RECEIVE: Server: Apache/2.2.3 (CentOS)
RECEIVE: X-Powered-By: PHP/5.1.6
RECEIVE: Content-Length: 32
RECEIVE: Connection: close
RECEIVE: Content-Type: text/html; charset=UTF-8
RECEIVE:
RECEIVE: Current IP Address: 86.20.19.130
DEBUG: get_ip: using web, checkip.dynu.com/ reports 86.20.19.130
SUCCESS: mail.therminology.net: skipped: IP address was already set to 86.20.19.130.
SUCCESS: therminology.net: skipped: IP address was already set to 86.20.19.130.

Maybe I should just carry on? What I'll try next is replace use=web with use=if and set to eth0 so it won't have to get outside my home network to check for the IP. If that won't change anything, I'll just carry on with the email server tutorial and hope for the best...?

Jay

Yeah I think you're right, I guess no connection is made to the dynamic dns server unless the IP address actually needs to be changed.

Maybe run ddclient with the force option and see if you get the SSL message in the output?

sudo ddclient -debug -verbose -noquiet -force

Sam

Running ddclient with the -force option did indeed show that my connection to namecheap was SSL. I wasn't seeing that connection at all before your suggestion. Thanks for the fantastic tutorials!

Fantastic tutorial! Thank you very much!

My DNS provider, zoneedit.com has a check IP page to determine your IP address (dynamic.zoneedit.com/checkip.html). When this page is accessed using "http://", the response is very slow and usually times out. When using "https://", the response is lightning fast. The problem I had was getting ddclient to use SSL during the IP check.

At the top of my ddclient configurantion file, I had "SSL=yes". First I tried "web=dynamic.zoneedit.com/checkip.html", unfortunately, I had many timeouts as ddclient did not use SSL. Then I tried "web=https://dynamic.zoneedit.com/checkip.html". This worked great! No more timeouts.

I thought this info might be helpful to someone.

First great tutorial. It helped me set up ddclient on my RPi server so I can make sure DDNS gets updated when my external IP address changes. But there is a problem that I haven't been able to figure out yet. I have tried web and fw methods to get the WAN IP address and it appears to work with either of those methods. The cache file has ip=, and wx=, in it. So dynu.com is telling me that nochg was required when the IP address update is requested, Obviously it will keep doing that forever which is a bad thing. I can stop it of course by editing the cache file and adding my WAN IP address. But I expect that when my WAN IP address does change I'll be back in the soup again.

I suspect that ddclient is not liking the response from dynu.com for some reason and doesn't update the cache but there no error message other than the warning about repeated nochg update requests being considered abuse (warning message in ddclient). I've started digging though the ddclient source but haven't done much with Perl in a long time so it will be a bit of a slow process.

Have you seen anything like this and what is the solution? Again running on RPi with the latest ddclient from the RPi repo.

I have some travel coming up and need to be sure that if the IP address changes while I'm gone I can still remotely access my DVR and cameras.

Thanks,
Burt

It was doing it every time the interval I had set fired off. The problem was caused by the DDNS provider not returning the IP address in their response to the update request. And due to the way ddclient was written it effectively set the IP address to nothing and then updated the cache file. I finally tracked it down and got the patched version, figured out what needed to be changed in the version on RPi, made the changes and voila! It is working perfectly.

So for any others having a similar problem be sure to look for the patch that saves the current $ip value in a temp and then tests to see if the IP address is returned in the response to a request to update DDNS and then either use that returned IP address or set $ip back to the saved temp value.

Thanks,
Burt

Sorry for not getting back sooner. We have been traveling so this is the first chance I've had.

I'm using Dynu for the DDNS service, but they are not the only ones that don't return the WAN IP address in the response message. I didn't apply the full update since everything else was working OK.

I pulled the 3.8.3 version of ddclient from sourceforge. Then I located the appropriate function for dyndns2 protocol processing and made the appropriate changes as shown below.

Here's what I incorporated from the 3.8.3 version of ddclient:

Note that I've added some comments to help clarify what was done. Basically it is define a variable to hold the current WAN IP address that was returned either from your router or an external web request. And obviously the "<==" comments are not part of the changed code. Those are just to highlight the changes.

Then if the returned value from the DDNS provider does include an IP address then set $ip to that returned value, otherwise set $ip=the temp variable that is holding the current WAN IP address.

sub nic_dyndns2_update {
....
## BBB Fixed bug dealing with no IP address returned from dyndns provider
# Save the current IP address that was returned by router or external web request.
# Add the temp variable $returnedip
my $returnedip = $ip; <== Add this line to ddclient Perl source file.
...
# I commented out the old split line but this could be removed.
## my ($status, $ip) = split / /, lc $line; <== comment out this old line until you are sure things are workingf.
# BBB bug #10: some dyndns providers does not return the IP so
# we can't use the returned IP. Need to use the IP saved in the temp variable
my ($status, $returnedip) = split / /, lc $line; <== Add this line to replace the old one
$ip = $returnedip if (not $ip); <== Add this line and you should be working correctly.
# The following line is from the unpatched code.
my $h = shift @hosts;
...

You could, of course, try installing the complete 3.8.3 version, but some comments online indicated that it might be better to just make the changes to fix this particular bug.

Sam,

Just wanted to say thanks for the tutorial. I actually came across it whilst setting up 'ddclient' for a Lubuntu installation on a PC, but I found your tutorial and its descriptions of what exactly is going on (and why) to be helpful in the extreme.

I'd like to echo the comments elsewhere that your approach here is atypical of the normal "here's a list of instructions" way of doing this, and the fact that you've taken the time to explain what's going on has made me feel like I've learned something.

Thanks again (I'll be back!),
Barry

Barry,

Thanks for the kind feedback. That's exactly what I am aiming for, glad it comes through in the tutorials.

Sam

Pages

Add new comment