Last active
January 30, 2016 18:37
-
-
Save puntonim/47397cea6fdba03a99b5 to your computer and use it in GitHub Desktop.
SSH tunnel in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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('[email protected]', '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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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('[email protected]', '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