{"id":13825878,"url":"https://github.com/pahaz/sshtunnel","last_synced_at":"2025-05-14T00:06:55.887Z","repository":{"id":17835468,"uuid":"20744134","full_name":"pahaz/sshtunnel","owner":"pahaz","description":"SSH tunnels to remote server.","archived":false,"fork":false,"pushed_at":"2024-03-10T15:20:42.000Z","size":507,"stargazers_count":1257,"open_issues_count":69,"forks_count":186,"subscribers_count":29,"default_branch":"master","last_synced_at":"2025-05-05T08:41:38.200Z","etag":null,"topics":["python","ssh","tunnel"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pahaz.png","metadata":{"files":{"readme":"README.rst","changelog":"changelog.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2014-06-11T21:14:05.000Z","updated_at":"2025-04-29T00:41:24.000Z","dependencies_parsed_at":"2024-01-07T22:49:04.480Z","dependency_job_id":"cb4db25a-7c0a-4c98-a621-8eb99404881b","html_url":"https://github.com/pahaz/sshtunnel","commit_stats":{"total_commits":335,"total_committers":25,"mean_commits":13.4,"dds":0.6179104477611941,"last_synced_commit":"d2167a235bf67c24c77786ddbd81e0dca2baec63"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pahaz%2Fsshtunnel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pahaz%2Fsshtunnel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pahaz%2Fsshtunnel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pahaz%2Fsshtunnel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pahaz","download_url":"https://codeload.github.com/pahaz/sshtunnel/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253645073,"owners_count":21941311,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python","ssh","tunnel"],"created_at":"2024-08-04T09:01:28.501Z","updated_at":"2025-05-14T00:06:55.871Z","avatar_url":"https://github.com/pahaz.png","language":"Python","funding_links":[],"categories":["\u003ca id=\"01e6651181d405ecdcd92a452989e7e0\"\u003e\u003c/a\u003e工具","Python (1887)","Infrastructure \u0026 DevOps","Python","python"],"sub_categories":["\u003ca id=\"9d6789f22a280f5bb6491d1353b02384\"\u003e\u003c/a\u003e隧道\u0026\u0026穿透"],"readme":"|CircleCI| |AppVeyor| |readthedocs| |coveralls| |version|\n\n|pyversions| |license|\n\n**Author**: `Pahaz`_\n\n**Repo**: https://github.com/pahaz/sshtunnel/\n\nInspired by https://github.com/jmagnusson/bgtunnel, which doesn't work on\nWindows.\n\nSee also: https://github.com/paramiko/paramiko/blob/master/demos/forward.py\n\nRequirements\n-------------\n\n* `paramiko`_\n\nInstallation\n============\n\n`sshtunnel`_ is on PyPI, so simply run:\n\n::\n\n    pip install sshtunnel\n\nor ::\n\n    easy_install sshtunnel\n\nor ::\n\n    conda install -c conda-forge sshtunnel\n\nto have it installed in your environment.\n\nFor installing from source, clone the\n`repo \u003chttps://github.com/pahaz/sshtunnel\u003e`_ and run::\n\n    python setup.py install\n\nTesting the package\n-------------------\n\nIn order to run the tests you first need\n`tox \u003chttps://testrun.org/tox/latest/\u003e`_ and run::\n\n    python setup.py test\n\nUsage scenarios\n===============\n\nOne of the typical scenarios where ``sshtunnel`` is helpful is depicted in the\nfigure below. User may need to connect a port of a remote server (i.e. 8080)\nwhere only SSH port (usually port 22) is reachable. ::\n\n    ----------------------------------------------------------------------\n\n                                |\n    -------------+              |    +----------+\n        LOCAL    |              |    |  REMOTE  | :22 SSH\n        CLIENT   | \u003c== SSH ========\u003e |  SERVER  | :8080 web service\n    -------------+              |    +----------+\n                                |\n                             FIREWALL (only port 22 is open)\n\n    ----------------------------------------------------------------------\n\n**Fig1**: How to connect to a service blocked by a firewall through SSH tunnel.\n\n\nIf allowed by the SSH server, it is also possible to reach a private server\n(from the perspective of ``REMOTE SERVER``) not directly visible from the\noutside (``LOCAL CLIENT``'s perspective). ::\n\n    ----------------------------------------------------------------------\n\n                                |\n    -------------+              |    +----------+               +---------\n        LOCAL    |              |    |  REMOTE  |               | PRIVATE\n        CLIENT   | \u003c== SSH ========\u003e |  SERVER  | \u003c== local ==\u003e | SERVER\n    -------------+              |    +----------+               +---------\n                                |\n                             FIREWALL (only port 443 is open)\n\n    ----------------------------------------------------------------------\n\n**Fig2**: How to connect to ``PRIVATE SERVER`` through SSH tunnel.\n\n\nUsage examples\n==============\n\nAPI allows either initializing the tunnel and starting it or using a ``with``\ncontext, which will take care of starting **and stopping** the tunnel:\n\nExample 1\n---------\n\nCode corresponding to **Fig1** above follows, given remote server's address is\n``pahaz.urfuclub.ru``, password authentication and randomly assigned local bind\nport.\n\n.. code-block:: python\n\n    from sshtunnel import SSHTunnelForwarder\n\n    server = SSHTunnelForwarder(\n        'alfa.8iq.dev',\n        ssh_username=\"pahaz\",\n        ssh_password=\"secret\",\n        remote_bind_address=('127.0.0.1', 8080)\n    )\n\n    server.start()\n\n    print(server.local_bind_port)  # show assigned local port\n    # work with `SECRET SERVICE` through `server.local_bind_port`.\n\n    server.stop()\n\nExample 2\n---------\n\nExample of a port forwarding to a private server not directly reachable,\nassuming password protected pkey authentication, remote server's SSH service is\nlistening on port 443 and that port is open in the firewall (**Fig2**):\n\n.. code-block:: python\n\n    import paramiko\n    import sshtunnel\n\n    with sshtunnel.open_tunnel(\n        (REMOTE_SERVER_IP, 443),\n        ssh_username=\"\",\n        ssh_pkey=\"/var/ssh/rsa_key\",\n        ssh_private_key_password=\"secret\",\n        remote_bind_address=(PRIVATE_SERVER_IP, 22),\n        local_bind_address=('0.0.0.0', 10022)\n    ) as tunnel:\n        client = paramiko.SSHClient()\n        client.load_system_host_keys()\n        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())\n        client.connect('127.0.0.1', 10022)\n        # do some operations with client session\n        client.close()\n\n    print('FINISH!')\n\nExample 3\n---------\n\nExample of a port forwarding for the Vagrant MySQL local port:\n\n.. code-block:: python\n\n    from sshtunnel import open_tunnel\n    from time import sleep\n\n    with open_tunnel(\n        ('localhost', 2222),\n        ssh_username=\"vagrant\",\n        ssh_password=\"vagrant\",\n        remote_bind_address=('127.0.0.1', 3306)\n    ) as server:\n\n        print(server.local_bind_port)\n        while True:\n            # press Ctrl-C for stopping\n            sleep(1)\n\n    print('FINISH!')\n\nOr simply using the CLI:\n\n.. code-block:: console\n\n    (bash)$ python -m sshtunnel -U vagrant -P vagrant -L :3306 -R 127.0.0.1:3306 -p 2222 localhost\n\nExample 4\n---------\n\nOpening an SSH session jumping over two tunnels. SSH transport and tunnels\nwill be daemonised, which will not wait for the connections to stop at close\ntime.\n\n.. code-block:: python\n\n    import sshtunnel\n    from paramiko import SSHClient\n\n\n    with sshtunnel.open_tunnel(\n        ssh_address_or_host=('GW1_ip', 20022),\n        remote_bind_address=('GW2_ip', 22),\n    ) as tunnel1:\n        print('Connection to tunnel1 (GW1_ip:GW1_port) OK...')\n        with sshtunnel.open_tunnel(\n            ssh_address_or_host=('localhost', tunnel1.local_bind_port),\n            remote_bind_address=('target_ip', 22),\n            ssh_username='GW2_user',\n            ssh_password='GW2_pwd',\n        ) as tunnel2:\n            print('Connection to tunnel2 (GW2_ip:GW2_port) OK...')\n            with SSHClient() as ssh:\n                ssh.connect('localhost',\n                    port=tunnel2.local_bind_port,\n                    username='target_user',\n                    password='target_pwd',\n                )\n                ssh.exec_command(...)\n\n\nCLI usage\n=========\n\n::\n\n    $ sshtunnel --help\n    usage: sshtunnel [-h] [-U SSH_USERNAME] [-p SSH_PORT] [-P SSH_PASSWORD] -R\n                     IP:PORT [IP:PORT ...] [-L [IP:PORT ...]] [-k SSH_HOST_KEY]\n                     [-K KEY_FILE] [-S KEY_PASSWORD] [-t] [-v] [-V] [-x IP:PORT]\n                     [-c SSH_CONFIG_FILE] [-z] [-n] [-d [FOLDER ...]]\n                     ssh_address\n\n    Pure python ssh tunnel utils\n    Version 0.4.0\n\n    positional arguments:\n      ssh_address           SSH server IP address (GW for SSH tunnels)\n                            set with \"-- ssh_address\" if immediately after -R or -L\n\n    options:\n      -h, --help            show this help message and exit\n      -U SSH_USERNAME, --username SSH_USERNAME\n                            SSH server account username\n      -p SSH_PORT, --server_port SSH_PORT\n                            SSH server TCP port (default: 22)\n      -P SSH_PASSWORD, --password SSH_PASSWORD\n                            SSH server account password\n      -R IP:PORT [IP:PORT ...], --remote_bind_address IP:PORT [IP:PORT ...]\n                            Remote bind address sequence: ip_1:port_1 ip_2:port_2 ... ip_n:port_n\n                            Equivalent to ssh -Lxxxx:IP_ADDRESS:PORT\n                            If port is omitted, defaults to 22.\n                            Example: -R 10.10.10.10: 10.10.10.10:5900\n      -L [IP:PORT ...], --local_bind_address [IP:PORT ...]\n                            Local bind address sequence: ip_1:port_1 ip_2:port_2 ... ip_n:port_n\n                            Elements may also be valid UNIX socket domains:\n                            /tmp/foo.sock /tmp/bar.sock ... /tmp/baz.sock\n                            Equivalent to ssh -LPORT:xxxxxxxxx:xxxx, being the local IP address optional.\n                            By default it will listen in all interfaces (0.0.0.0) and choose a random port.\n                            Example: -L :40000\n      -k SSH_HOST_KEY, --ssh_host_key SSH_HOST_KEY\n                            Gateway's host key\n      -K KEY_FILE, --private_key_file KEY_FILE\n                            RSA/DSS/ECDSA private key file\n      -S KEY_PASSWORD, --private_key_password KEY_PASSWORD\n                            RSA/DSS/ECDSA private key password\n      -t, --threaded        Allow concurrent connections to each tunnel\n      -v, --verbose         Increase output verbosity (default: ERROR)\n      -V, --version         Show version number and quit\n      -x IP:PORT, --proxy IP:PORT\n                            IP and port of SSH proxy to destination\n      -c SSH_CONFIG_FILE, --config SSH_CONFIG_FILE\n                            SSH configuration file, defaults to ~/.ssh/config\n      -z, --compress        Request server for compression over SSH transport\n      -n, --noagent         Disable looking for keys from an SSH agent\n      -d [FOLDER ...], --host_pkey_directories [FOLDER ...]\n                            List of directories where SSH pkeys (in the format `id_*`) may be found\n\n.. _Pahaz: https://github.com/pahaz\n.. _sshtunnel: https://pypi.python.org/pypi/sshtunnel\n.. _paramiko: http://www.paramiko.org/\n.. |CircleCI| image:: https://circleci.com/gh/pahaz/sshtunnel.svg?style=svg\n   :target: https://circleci.com/gh/pahaz/sshtunnel\n.. |AppVeyor| image:: https://ci.appveyor.com/api/projects/status/oxg1vx2ycmnw3xr9?svg=true\u0026passingText=Windows%20-%20OK\u0026failingText=Windows%20-%20Fail\n   :target: https://ci.appveyor.com/project/pahaz/sshtunnel\n.. |readthedocs| image:: https://readthedocs.org/projects/sshtunnel/badge/?version=latest\n   :target: http://sshtunnel.readthedocs.io/en/latest/?badge=latest\n   :alt: Documentation Status\n.. |coveralls| image:: https://coveralls.io/repos/github/pahaz/sshtunnel/badge.svg?branch=master\n   :target: https://coveralls.io/github/pahaz/sshtunnel?branch=master\n.. |pyversions| image:: https://img.shields.io/pypi/pyversions/sshtunnel.svg\n.. |version| image:: https://img.shields.io/pypi/v/sshtunnel.svg\n   :target: `sshtunnel`_\n.. |license| image::  https://img.shields.io/pypi/l/sshtunnel.svg\n   :target: https://github.com/pahaz/sshtunnel/blob/master/LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpahaz%2Fsshtunnel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpahaz%2Fsshtunnel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpahaz%2Fsshtunnel/lists"}