Introduction

DDNS is a good solution for everyone who has dynamic external IP and would like to access his host remotely. To take it into use we need to have an account created by one of DDNS providers and we also need to have relevant client application running on our host PC. Hovewer, if we don't want to use services of DDNS providers, but we have own domain, we can go for an alternative solution. The idea is to create a subdomain, record 'A' of which will direct to the external IP of our host. The only thing which we need to think of is the way how to update the record whenever IP changes. Solution proposed below is based on running a daemon by our host. The daemon periodically monitors for any changes of the external IP. Whenever change is detected, daemon loggs into our Admin Panel, and updates the record for our subdomain. Solutions below show how to apply the idea using Python language.

Problems to be solved

1. How to check the external IP?

It can be solved in one line using urllib2 if we can rely on http://icanhazip.com.

from urllib2 import urlopen
urlopen('http://icanhazip.com').read()[:-1]

2. How to log in to the Admin Panel?

Selenium library seems to be a great solution. An example on how to use it for linuxpl.com is shown below.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver = webdriver.Firefox()

# Login to admin panel
driver.get('https://' + self.domain + ':2223/')
elem = driver.find_element_by_name('username')
elem.send_keys(self.username)
elem = driver.find_element_by_name('password')
elem.send_keys(self.password)
elem.send_keys(Keys.RETURN)

# Go to DNS management page
driver.find_element_by_link_text(self.subdomain).click()
driver.find_element_by_css_selector('a[href*="CMD_DNS_CONTROL"]').click()

# Remove old entry
driver.find_element_by_name('arecs0').click()
driver.find_element_by_name('delete').click()

# Add new entry
elem = driver.find_element_by_name('name')
elem.send_keys(self.subdomain + '.')
elem = driver.find_element_by_name('value')
elem.send_keys(my_ip)
driver.find_element_by_name('add').click()

# Log out
driver.find_element_by_css_selector('a[href*="LOGOUT"]').click()

driver.close()

3. How to make the browser invisible for the user?

It's as simple as creating a virtual display with pyvirtualdisplay.

from pyvirtualdisplay import Display
display = Display(visible=0, size=(800,600))
display.start()
# operate on the browser here
display.stop()

4. How to turn the script into a daemon?

Just take a look on python-daemon library. You're looking for something like this:

from time import sleep
from daemon import runner

class Daemon():
    def __init__(self):
        self.stdin_path = '/dev/null'
        self.stdout_path = '/dev/tty'
        self.stderr_path = '/dev/tty'
        self.pidfile_path = '/var/run/mydaemon.pid'
        self.pidfile_timeout = 5

    def run(self):
        interval = 60*10 # in seconds
        while(1):
            # My stuff
            sleep(interval)

if __name__ == '__main__':
    daemon = Daemon()
    daemon_runner = runner.DaemonRunner(daemon)
    daemon_runner.do_action()

The way how you install the daemon is OS dependent.

Postface

Of course to make the daemon fully usable, you also need to handle all the exceptions which may occure. Additionally you should think of the way on how to store the information about the last IP which has been uploaded. Have fun with coding!