#!/usr/bin/python
import optparse
import signal
import sys
import logging
import gevent
from gevent.server import StreamServer
from gevent.socket import create_connection, gethostbyname
DEBUG = False
class Logger:
def __init__(self, name, stdout):
self.logger = logging.getLogger('')
self.logger.setLevel(logging.DEBUG)
if stdout:
the_format = "%(asctime)s\t%(levelname)s\t%(message)s"
logging.basicConfig(format=the_format)
def get_logger(self):
return self.logger
class PortForwarder(StreamServer):
def __init__(self, source, dest, logger, **kwargs):
StreamServer.__init__(self, source, **kwargs)
self.source = source
self.dest = dest
self.logger = logger
self.closed = False
self.output_socket = None
def handle(self, source, address):
self.logger.info('{0}:{1} accepted'.format(address[0], address[1]))
try:
if not self.output_socket:
self.output_socket = create_connection(self.dest)
gevent.spawn(join, source, self.output_socket, self.logger)
gevent.spawn(join, self.output_socket, source, self.logger)
except IOError as ex:
self.logger.info('{0}:{1} failed to connect to {2}:{3} - {4}'.format(address[0], address[1], self.dest[0], self.dest[1], ex))
return
def close(self):
if self.closed:
self.logger.info('Multiple exit signals received - aborting.')
sys.exit(0)
else:
self.logger.info('Closing listener socket')
#StreamServer.close(self)
def join(input_socket, output_socket, logger):
try:
if DEBUG:
input_destination = "{0}:{1}".format(input_socket.getsockname()[0], input_socket.getsockname()[1])
output_destination = "{0}:{1}".format(output_socket.getsockname()[0], output_socket.getsockname()[1])
logger.info("{0} -> {1}".format(input_destination, output_destination))
while True:
data = input_socket.recv(1024)
if not data:
break
output_socket.sendall(data)
except Exception as e:
logger.info("Exception encounted: {0}".format(e))
finally:
input_socket.close()
output_socket.close()
def get_opts():
p = optparse.OptionParser()
p.add_option('--remoteHost', default=None, dest='remote_host', help='Remote host name')
p.add_option('--remotePort', default=None, dest='remote_port', help='Remote port')
p.add_option('--localHost', default=None, dest='local_host', help='Local host name')
p.add_option('--localPort', default=None, dest='local_port', help='Local port')
(opts, args) = p.parse_args()
if opts.remote_port is None or opts.local_port is None:
p.print_help()
sys.exit(1)
return opts
if __name__ == "__main__":
opts = get_opts()
logger = Logger('Tunnel', True)
source = (opts.local_host, int(opts.local_port))
dest = (opts.remote_host, int(opts.remote_port))
server = PortForwarder(source, dest, logger.get_logger())
logger.get_logger().info("Starting port forwarder {0}:{1} -> {2}:{3}".format(source[0], source[1], dest[0], dest[1]))
gevent.signal(signal.SIGTERM, server.close)
gevent.signal(signal.SIGINT, server.close)
try:
gevent.joinall([
server.serve_forever()
])
except KeyboardInterrupt as e:
logger.get_logger().info("Shutting down.")
except Exception as e:
logger.get_logger().info("Unknown exception: '{0}'".format(e))
finally:
server.stop()
Recent Comments