Pure python SSH tunnels
Project description
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
Requirements
Testing the package
In order to run the tests you first need tox and run:
python setup.py test
Usage scenarios
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 (only port 443 is open) ----------------------------------------------------------------------
Fig2: How to connect to PRIVATE SERVER through SSH tunnel.
Usage examples
API allows either initializing the tunnel and starting it or using a with context, which will take care of starting and stopping the tunnel:
Example 1
Code corresponding to Fig1 above follows, given remote server’s address is pahaz.urfuclub.ru, password authentication and randomly assigned local bind port.
from sshtunnel import SSHTunnelForwarder server = SSHTunnelForwarder( 'pahaz.urfuclub.ru', ssh_username="pahaz", ssh_password="secret", remote_bind_address=('127.0.0.1', 8080) ) server.start() print(server.local_bind_port) # show assigned local port # work with `SECRET SERVICE` through `server.local_bind_port`. server.stop()
Example 2
Example of a port forwarding to a private server not directly reachable, assuming password protected pkey authentication, remote server’s SSH service is listening on port 443 and that port is open in the firewall (Fig2):
import paramiko from sshtunnel import SSHTunnelForwarder with SSHTunnelForwarder( (REMOTE_SERVER_IP, 443), ssh_username="", ssh_pkey="/var/ssh/rsa_key", ssh_private_key_password="secret", remote_bind_address=(PRIVATE_SERVER_IP, 22), local_bind_address=('0.0.0.0', 10022) ) as tunnel: client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramko.AutoAddPolicy()) client.connect('127.0.0.1', 10022) # do some operations with client session client.close() print('FINISH!')
Example 3
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:
(bash)$ python -m sshtunnel -U vagrant -P vagrant -L :3306 -R 127.0.0.1:3306 -p 2222 localhost
CLI usage
$ sshtunnel --help 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 SSH_USERNAME, --username SSH_USERNAME SSH server account username -p SSH_PORT, --server_port SSH_PORT SSH server TCP port (default: 22) -P SSH_PASSWORD, --password SSH_PASSWORD SSH server account password -R IP:PORT [IP:PORT ...], --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 port is omitted, defaults to 22. Example: -R 10.10.10.10: 10.10.10.10:5900 -L [IP:PORT [IP:PORT ...]], --local_bind_address [IP:PORT [IP:PORT ...]] Local bind address sequence: ip_1:port_1 ip_2:port_2 ... ip_n:port_n Elements may also be valid UNIX socket domains: /tmp/foo.sock /tmp/bar.sock ... /tmp/baz.sock 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 SSH_HOST_KEY Gateway's host key -K KEY_FILE, --private_key_file KEY_FILE RSA/DSS/ECDSA private key file -S KEY_PASSWORD, --private_key_password KEY_PASSWORD RSA/DSS/ECDSA private key password -t, --threaded Allow concurrent connections to each tunnel -v, --verbose Increase output verbosity (default: ERROR) -V, --version Show version number and quit -x IP:PORT, --proxy IP:PORT IP and port of SSH proxy to destination -c SSH_CONFIG_FILE, --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
Online documentation
Documentation may be found at readthedocs.
CONTRIBUTORS
CHANGELOG
- v.0.1.1 (JM Fernández)
- Fix #72
- v.0.1.0 (JM Fernández)
- Add tunnel_bindings property
- Several bugfixes (#49, #56, #57, #59, #60, #62, #64, #66, …) (Pahaz Blinov, JM Fernández)
- Add TRACE logging level (JM Fernández)
- Code and tests refactoring (JM Fernández)
- Drop python3.2 support
- v.0.0.8 (JM Fernández)
- Merge #31: Support Unix domain socket (local) forwarding (Dan Harbin)
- Simplify API (JM Fernández)
- Add sphinx-based documentation (JM Fernández)
- Add allow_agent (fixes #36, #46) (JM Fernández)
- Add compression (JM Fernández)
- Add __str__ method (JM Fernández)
- Add test functions (JM Fernández)
- Fix default username when not provided and ssh_config file is skipped (JM Fernández)
- Fix gateway IP unresolvable exception catching (JM Fernández)
- Minor fixes (JM Fernández)
- Add AppVeyor support (JM Fernández)
- v.0.0.7 (JM Fernández)
- Tunnels can now be stopped and started safely (#41) (JM Fernández)
- Add timeout to SSH gateway and keep-alive messages (#29) (JM Fernández)
- Allow sending a pkey directly (#43) (Chronial)
- Add -V CLI option to show current version (JM Fernández)
- Add coverage (JM Fernández)
- Refactoring (JM Fernández)
- v.0.0.6 (Pahaz Blinov)
- add -S CLI options for ssh private key password support (Pahaz Blinov)
- v.0.0.5 (Pahaz Blinov)
- add ssh_proxy argument, as well as ssh_config(5) ProxyCommand support (Lewis Thompson)
- add some python 2.6 compatibility fixes (Mart Sõmermaa)
- paramiko.transport inherits handlers of loggers passed to SSHTunnelForwarder (JM Fernández)
- fix #34, #33, code style and docs (JM Fernández)
- add tests (Pahaz Blinov)
- add CI integration (Pahaz Blinov)
- normal packaging (Pahaz Blinov)
- disable check distenation socket connection by SSHTunnelForwarder.local_is_up (Pahaz Blinov) [changed default behavior]
- use daemon mode = False in all threads by default; detail (Pahaz Blinov) [changed default behavior]
- v.0.0.4.4 (Pahaz Blinov)
- fix issue #24 - hide ssh password in logs (Pahaz Blinov)
- v.0.0.4.3 (Pahaz Blinov)
- fix default port issue #19 (Pahaz Blinov)
- v.0.0.4.2 (Pahaz Blinov)
- fix Thread.daemon mode for Python < 3.3 #16, #21 (Lewis Thompson, Erik Rogers)
- v.0.0.4.1 (Pahaz Blinov)
- fix CLI issues #13 (Pahaz Blinov)
- v.0.0.4 (Pahaz Blinov)
- daemon mode by default for all threads (JM Fernández, Pahaz Blinov) - incompatible
- move make_ssh_forward_server to SSHTunnelForwarder.make_ssh_forward_server (Pahaz Blinov, JM Fernández) - incompatible
- move make_ssh_forward_handler to SSHTunnelForwarder.make_ssh_forward_handler_class (Pahaz Blinov, JM Fernández) - incompatible
- rename open to open_tunnel (JM Fernández) - incompatible
- add CLI interface (JM Fernández)
- support opening several tunnels at once (JM Fernández)
- improve stability and readability (JM Fernández, Pahaz Blinov)
- improve logging (JM Fernández, Pahaz Blinov)
- add raise_exception_if_any_forwarder_have_a_problem argument for opening several tunnels at once (Pahaz Blinov)
- add ssh_config_file argument support (JM Fernández)
- add Python 3 support (JM Fernández, Pahaz Blinov)
- v.0.0.3 (Pahaz Blinov)
- add threaded option (Cameron Maske)
- fix exception error message, correctly printing destination address (Gustavo Machado)
- fix pip install failure (Colin Jermain, Pahaz Blinov)
- v.0.0.1 (Pahaz Blinov)
- SSHTunnelForwarder class (Pahaz Blinov)
- open function (Pahaz Blinov)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size sshtunnel-0.1.2-py2.py3-none-any.whl (27.0 kB) | File type Wheel | Python version py2.py3 | Upload date | Hashes View |
Filename, size sshtunnel-0.1.2.tar.gz (34.4 kB) | File type Source | Python version None | Upload date | Hashes View |
Hashes for sshtunnel-0.1.2-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 61138098403746fc2b6243e96fc03710570d6920af37ea3c6b4005d6df209216 |
|
MD5 | a926d4c4617cc69e8e4184809af28b5e |
|
BLAKE2-256 | e1b0e7f0e1cc62a69a93eea7c2f20913c1e3e8f8abd795fe9155995fdc5a02a0 |