Skip to content

Instantly share code, notes, and snippets.

@puntonim
Last active January 30, 2016 18:37
Show Gist options
  • Save puntonim/47397cea6fdba03a99b5 to your computer and use it in GitHub Desktop.
Save puntonim/47397cea6fdba03a99b5 to your computer and use it in GitHub Desktop.
SSH tunnel in Python
# Create an SSH tunnel in Python.
# In this example we suppose we are in a firewalled network where we cannot
# access GMAIL IMAP server on port 993.
# So we create a tunnel to a machine out of the firewalled network and forward
# to GMAIL IMAP server.
#
# Requirements:
# pip install paramiko
#
# Inspired by:
# https://github.com/paramiko/paramiko/blob/master/demos/forward.py
#
# UPDATE: check the other Gist in this folder!
import paramiko
import select
import time
import thread
try:
import SocketServer
except ImportError:
import socketserver as SocketServer
class Handler(SocketServer.BaseRequestHandler):
def handle(self):
try:
chan = self.ssh_transport.open_channel('direct-tcpip',
(self.chain_host,
self.chain_port),
self.request.getpeername())
except Exception as e:
print('Incoming request to %s:%d failed: %s' % (self.chain_host,
self.chain_port,
repr(e)))
return
if chan is None:
print('Incoming request to %s:%d was rejected by the SSH server.' %
(self.chain_host, self.chain_port))
return
print(
'Connected! Tunnel open %r -> %r -> %r' % (
self.request.getpeername(),
chan.getpeername(), (
self.chain_host,
self.chain_port)))
while True:
r, w, x = select.select([self.request, chan], [], [])
if self.request in r:
data = self.request.recv(1024)
if len(data) == 0:
break
chan.send(data)
if chan in r:
data = chan.recv(1024)
if len(data) == 0:
break
self.request.send(data)
peername = self.request.getpeername()
chan.close()
self.request.close()
print('Tunnel closed from %r' % (peername,))
class Tunnel:
def __init__(self,
remote_address,
remote_port,
remote_username,
remote_password,
remote_forward_address,
remote_forward_port,
local_bind_address,
local_bind_port):
self.remote_address = remote_address
self.remote_port = remote_port
self.remote_username = remote_username
self.remote_password = remote_password
self.remote_forward_address = remote_forward_address
self.remote_forward_port = remote_forward_port
self.local_bind_address = local_bind_address
self.local_bind_port = local_bind_port
def start(self):
self.client = paramiko.SSHClient()
self.client.load_system_host_keys()
self.client.set_missing_host_key_policy(paramiko.WarningPolicy())
self.client.connect(
self.remote_address,
self.remote_port,
username=self.remote_username,
password=self.remote_password,
key_filename=None,
look_for_keys=False)
h = Handler
h.chain_host = self.remote_forward_address
h.chain_port = self.remote_forward_port
h.ssh_transport = self.client.get_transport()
self.forwarder = SocketServer.ThreadingTCPServer(
(self.local_bind_address, self.local_bind_port), h)
self.forwarder.daemon_threads = True
self.forwarder.allow_reuse_address = True
thread.start_new_thread(self.forwarder.serve_forever, ())
time.sleep(.5)
def stop(self):
self.client.close()
self.forwarder.shutdown()
self.forwarder.server_close()
def main():
print 'START'
params = dict(
remote_address='00.84.23.000',
remote_port=443,
remote_username='myself',
remote_password='mypassword',
remote_forward_address='imap.gmail.com',
remote_forward_port=993,
local_bind_address='localhost',
local_bind_port=6666
)
tunnel = Tunnel(**params)
tunnel.start()
print 'STARTING IMAP comunication...'
import imaplib
mail = imaplib.IMAP4_SSL(params['local_bind_address'],
port=params['local_bind_port'])
mail.login('myeamail@gmail.com', 'mygmailpassword')
print mail.list()
tunnel.stop()
print 'Now you can check that there is nothing listening on port {}.'.format(
params['local_bind_port'])
print 'Just run:'
print '$ netstat -an | grep {}'.format(params['local_bind_port'])
_ = raw_input('Press any key to quit: ')
if __name__ == '__main__':
main()
# Create an SSH tunnel in Python.
# In this example we suppose we are in a firewalled network where we cannot
# access GMAIL IMAP server on port 993.
# So we create a tunnel to a machine out of the firewalled network and forward
# to GMAIL IMAP server.
#
# Requirements:
# pip install sshtunnel
from sshtunnel import open_tunnel
import imaplib
params = dict (
ssh_address='00.84.23.000',
ssh_port=443,
ssh_host_key=None,
ssh_username='myusername',
ssh_password='mypassword',
ssh_private_key=None,
remote_bind_address=('imap.gmail.com', 993),
local_bind_address=('localhost', 6666),
)
with open_tunnel(**params):
mail = imaplib.IMAP4_SSL(*params['local_bind_address'])
mail.login('myaddress@gmail.com', 'mygmailpassword')
print mail.list()
print 'Now you can check that there is nothing listening on port {}.'.format(
params['local_bind_address'][1])
print 'Just run:'
print '$ netstat -an | grep {}'.format(params['local_bind_address'][1])
_ = raw_input('Press any key to quit: ')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment