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 main.quit() def emp(igd, err, proto, ep, lip, lp, msg): print >> stderr, "ERR" print >> stderr, err, proto, ep, lip, lp, msg main.quit() 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") main.run() if igd.external_ip: print igd.external_ip exit(0) else: exit(1)
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 server 211.14.6.124 zone gniibe.org update delete www.gniibe.org. A update add www.gniibe.org. 600 A $external_ip send EOF fi
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.