No-IP Dynamic DNS

Using a PHP script to update your dynamic DNS record at No-IP.org

This article can help in case your router holding a public IP address can neither be put into bridge mode nor it supports updating dynamic DNS records through its firmware.

What you need

You need a web server that can execute PHP scripts (Apache Httpd, Nginx, etc.) and a device connected to the Internet (for example, a MikroTik router or a computer with an Internet browser).

Setting up an Nginx web server and deploying the PHP script

This example uses the CentOS 7.5 operating system and an Nginx web server with PHP FPM to run the PHP script. The first step would be to install all the necessary packages. Since Nginx doesn't come in the default CentOS 7 repositories, it is necessary to add a new repository. This will make future updates easy. Create a file named /etc/yum.repos.d/nginx.repo with your favorite text editor and copy and paste the below configuration.

1
2
3
4
5
[nginx]
name=Nginx Mainline Repository
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1

When you execute the yum repolist command, you should get something like shown below. The Nginx Mainline Repository should show a number of packages greater then zero (usually around 500 packages).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
[root@cota]# yum repolist
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.coreix.net
 * epel: mirrors.coreix.net
 * extras: centos.serverspace.co.uk
 * updates: mirrors.coreix.net
 * webtatic: uk.repo.webtatic.com
repo id                                                      repo name                                                                                  status
!base/7/x86_64                                               CentOS-7 - Base                                                                            10,019
!epel/x86_64                                                 Extra Packages for Enterprise Linux 7 - x86_64                                             13,194
!extras/7/x86_64                                             CentOS-7 - Extras                                                                             413
!nginx/x86_64                                                Nginx Mainline Repository                                                                     537
!pgdg95/7/x86_64                                             PostgreSQL 9.5 7 - x86_64                                                                     654
!updates/7/x86_64                                            CentOS-7 - Updates                                                                          1,945
!webtatic/x86_64                                             Webtatic Repository EL7 - x86_64                                                              363
repolist: 27,125

When you've verified that the Nginx repository has been set up, install the required packages as shown below.

1
yum -y install nginx php-fpm httpd-tools

Enable the Nginx and PHP FPM services. The --now option can be used with the systemctl command to start the services right away (apart from enabling it on system startup).

1
2
systemctl enable nginx --now
systemctl enable php-fpm --now

Protect the path /var/www/html/update-ip-address.php using a simple HTTP authentication method. The htpasswd command will prompt you for a password. Use a strong password to avoid unauthorized change requests.

1
htpasswd -c /etc/nginx/.htpasswd updateip

Also, edit the default.conf file to make the system ask for a password before executing the script.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
server {
    # ...omitted for brevity
    location ~ update-ip-address/?$ {
        auth_basic_user_file /etc/nginx/.htpasswd;
        auth_basic "Restricted Access";
        try_files /update-ip-address.php =404;
        fastcgi_pass unix:/run/php-fpm/www.sock;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    # ...omitted for brevity
}

Create a file /var/www/html/update-ip-address.php, copy the below code, and save it. If you have SELinux enabled (on by default on a minimal CentOS 7 installation), restore the appropriate SELinux context like this: restorecon -v /var/www/html/update-ip-address.php.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php
    function httpRequest($url, $method="GET", $headers=array(), $postfields=array()) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        if(!empty($headers)) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        if($method == "POST") {
            curl_setopt($curl, CURLOPT_POST, TRUE);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $postfields);
        }
        else {
            curl_setopt($curl, CURLOPT_HTTPGET, TRUE);
        }
        $result = curl_exec($curl);
        curl_close($curl);
        return $result;
    }

    $hostname = "your-domain.no-ip.org";
    $username = "your-no-ip-username";
    $password = "Pyour-no-ip-password";
    $base64 = base64_encode("$username:$password");
    $authorization = "Authorization: Basic $base64";
    $userAgent = "User-Agent: LukaSostaric Update Client/v1.0";
    $oldIP = gethostbyname($hostname);
    $newIP = $_SERVER["REMOTE_ADDR"];
    $url = "https://dynupdate.no-ip.com/nic/update?hostname=$hostname&myip=$newIP";

    if($newIP != $oldIP) {
        $response = httpRequest($url, "GET", array($authorization, $userAgent));
        echo $response;
    }
    else {
        echo "The IP address has not changed! No need to update it.";
    }
?>

Test your script by visiting https://your-vps-ip/update-ip-address.php. If everything has been set up correctly, you should get a 200 response from your web server and a message like, "The IP address hasn't changed. No need to update it," or "good new-IP-address".