Skip to main content

CI pyversions version license

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

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(...)

Metadata

Release files for deepnote-sshtunnel 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for deepnote-sshtunnel 1.0.0
File Size Uploaded
deepnote_sshtunnel-1.0.0.tar.gz 23.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for deepnote-sshtunnel 1.0.0
File Interpreter ABI Platform
deepnote_sshtunnel-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.7 kB

Release files / deepnote_sshtunnel-1.0.0.tar.gz

Download URL deepnote_sshtunnel-1.0.0.tar.gz
Size 23.0 kB
Tags Source
SHA-256 checksum
How to use checksums
106c7a0cc8a2ea6e74eceb359f54e6e25c8235e2bb7479306d72109a7059e73d
BLAKE2b-256 checksum
How to use checksums
7257417696060bf831ab16049f97024b631788337d20bd600180a951a4334aa2
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release files / deepnote_sshtunnel-1.0.0-py3-none-any.whl

Download URL deepnote_sshtunnel-1.0.0-py3-none-any.whl
Size 20.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
398ab4f13eddeb5fa20ca9a6d79d57b8959fd7be999c901fe1f38bc13b1c20ea
BLAKE2b-256 checksum
How to use checksums
5422c724cbe83eb07aa49d93d1c22973418ac5fceabeaad8d714adfef7d92d13
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page