Custom dynamic DNS

Hi,

Anyone know how to create your own custom dynamic dns solution, like dyndns?

Any how tos would be good.

12 Replies

I created a child-domain "dyn"

dyn IN NS server1

dyn IN NS server2

The "dyn.mydomain.example"

$ORIGIN .
$TTL 5  ; 5 seconds
dyn.mydomain.example          IN SOA  localhost. root.localhost. (
                                1997022716 ; serial
                                60         ; refresh (1 minute)
                                60         ; retry (1 minute)
                                3600000    ; expire (5 weeks 6 days 16 hours)
                                10800      ; minimum (3 hours)
                                )
                        NS      server1
                        NS      server2

$ORIGIN dyn.mydomain.example
home                    A       1.2.3.4

So now "home.dyn.mydomain.example" is the DNS entry that I'll change.

In named.conf

zone "dyn.mydomain.example" {
        type master;
        file "src/dyn.mydomain.example";

        allow-update {127.0.0.1;};
};

This is weak security 'cos anyone on localhost would be able to update this domain, but since I'm the only one…

Now I can update the value easily:

#!/bin/sh
nsupdate -v << EOF
server 127.0.0.1
zone dyn.mydomain.example
update delete home.mydomain.example
update add home.dyn.mydomain.example. 5 IN A $ip_address
send
EOF

That's how I do it for my home machine. (In fact I run DNS on my home machine and then notify my linode to pick up the updates).

After that you just to decide on how you pick up your IP address and populate it. A simple CGI could do the job.

I did it via the Linode API. My domain is hosted on the Linode nameservers, so I created a subdomain with a low TTL, and I wrote a shell script on my home fileserver that checks if its IP has changed since the last check, and if it has, it changes the subdomain's IP via the linode API. I may or may not have based the script on something somebody else posted here previously (don't recall). I'll try to remember to post the script when I get home.

Sounds good, look forward to seeing the script :)

Aaand I completely forgot. Will try to remember tonight :)

Here's the shell script, with my various keys and IDs removed:

#!/bin/sh

LINODE_API_KEY=(PUT YOUR LINODE API KEY HERE)
DOMAIN_ID=(PUT YOUR DOMAIN ID HERE)
RESOURCE_ID=(PUT YOUR RESOURCE ID HERE)

WAN_IP=`wget -O - -q http://(PATH_TO_PHP_SCRIPT_HERE)`

OLD_WAN_IP=`cat /tmp/CURRENT_WAN_IP.txt`

if [ "$WAN_IP" = "$OLD_WAN_IP" ]; then
        echo "IP Unchanged"
else
        echo $WAN_IP > /tmp/CURRENT_WAN_IP.txt
        wget -qO- https://api.linode.com/?api_key="$LINODE_API_KEY"\&api_action=domain.resource.update\&DomainID="$DOMAIN_ID"\&ResourceID="$RESOURCE_ID"\&Target="$WAN_IP"
fi

And here's the PHP script that wget is calling:

Put the PHP script on your server, fill in your API key, the two IDs, and the URL, and put the shell script in a cron job on the system whose IP you want to update (in my case, my home file server), and you're good to go.

You can also use the literal token '[remote_addr]' in place of an actual IP address for Target; this will do the right thing without needing a PHP script. (See http://www.linode.com/api/dns/domain.resource.update)

Ah, that'd be useful, although then you'd be unable to notice if the IP had changed, and would simply be asking Linode to update the DNS entry every few minutes. In any case, here's a script with that method (untested, writing this in the forum directly:

#!/bin/sh

LINODE_API_KEY=(PUT YOUR LINODE API KEY HERE)
DOMAIN_ID=(PUT YOUR DOMAIN ID HERE)
RESOURCE_ID=(PUT YOUR RESOURCE ID HERE)

wget -qO- https://api.linode.com/?api_key="$LINODE_API_KEY"\&api_action=domain.resource.update\&DomainID="$DOMAIN_ID"\&ResourceID="$RESOURCE_ID"\&Target=[remote_addr]

To shorten it even more you could just embed the API key and IDs right into the URL. The downside of this method is, as I said, it would hit Linode every time.

Where do you get the domain and resource ID from?

IIRC you make an API request to get a list of the domains and take note of the IDs. First you do a domain.list:

http://www.linode.com/api/dns/domain.list

And then a domain.resource.list:

http://www.linode.com/api/dns/domain.resource.list

You can do the API calls right in your web browser, just build the URL of the request manually and take note of the results.

Since DynDNS is now requiring payment (or 30 day logins), I've updated a Python script from githib:

https://github.com/Andomar/LinodeDynDns

You can configure the script with a hostname, and it will look up the ResourceID and DomainID for you.

If you install Python, it works on Windows too.

Reviving this old thread, to modernize it since wget does not play well with REST API POST methods.

Here is an updated script:

!/bin/sh

LINODE_API_KEY={YOUR KEY}
DOMAIN_ID={YOUR DOMAIN ID}
RESOURCE_ID={YOUR RECORD ID}
curl -4 -H "Content-Type: application/json" -H "Authorization: Bearer $LINODE_API_KEY" -X PUT -d '{"name": "vpn", "target": "
[remote_addr]", "priority": 50, "weight": 50, "ttl_sec": 300, "tag": null}' https://api.linode.com/v4/domains/$DOMAIN_ID/records/$RESOURCE_ID

Couple of things… I wanted to use WGET, and tried with various flags. The alpine based container that I was running it from did not have curl installed.

I gave up an reformatted the wget into a curl command based on the examples in the documentation.

Note I had to the -4 parameter to the curl command in order to force [remote_addr] to return an IPv4 address. Without the API picked up my IPv6 and create a "AAAA" record with the IPv6 address instead.

Sorry, I could not figure out how to get the code block to format correctly . . .

I wrote this recently, and it's been working great. I have it in a cron job that every 30 minutes.

https://gist.github.com/christr/9de75da7fd1ffbd1aa4f0b33316fff8c

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct