Another option for dynamic DNS on my site or how I abandoned dyndns

For a long time I used the service from the company dyndns, which allowed you to bind the domain name to the dynamic ip-address of the computer. It is convenient to administer the client, it is convenient for the client from home to connect to a working computer. But for some time now, the service began to tighten the nuts.

At first, you could use one domain name on your account for free. Later, the domain name began to be reset every month - this periodically required restoration work. Other free services did not appeal to me and at some point I signed up for their paid service for $ 25 per year, which gave me the opportunity to use up to 30 domain names.

There was an inconvenience - the client program for Windows renders all the domain names of my account during setup and any client may accidentally or intentionally damage the binding of someone else's domain name. In general, it is oppressive, but bearable. Last week, it was time to renew my subscription for a year. The price rose to $ 30, and by the time the ruble fell to 60 rubles per dollar. I felt sorry for the rubles and I still decided to squeeze the dynamic DNS on my site.

Initial data:
  • windows and * nix machines with dynamic ip
  • freebsd 9.3
  • bind9
  • apache 2.4
  • php 5.3
  • own domain

What you need to get:
  • easy to use client part


Solution:

Suppose our domain is MyDomain.ru. We describe it as a master zone in /etc/namedb/named.conf:

zone "MyDomain.ru" {
           type master;
           file "/etc/namedb/master/MyDomain.ru";
};

Accordingly, in / etc /namedb/master/MyDomain.ru we will write something like:

$ORIGIN .
$TTL 3600       ; 1 hour
MyDomain.ru              IN SOA  ns1.MyDomain.ru. root.MyDomain.ru. (
                                2015032014 ; serial
                                10800      ; refresh (3 hours)
                                3600       ; retry (1 hour)
                                604800     ; expire (1 week)
                                86400      ; minimum (1 day)
                                )
                        NS      ns1.MyDomain.ru.
                        NS      ns2.MyDomain.ru.
                        A       188.120.254.163
                        MX      10 mail.MyDomain.ru.
                        MX      20 mail.MyDomain.ru.
$ORIGIN MyDomain.ru.
mail                    A       192.168.0.1
ns1                     A       192.168.0.1
ns2                     A       192.168.0.1
smtp                    A       192.168.0.1
www                     A       192.168.0.1

After execution:

echo 'named_enable="YES" ' >> /etc/rc.conf
/etc/rc.d/named start


We get a working dns server, check the name resolution for addresses with a ping, if there is a firewall, do not forget to open the 53 and 953 input ports. Configure rndc, the named daemon management utility.

rndc-confgen

We distribute its output into two files:

key "rndc-key" {
    algorithm hmac-md5;
    secret "rxeXMLrA\1py6mDLhGO7dA==";
};
options {
    default-key "rndc-key";
    default-server 127.0.0.1;
    default-port 953;
};

We put in /etc/namedb/rndc.conf, and

# key "rndc-key" {
#       algorithm hmac-md5;
#       secret "rxeXMLrA\1py6mDLhGO7dA==";
# };
#
# controls {
#       inet 127.0.0.1 port 953
#       allow { 127.0.0.1; } keys { "rndc-key"; };
# };

after removing the comment, add it to /etc/namedb/named.conf. If everything is correct, then the following command should succeed:

rndc reload


You can see the status
rndc status

You can read man by rndc.

You need to add some rights to the user on behalf of which named works:

chown bind /etc/named/master

We create the ddns user (with the home directory / home / ddns), on behalf of which the script for updating the dns server record will work.
We create a script of the following content and place it in /home/ddns/ddns.sh, for example:

#!/usr/local/bin/bash
TTL=120
SERVER=127.0.0.1
ZONE=MyDomain.ru.
HOSTNAME=$1.$ZONE
KEY="rxeXMLrA\1py6mDLhGO7dA=="
new_ip_address=$2
nsupdate << EOF
server $SERVER
key rndc-key $KEY
zone $ZONE
update delete $HOSTNAME A
update add $HOSTNAME $TTL A $new_ip_address
send
EOF

Don't forget
chown ddns:ddns /home/ddns/ddns.sh 
chmod 700 /home/ddns/ddns.sh 

Call it with two parameters

/home/ddns/ddns test 192.168.0.2

should add a third-level domain test.MyDomain.ru with the address 192.168.0.2 to our zone.

Now it remains to somehow allow clients to access this script so that they can update their names in the zone to the current IP addresses. I solved this using a web server. In the Apache configuration, it allowed virtual servers and created one for its own needs.


    ServerAdmin root@MyDomain.ru
    DocumentRoot "/usr/local/www/ddns"
    ServerName ddns.MyDomain.ru
    DirectoryIndex index.php
    ErrorLog "/var/log/apache/ddns-error.log"
    CustomLog "/var/log/apache/ddns-access.log" common
    
        AllowOverride All
        Order allow,deny
        Require valid-user
        Allow from all
        AuthName "Who are you?"
        AuthType Basic
        AuthUserFile /usr/local/www/ddns/.htpasswd
    

The main nuance is that access to this site is possible only with an username and password. Credentials are stored in /usr/local/www/ddns/.htpasswd, in the same directory we place the php script of the following contents:



Unfortunately, I couldn’t run the bash script directly from php, I think this is caused by the security settings of the www user, on behalf of whom the web server service works. Therefore, I use sudo on behalf of the ddns user (a regular user in whose home directory the script itself lies). Here is the contents of the / usr / local / etc / sudoers file for this:

www ALL=(ddns) NOPASSWD: /home/ddns/ddns.sh

Well, do not forget, in fact, fill the file with credentials:

htpasswd -сb /usr/local/www/ddns/.htpasswd test test-password
htpasswd -b /usr/local/www/ddns/.htpasswd test1 test1-password
htpasswd -b /usr/local/www/ddns/.htpasswd test2 test2-password

If sudo is configured correctly, there are no problems with access rights of the www user, then when the client accesses the resource
http://ddns.MyDomain.ru 

We receive an invitation to enter credentials.

We enter the username and password, we get a response in the browser with the client ip-address. On the server, at the same time, the php script updates the domain name in dns by the client login and its ip address. I also consider it reasonable to add the following lines to the named setting for our zone:

 update-policy {
 grant rndc-key name test.MyDomain.ru. A;
 grant rndc-key name test1.MyDomain.ru. A;
 grant rndc-key name test2.MyDomain.ru. A;
 };

So that only the allowed domain names can be edited with the rndc-key switch. It would be nice to arrange the client and server communication through https so that open passwords do not go on the Internet.

It remains only to finish the client. Everything is simple there.

curl -u test:test-password http://ddns.MyDomain.ru

The curl utility in * nix systems should be by default, it will have to be downloaded for Windows. Place this command in a bat-file or sh-script and place it in the task scheduler or cron, respectively, with a call interval of 5 minutes.

To connect the next client to this scheme, we come up with a login (domain of the 3rd level) and a password for it. Edit the client script and add the credentials to .htpasswd.

Also popular now: