import socket

HOST="192.168.1.1"
PORT=2869

import socket
import fcntl
import struct

# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/439094
def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

xml = """<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:AddPortMapping xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewRemoteHost></NewRemoteHost><NewExternalPort>%d</NewExternalPort><NewProtocol>TCP</NewProtocol><NewInternalPort>22</NewInternalPort><NewInternalClient>%s</NewInternalClient><NewEnabled>1</NewEnabled><NewPortMappingDescription>SSH Tunnel</NewPortMappingDescription><NewLeaseDuration>0</NewLeaseDuration></u:AddPortMapping></s:Body></s:Envelope>

""" % (2200, get_ip_address('eth0'))

packet = """POST /WANIPConnCtrlUrl HTTP/1.1\r
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping"\r
Content-Type: text/xml; charset="utf-8"\r
User-Agent: natb0rk\r
Host: 192.168.1.1:2869\r
Content-Length: %d\r
\r
%s""" % (len(xml), xml)


s.send(packet)

data = s.recv(4096)

if (data[0:12] != 'HTTP/1.1 200'):
    print "** ERROR:\n%s" % (data)
