跳转到主要内容

纯Python SSH隧道

项目描述

CircleCI AppVeyor Documentation Status coveralls version

pyversions license

作者: Pahaz

仓库: https://github.com/pahaz/sshtunnel/

https://github.com/jmagnusson/bgtunnel的启发,它不支持Windows。

另请参阅:https://github.com/paramiko/paramiko/blob/master/demos/forward.py

要求

安装

sshtunnel位于PyPI,因此只需运行

pip install sshtunnel

easy_install sshtunnel

conda install -c conda-forge sshtunnel

将其安装到您的环境中。

从源安装时,克隆仓库并运行

python setup.py install

测试包

为了运行测试,您首先需要tox并运行

python setup.py test

使用场景

以下图中展示了 sshtunnel 有帮助的典型场景之一。用户可能需要连接远程服务器(例如 8080 端口)的端口,而只有 SSH 端口(通常是端口 22)可以访问。

----------------------------------------------------------------------

                            |
-------------+              |    +----------+
    LOCAL    |              |    |  REMOTE  | :22 SSH
    CLIENT   | <== SSH ========> |  SERVER  | :8080 web service
-------------+              |    +----------+
                            |
                         FIREWALL (only port 22 is open)

----------------------------------------------------------------------

图1:如何通过 SSH 隧道连接被防火墙阻止的服务。

如果 SSH 服务器允许,也可以从(REMOTE SERVER 角度)访问外部(LOCAL CLIENT 角度)不可见的私有服务器。

----------------------------------------------------------------------

                            |
-------------+              |    +----------+               +---------
    LOCAL    |              |    |  REMOTE  |               | PRIVATE
    CLIENT   | <== SSH ========> |  SERVER  | <== local ==> | SERVER
-------------+              |    +----------+               +---------
                            |
                         FIREWALL (only port 443 is open)

----------------------------------------------------------------------

图2:如何通过 SSH 隧道连接 PRIVATE SERVER

使用示例

API 允许初始化隧道并启动它,或者使用 with 上下文,这将负责启动和停止隧道。

示例 1

以下代码对应于上述 图1,假设远程服务器地址为 pahaz.urfuclub.ru,密码认证,随机分配本地绑定端口。

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

示例 2

以下是一个将端口转发到无法直接访问的私有服务器的示例,假设使用密码保护的私钥认证,远程服务器 SSH 服务监听端口 443,并且该端口在防火墙中已开放(图2)。

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!')

示例 3

为 Vagrant MySQL 本地端口进行端口转发的示例。

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!')

或者简单地使用 CLI

(bash)$ python -m sshtunnel -U vagrant -P vagrant -L :3306 -R 127.0.0.1:3306 -p 2222 localhost

示例 4

通过跳过两个隧道来打开 SSH 会话。SSH 传输和隧道将被守护,不会在关闭时间等待连接停止。

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

CLI 使用方法

$ 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]
                 [-d [FOLDER [FOLDER ...]]]
                 ssh_address

Pure python ssh tunnel utils
Version 0.4.0

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
  -d [FOLDER [FOLDER ...]], --host_pkey_directories [FOLDER [FOLDER ...]]
                        List of directories where SSH pkeys (in the format `id_*`) may be found

在线文档

文档可以在 readthedocs 上找到。

贡献者

