You have to use a little trick. If you know the IP address and port of the peer you want to connect to, say 192.168.1.2:8081 , then you can punch the hole by connecting directly to it (using the same IP, of course) and telling it what your real IP is:
import socket
peer_ip = "192.168.1.2"
peer_port = 8081
my_ip = "192.168.1.1"
my_port = 8080
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((peer_ip, peer_port))
sock.send("OPEN %s:%d\n" % (my_ip, my_port))
If you connect to it then the firewall should open a port from your IP address to the peer's IP address and port that you specified in the OPEN command (this is a TCP hole punch protocol called ASYNC3 , which is described on the Async3 website).
To test this, you can use nc to connect to the peer and say hi. This should work if you are behind a NAT and have a firewall (even if it's not the same firewall that opened the hole):
$ nc 192.168.1.2 8081
hello, world!