Author: Pahaz Blinov
Repo: https://github.com/pahaz/sshtunnel/
Inspired by https://github.com/jmagnusson/bgtunnel, but it doesn't work on Windows.
See also: https://github.com/paramiko/paramiko/blob/master/demos/forward.py
sshtunnel is on PyPI, so simply run:
pip install sshtunnel
or
easy_install sshtunnel
to have it installed in your environment.
For installing from source, clone the repo and run:
python setup.py install
In order to run the tests you first need tox and run:
python setup.py test
One of the typical scenarios where sshtunnel
is helpful is depicted in the
figure below. User may need to connect a port of a remote server (i.e. 8080)
where only SSH port (usually port 22) is reachable.
---------------------------------------------------------------------- | -------------+ | +----------+ LOCAL | | | REMOTE | :22 SSH CLIENT | <== SSH ========> | SERVER | :8080 web service -------------+ | +----------+ | FIREWALL (only port 22 is open) ----------------------------------------------------------------------
Fig1: How to connect to a service blocked by a firewall through SSH tunnel.
If allowed by the SSH server, it is also possible to reach a private server
(from the perspective of REMOTE SERVER
) not directly visible from the
outside (LOCAL CLIENT
's perspective).
---------------------------------------------------------------------- | -------------+ | +----------+ +--------- LOCAL | | | REMOTE | | PRIVATE CLIENT | <== SSH ========> | SERVER | <== local ==> | SERVER -------------+ | +----------+ +--------- | FIREWALL ----------------------------------------------------------------------
Fig2: How to connect to PRIVATE SERVER
through SSH tunnel.
API allows either initializing the tunnel and starting it or using a with
context, which will take care of starting and stopping the tunnel:
from sshtunnel import SSHTunnelForwarder
server = SSHTunnelForwarder(
('pahaz.urfuclub.ru', 22),
ssh_username="pahaz",
ssh_password="secret",
remote_bind_address=('127.0.0.1', 5555)
)
server.start()
print(server.local_bind_port)
# work with `SECRET SERVICE` through `server.local_bind_port`.
server.stop()
Example of a port forwarding for the Vagrant MySQL local port:
from sshtunnel import SSHTunnelForwarder
from time import sleep
with SSHTunnelForwarder(
('localhost', 2222),
ssh_username="vagrant",
ssh_password="vagrant",
remote_bind_address=('127.0.0.1', 3306)
) as server:
print(server.local_bind_port)
while True:
# press Ctrl-C for stopping
sleep(1)
print('FINISH!')
Or simply using the CLI:
$ python -m sshtunnel -U vagrant -P vagrant -L :3306 -R 127.0.0.1:3306 -p 2222 localhost
usage: sshtunnel [-h] [-U SSH_USERNAME] [-p SSH_PORT] [-P SSH_PASSWORD] -R IP:PORT [IP:PORT ...] [-L [IP:PORT [IP:PORT ...]]] [-k SSH_HOST_KEY] [-K KEY_FILE] [-S KEY_PASSWORD] [-t] [-v] [-V] [-x IP:PORT] [-c SSH_CONFIG_FILE] [-z] [-n] ssh_address Pure python ssh tunnel utils positional arguments: ssh_address SSH server IP address (GW for ssh tunnels) set with "-- ssh_address" if immediately after -R or -L optional arguments: -h, --help show this help message and exit -U, --username SSH_USERNAME SSH server account username -p, --server_port SSH_PORT SSH server TCP port (default: 22) -P, --password SSH_PASSWORD SSH server account password -R, --remote_bind_address IP:PORT [IP:PORT ...] Remote bind address sequence: ip_1:port_1 ip_2:port_2 ... ip_n:port_n Equivalent to ssh -Lxxxx:IP_ADDRESS:PORT If omitted, default port is 22. Example: -R 10.10.10.10: 10.10.10.10:5900 -L, --local_bind_address [IP:PORT [IP:PORT ...]] Local bind address sequence: ip_1:port_1 ip_2:port_2 ... ip_n:port_n Equivalent to ssh -LPORT:xxxxxxxxx:xxxx, being the local IP address optional. By default it will listen in all interfaces (0.0.0.0) and choose a random port. Example: -L :40000 -k, --ssh_host_key SSH_HOST_KEY Gateway's host key -K, --private_key_file KEY_FILE RSA/DSS/ECDSA private key file -S, --private_key_file_password KEY_PASSWORD RSA/DSS/ECDSA private key password -t, --threaded Allow concurrent connections to each tunnel -v, --verbosity Increase output verbosity (default: ERROR) -V, --version Show version number and quit -x, --proxy IP:PORT IP and por for SSH proxy to destination -c, --config SSH_CONFIG_FILE SSH configuration file, defaults to ~/.ssh/config -z, --compress Request server for compression over SSH transport -n, --noagent Disable looking for keys from an SSH agent