sshtunnel

0.4.0 · active · verified Sat Mar 28

sshtunnel is a pure Python library that enables the creation of secure SSH tunnels, primarily for port forwarding to access services (like databases or web servers) behind a firewall or on a private network. It leverages `paramiko` for SSH capabilities and is actively maintained, with recent releases addressing stability and usability.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to establish an SSH tunnel using `SSHTunnelForwarder` to access a remote service, such as a database. It uses environment variables for secure credential handling. The `with` statement ensures the tunnel is properly started and stopped.

import os
from sshtunnel import SSHTunnelForwarder
import time

# --- Configuration from Environment Variables ---
# SSH Host (the jump server)
SSH_HOST = os.environ.get('SSH_JUMP_HOST', 'your_ssh_jump_host.com')
SSH_PORT = int(os.environ.get('SSH_JUMP_PORT', '22'))
SSH_USERNAME = os.environ.get('SSH_JUMP_USER', 'your_ssh_user')
SSH_PASSWORD = os.environ.get('SSH_JUMP_PASSWORD', '') # Optional, use SSH keys preferrably
SSH_PKEY = os.environ.get('SSH_JUMP_PKEY_PATH', '~/.ssh/id_rsa') # Path to private key
SSH_PKEY_PASSWD = os.environ.get('SSH_JUMP_PKEY_PASSWD', '') # Password for private key, if encrypted

# Remote Bind Address (the actual service you want to reach, from the perspective of the SSH Host)
REMOTE_BIND_HOST = os.environ.get('DB_HOST_PRIVATE_IP', '10.0.0.5')
REMOTE_BIND_PORT = int(os.environ.get('DB_PORT', '5432')) # e.g., 5432 for PostgreSQL, 3306 for MySQL

# Local Bind Address (where the tunnel will be accessible on your local machine)
LOCAL_BIND_HOST = os.environ.get('LOCAL_TUNNEL_HOST', '127.0.0.1')
LOCAL_BIND_PORT = int(os.environ.get('LOCAL_TUNNEL_PORT', 'auto')) # 'auto' for a random available port

# Example of connecting to a PostgreSQL database via an SSH tunnel
try:
    with SSHTunnelForwarder(
        (SSH_HOST, SSH_PORT),
        ssh_username=SSH_USERNAME,
        ssh_password=SSH_PASSWORD if SSH_PASSWORD else None,
        ssh_pkey=SSH_PKEY if os.path.exists(os.path.expanduser(SSH_PKEY)) else None,
        ssh_private_key_password=SSH_PKEY_PASSWD if SSH_PKEY_PASSWD else None,
        remote_bind_address=(REMOTE_BIND_HOST, REMOTE_BIND_PORT),
        local_bind_address=(LOCAL_BIND_HOST, LOCAL_BIND_PORT) if LOCAL_BIND_PORT != 'auto' else (LOCAL_BIND_HOST, 0)
    ) as tunnel:
        print(f"SSH tunnel established. Local port: {tunnel.local_bind_port}")
        print(f"Accessing {REMOTE_BIND_HOST}:{REMOTE_BIND_PORT} via localhost:{tunnel.local_bind_port}")

        # In a real application, you would now connect your database client to:
        # host='127.0.0.1', port=tunnel.local_bind_port
        # For demonstration, we just keep the tunnel open for a few seconds.
        print("Tunnel active for 10 seconds. Press Ctrl+C to stop sooner.")
        time.sleep(10)
        print("Tunnel closing.")

except Exception as e:
    print(f"An error occurred: {e}")
    print("Please check your SSH configuration, network connectivity, and credentials.")

view raw JSON →