Skip to content

Instantly share code, notes, and snippets.

@sphaero
Last active April 6, 2020 16:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sphaero/8423100 to your computer and use it in GitHub Desktop.
Save sphaero/8423100 to your computer and use it in GitHub Desktop.
Simple DynDNS Service using (apache) webserver and DNSMasq
#!/usr/bin/env python
# Simple Dynamic DNS update script for use with DNSMasq
#
# Install this WSGI script on a (apache) webserver. Make sure
# DNSMasq runs as the same user as this script does on the webserver
# E.g: /etc/default/dnsmasq add: (Debian and deriatives)
# DNSMASQ_USER='wsgiuser'
#
# ### DNSMASQ.CONF ###
# domain-needed
# bogus-priv
# filterwin2k
# no-resolv
# no-dhcp-interface=eth0
# bind-interfaces
# no-hosts
# addn-hosts=/tmp/dynhosts
# domain=dyn.z25.org
# expand-hosts
# ### END DNSMASQ.CONF ###
#
# ### APACHE EXAMPLE CONF ###
# # This file defines the apache configuration for the dyndns.example.com domain
# # (change example.com to your own domain name, of course)
# <VirtualHost *:80>
# ServerName dyndns.example.com
# # dyndns interface
# ServerAdmin support@example.com
#
# DocumentRoot /var/www/dyndns/
# WSGIScriptAlias /nic/update /var/www/dyndns/dyn_dns.py
# <Directory /var/www/dyndns/>
# Options FollowSymLinks MultiViews +ExecCGI
# AllowOverride FileInfo
# AddHandler wsgi-script .py
# Order allow,deny
# allow from all
# </Directory>
#
# LogLevel warn
# ErrorLog /var/log/apache2/dyndns.error.log
# CustomLog /var/log/apache2/dyndns.access.log combined
# ServerSignature On
# </VirtualHost>
# ### END APACHE EXAMPLE CONF ###
from cgi import parse_qs, escape
import psutil
import os
import signal
def signal_dnsmasq():
pids = psutil.get_pid_list()
for pid in pids:
if psutil.Process(pid).name == "dnsmasq":
os.kill(pid,signal.SIGHUP)
break
def update_host(hostname, ip):
line_to_update = "%s\t%s\n" %(ip, hostname)
with open('/tmp/dynhosts', 'r') as f:
data = f.readlines()
updated = False
# need to enumerate list iter to update data
for idx, line in enumerate(data):
# split tab delimiter
hn = line.split('\t')[1]
# remove end of line char
hn = hn.split('\n')[0]
if line == line_to_update:
return
elif hn == hostname:
data[idx] = line_to_update
updated = True
if not updated:
data.append(line_to_update)
with open('/tmp/dynhosts', 'w') as f:
f.writelines(data)
signal_dnsmasq()
def dyn_dns_app(environ, start_response):
status = '404 Not Found' # HTTP Status
headers = [('Content-type', 'text/plain')] # HTTP Headers
# The returned object is going to be printed
ip = environ['REMOTE_ADDR']
d = parse_qs(environ['QUERY_STRING'])
hostname = d.get('hostname')
if hostname:
status = '200 OK'
update_host(hostname[0], ip)
start_response(status, headers)
return ["good"]
else:
start_response(status, headers)
return [""]
application = dyn_dns_app
if __name__ == '__main__':
from wsgiref.simple_server import make_server
httpd = make_server('', 8000, dyn_dns_app)
print "Serving on port 8000..."
# Serve until process is killed
httpd.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment