Let us create a local port forwarding script that will redirect all traffic received at port 8800 to the Google home page (http://www.google.com). We can pass the local and remote host as well as port number to this script. For the sake of simplicity, let's only specify the local port number as we are aware that the web server runs on port 80.
Listing 3.1 shows a port forwarding example, as follows:
#!/usr/bin/env python # Python Network Programming Cookbook, Second Edition -- Chapter - 3 # This program is optimized for Python 2.7.12 and Python 3.5.2. # It may run on any other version with/without modifications. import argparse LOCAL_SERVER_HOST = 'localhost' REMOTE_SERVER_HOST = 'www.google.com' BUFSIZE = 4096 import asyncore import socket class PortForwarder(asyncore.dispatcher): def __init__(self, ip, port, remoteip,remoteport,backlog=5): asyncore.dispatcher.__init__(self) self.remoteip=remoteip self.remoteport=remoteport self.create_socket(socket.AF_INET,socket.SOCK_STREAM) self.set_reuse_addr() self.bind((ip,port)) self.listen(backlog) def handle_accept(self): conn, addr = self.accept() print ("Connected to:",addr) Sender(Receiver(conn),self.remoteip,self.remoteport) class Receiver(asyncore.dispatcher): def __init__(self,conn): asyncore.dispatcher.__init__(self,conn) self.from_remote_buffer='' self.to_remote_buffer='' self.sender=None def handle_connect(self): pass def handle_read(self): read = self.recv(BUFSIZE) self.from_remote_buffer += read def writable(self): return (len(self.to_remote_buffer) > 0) def handle_write(self): sent = self.send(self.to_remote_buffer) self.to_remote_buffer = self.to_remote_buffer[sent:] def handle_close(self): self.close() if self.sender: self.sender.close() class Sender(asyncore.dispatcher): def __init__(self, receiver, remoteaddr,remoteport): asyncore.dispatcher.__init__(self) self.receiver=receiver receiver.sender=self self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((remoteaddr, remoteport)) def handle_connect(self): pass def handle_read(self): read = self.recv(BUFSIZE) self.receiver.to_remote_buffer += read def writable(self): return (len(self.receiver.from_remote_buffer) > 0) def handle_write(self): sent = self.send(self.receiver.from_remote_buffer) self.receiver.from_remote_buffer = self.receiver.
from_remote_buffer[sent:] def handle_close(self): self.close() self.receiver.close() if __name__ == "__main__": parser = argparse.ArgumentParser(description='Stackless
Socket Server Example') parser.add_argument('--local-host', action="store",
dest="local_host", default=LOCAL_SERVER_HOST) parser.add_argument('--local-port', action="store",
dest="local_port", type=int, required=True) parser.add_argument('--remote-host', action="store",
dest="remote_host", default=REMOTE_SERVER_HOST) parser.add_argument('--remote-port', action="store",
dest="remote_port", type=int, default=80) given_args = parser.parse_args() local_host, remote_host = given_args.local_host,
given_args.remote_host local_port, remote_port = given_args.local_port,
given_args.remote_port print ("Starting port forwarding local %s:%s => remote
%s:%s" % (local_host, local_port, remote_host, remote_port)) PortForwarder(local_host, local_port, remote_host, remote_port) asyncore.loop()
If you run this script, it will show the following output:
$ python 13_1_port_forwarding.py --local-port=8800 Starting port forwarding local localhost:8800 => remote www.google.com:80
Now, open your browser and visit http://localhost:8800. This will take you to the Google home page and the script will print something similar to the following command:
('Connected to:', ('127.0.0.1', 37236))
The following screenshot shows the forwarding of a local port to a remote host:
Port Forwarding to Remote Host