Email your new IP address with TomatoUSB

So my router is now TomatoUSB and I wanted an alert when the IP changed. Sure, I could probably put something local on the router, but where's the fun in that?

So I put together a quick python script to drop me an email if the IP ever changes. Yes, TomatoUSB supports various Dynamic DNS services, but doesn't seem to natively support "email me."

So on the DDNS setup page, I chose the "Custom URL" service, and I put in "http://192.168.90.99/IPCHECKS?new_ip=@IP" as the URL (the internal address of an Apache server running WSGI.

I have a custom config file /etc/httpd/conf.d/wsgi_IP as follows:

WSGIScriptAlias /IPCHECKS /var/www/wsgi/IP.wsgi

<Directory "/var/www/wsgi/">
  WSGIApplicationGroup %{GLOBAL}
  Order deny,allow
  Deny from all
  Allow from 192 127 ::1
</Directory>

HOPEFULLY that means none of you can change what I think my IP address is. ;)

Here's the actual python script (/var/www/wsgi/IP.wsgi):

from __future__ import print_function
from cgi import parse_qs, escape
import socket
import smtplib

# This is RevRagnarok's ugly IP checker.
# Tomato (firmware) will post to us with a "new_ip" parameter
# At this point, I want to see manually that the IPs change, not have it autoupdate
# Note: I had to enable HTTP sending email in SELinux:
# setsebool -P httpd_can_sendmail 1

def application(environ, start_response):
    parameters = parse_qs(environ.get('QUERY_STRING', ''))
    if 'new_ip' in parameters:
        newip = escape(parameters['new_ip'][0])
    else:
        newip = 'Unknown!'
    start_response('200 OK', [('Content-Type', 'text/html')])
    # Look up DNS values
    oldip = socket.gethostbyname('revragnarok.com') # Yes, IPv4 only
    # Compare
    changed = ''
    if newip != oldip:
        changed = 'IP changed from {0} to {1}.'.format(oldip, newip)
    if changed:
        e_from = '[email protected]'
        e_to = ['[email protected]']
        e_msg = """Subject: IP Address change detected

{0}""".format(changed)
        # I considered a try/catch block here, but then what would I do?
        smtpObj = smtplib.SMTP('localhost')
        smtpObj.sendmail(e_from, e_to, e_msg)
    else:
       changed = '(unchanged)'
       changed = 'IP is {0} (unchanged).'.format(newip)
    return [changed]

And don't forget, if you use SELinux, fix permissions on the script, and allow the webserver to send email:

[root@webserver wsgi]# ls -Z IP.wsgi 
-rw-r--r--. root root system_u:object_r:httpd_sys_script_exec_t:s0 IP.wsgi
[root@webserver wsgi]# setsebool -P httpd_can_sendmail 1

Comments

No comments.