变更日志

  • v.0.4.0 (Pahaz)
    • 将所有隧道线程的守护进程 mod 标志更改为以防止意外的挂起(不完全向后兼容)

    • 为 Mongo/Postgres/MySQL 添加基于 docker 的端到端功能测试(#219

    • 为端到端挂起测试添加基于 docker(#219

  • v.0.3.2 (Pahaz, JM Fernández)
    • 修复主机密钥目录检测

    • 将默认 ssh 配置文件夹统一到 ~/.ssh

  • v.0.3.1 (Pahaz)
    • 将打开连接超时增加到 10 秒

  • v.0.3.0 (Pahaz)
    • 将默认 with 上下文行为更改为退出时使用 .stop(force=True)(不完全向后兼容)

    • 移除用于防止挂起的无用的 daemon_forward_servers = True 修补程序(不完全向后兼容)

    • 将默认传输保活时间设置为 5 秒(对于版本 < 0.3.0 已禁用)

    • 将默认传输超时设置为 0.1

    • 弃用并移除 block_on_close 选项

    • 修复“死锁”/“隧道挂起”(#173#201#162#211

  • v.0.2.2 (Pahaz)
    • 为强制关闭活动连接添加 .stop(force=True)#201

  • 版本 v.0.2.1(由 PahazEddie Chiangkkrasovskii 贡献)
    • 修复了DOWN状态隧道中孤儿线程的bug(#170

  • 版本 v.0.2.0(由 Georgy Rylov 贡献)
    • 支持无代理命令的IPv6。使用内置的paramiko创建套接字逻辑。逻辑首先尝试使用IPv6套接字族,然后是IPv4套接字族。

  • 版本 v.0.1.5(由 JM Fernández 贡献)
    • 引入 block_on_close 属性

  • 版本 v.0.1.4(由 Niels Zeilemaker 贡献)
    • 允许从 ~/.ssh 加载私钥

  • 版本 v.0.1.3(由 Ignacio Peluffo 和其他人贡献)
    • pkey_file 参数更新为接受使用 ~ 的用户文件夹的相对路径

    • 多个bug修复

  • 版本 v.0.1.2(由 JM Fernández 贡献)
    • 修复 #77

  • 版本 v.0.1.1(由 JM Fernández 贡献)
    • 修复 #72

  • 版本 v.0.1.0(由 JM Fernández 贡献)
    • 添加 tunnel_bindings 属性

    • 多个bug修复 (#49, #56, #57, #59, #60, #62, #64, #66, …)(由 PahazJM Fernández 贡献)

    • 添加 TRACE 记录级别(由 JM Fernández 贡献)

    • 代码和测试重构(由 JM Fernández 贡献)

    • 放弃对 python3.2 的支持

  • 版本 v.0.0.8(由 JM Fernández 贡献)
  • 版本 v.0.0.7(由 JM Fernández 贡献)
  • 版本 v.0.0.6(由 Pahaz 贡献)
    • 添加 -S CLI 选项以支持 ssh 私钥密码(由 Pahaz 贡献)

  • 版本 v.0.0.5(由 Pahaz 贡献)
    • 添加 ssh_proxy 参数,以及 ssh_config(5)ProxyCommand 支持(《Lewis Thompson》)

    • 添加一些 Python 2.6 兼容性修复(《Mart Sõmermaa》)

    • paramiko.transport 继承了传递给 SSHTunnelForwarder 的日志记录器的处理器(《JM Fernández》)

    • 修复 #34#33,代码风格和文档(《JM Fernández》)

    • 添加测试(《Pahaz》)

    • 添加 CI 集成(《Pahaz》)

    • 正常打包(《Pahaz》)

    • 通过 SSHTunnelForwarder.local_is_up 禁用检查目标套接字连接(《Pahaz》)[更改默认行为]

    • 默认情况下,在所有线程中使用 daemon 模式 = False;详细信息(《Pahaz》)[更改默认行为]

  • v.0.0.4.4(《Pahaz》)
    • 修复问题 #24 - 隐藏日志中的 ssh 密码(《Pahaz》)

  • v.0.0.4.3(《Pahaz》)
    • 修复默认端口问题 #19(《Pahaz》)

  • v.0.0.4.2(《Pahaz》)
  • v.0.0.4.1(《Pahaz》)
    • 修复 CLI 问题 #13(《Pahaz》)

  • v.0.0.4(《Pahaz》)
    • 默认情况下,所有线程使用守护线程模式 - 不兼容(《JM Fernández》、《Pahaz》)

    • make_ssh_forward_server 移动到 SSHTunnelForwarder.make_ssh_forward_server(《Pahaz》、《JM Fernández》)- 不兼容

    • make_ssh_forward_handler 移动到 SSHTunnelForwarder.make_ssh_forward_handler_class(《Pahaz》、《JM Fernández》)- 不兼容

    • open 重命名为 open_tunnel(《JM Fernández》)- 不兼容

    • 添加 CLI 界面(《JM Fernández》)

    • 支持同时打开多个隧道(《JM Fernández》)

    • 提高稳定性和可读性(《JM Fernández》、《Pahaz》)

    • 改进日志(《JM Fernández》、《Pahaz》)

    • 为同时打开多个隧道添加 raise_exception_if_any_forwarder_have_a_problem 参数(《Pahaz》)

    • 添加 ssh_config_file 参数支持(《JM Fernández》)

    • 添加 Python 3 支持(《JM Fernández》、《Pahaz》)

  • v.0.0.3(《Pahaz》)
  • v.0.0.1(《Pahaz》版本)
    • SSHTunnelForwarder 类(《Pahaz》)

    • open 函数(《Pahaz》)

项目详情


下载文件

下载适用于您平台文件的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。

源分布

sshtunnel-0.4.0.tar.gz (62.7 kB 查看哈希值)

上传时间:

构建分布

sshtunnel-0.4.0-py3.8.egg (24.2 kB 查看哈希值)

上传时间:

sshtunnel-0.4.0-py2.py3-none-any.whl (24.7 kB 查看哈希值)

上传时间: Python 2 Python 3

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面