UPnP and running a web service behind firewall

Here, I describe what I did now, but it seems that I need to run gupnp.igd process to watch change of external IP address...

UPnP Python Script

I wrote a python script to update port forwarding of my home router. It sets three port forwardings, one is external:80 to internal:8080 for HTTP, another is external:9418 to internal:9418 for Git, and the other is external:22 to internal:22 for SSH. Here is the code.

#! /usr/bin/python
import gupnp.igd
import glib
from sys import stderr, argv

my_ip = argv[1]

igd = gupnp.igd.Simple()
igd.external_ip = None

main = glib.MainLoop()

def mep(igd, proto, eip, erip, port, localip, lport, msg):
    if port == 80:
        igd.external_ip = eip

def emp(igd, err, proto, ep, lip, lp, msg):
    print >> stderr, "ERR"
    print >> stderr, err, proto, ep, lip, lp, msg

igd.connect("mapped-external-port", mep)
igd.connect("error-mapping-port", emp)
igd.add_port("TCP", 80, my_ip, 8080, 0, "web")
igd.add_port("TCP", 9418, my_ip, 9418, 0, "git")
igd.add_port("TCP", 22, my_ip, 22, 0, "ssh")


if igd.external_ip:
    print igd.external_ip

Output is the external IP address of the router.

Dhclient exit hook

As explained in the article nsupdate for a machine behind firewall with dynamic IP address, I have a script named /etc/dhcp/dhclient-exit-hooks.d/upnp+nsupdate. All content of the file is like following:

#! /bin/sh
cd /home/gniibe/dynamic-ip

if ./upnp_setup.py $new_ip_address >/tmp/external_ip; then
   read external_ip < /tmp/external_ip
   nsupdate -k Kwww.gniibe.org.+008+34054.private <<EOF
zone gniibe.org
update delete www.gniibe.org. A
update add www.gniibe.org. 600 A $external_ip

That is, when it gets IP address by a DHCP server (== the router), it executes upnp_setup.py script to update port forwardings. The script outputs routers external IP address. With the external IP address, it invokes nsupdate to update DNS A entry of www.gniibe.org.