Pure python SSH tunnels (Deepnote fork)
Project description
deepnote-sshtunnel – Pure python SSH tunnels
This is a Deepnote fork of pahaz/sshtunnel with the following changes:
Python 3.10+ only (dropped Python 2 and older 3.x support)
paramiko 3, 4, and 5 compatibility (removed deprecated DSA/DSSKey support)
Modern packaging with pyproject.toml, hatchling, and uv
GitHub Actions CI and trusted PyPI publishing
Original author: Pahaz
Upstream repo: https://github.com/pahaz/sshtunnel/
Requirements
paramiko >= 3.4
Python >= 3.10
Installation
deepnote-sshtunnel is on PyPI, so simply run:
pip install deepnote-sshtunnel
or:
uv add deepnote-sshtunnel
The import name remains sshtunnel for drop-in compatibility:
from sshtunnel import SSHTunnelForwarder
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(
'alfa.8iq.dev',
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
import sshtunnel
with sshtunnel.open_tunnel(
(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(paramiko.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 open_tunnel
from time import sleep
with open_tunnel(
('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
Example 4
Opening an SSH session jumping over two tunnels. SSH transport and tunnels will be daemonised, which will not wait for the connections to stop at close time.
import sshtunnel
from paramiko import SSHClient
with sshtunnel.open_tunnel(
ssh_address_or_host=('GW1_ip', 20022),
remote_bind_address=('GW2_ip', 22),
) as tunnel1:
print('Connection to tunnel1 (GW1_ip:GW1_port) OK...')
with sshtunnel.open_tunnel(
ssh_address_or_host=('localhost', tunnel1.local_bind_port),
remote_bind_address=('target_ip', 22),
ssh_username='GW2_user',
ssh_password='GW2_pwd',
) as tunnel2:
print('Connection to tunnel2 (GW2_ip:GW2_port) OK...')
with SSHClient() as ssh:
ssh.connect('localhost',
port=tunnel2.local_bind_port,
username='target_user',
password='target_pwd',
)
ssh.exec_command(...)
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.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file deepnote_sshtunnel-1.0.0.tar.gz.
File metadata
- Download URL: deepnote_sshtunnel-1.0.0.tar.gz
- Upload date:
- Size: 23.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
106c7a0cc8a2ea6e74eceb359f54e6e25c8235e2bb7479306d72109a7059e73d
|
|
| MD5 |
6ee8a57fae5cd9f530e5c55c276cdd08
|
|
| BLAKE2b-256 |
7257417696060bf831ab16049f97024b631788337d20bd600180a951a4334aa2
|
File details
Details for the file deepnote_sshtunnel-1.0.0-py3-none-any.whl.
File metadata
- Download URL: deepnote_sshtunnel-1.0.0-py3-none-any.whl
- Upload date:
- Size: 20.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
398ab4f13eddeb5fa20ca9a6d79d57b8959fd7be999c901fe1f38bc13b1c20ea
|
|
| MD5 |
67162a6310c30cc4b2f3f79796b1bad2
|
|
| BLAKE2b-256 |
5422c724cbe83eb07aa49d93d1c22973418ac5fceabeaad8d714adfef7d92d13
|