Skip to main content

Manage multiple tunnels via YAML configuration files and flexibly select to run one or more tunnels through command-line arguments.

Project description

SSH 隧道管理器

基于 Python 3.10 实现,支持 本地 (local)远程 (remote)动态 (dynamic) 三种端口转发模式。通过 YAML 配置文件管理多个隧道,并通过命令行参数灵活选择运行一个或多个隧道。

一、SSH 的转发模式介绍

SSH有三种将目标主机的服务“映射”到本地访问的方式,分别是本地端口转发、远程端口转发和动态端口转发。三种方式对比如下:

类型 常用参数 核心功能 典型应用场景
本地端口转发 -L 访问远程网络中的服务 想访问公司内网数据库、远程服务器上的Web服务
远程端口转发 -R 将本地服务暴露给外部网络 把本地的个人网站、开发服务展示给外网同事看
动态端口转发 -D 建立一个加密的SOCKS代理服务器 不固定转发端口,让浏览器或应用程序通过代理安全上网

1.1 Local本地转发- 将远程的服务映射本地

通过一个跳板机 (your-jump-server.com),将内网中 internal-server.local 的 80 端口(Web 服务)映射到你本地电脑的 8080 端口。

配置示例

tunnels:
  - id: web_server                     # 唯一标识符,用于命令行选择(-c web_server)
    name: "本地访问内网Web服务"          # 人类可读的描述,仅用于展示
    type: local                        # 指定为本地端口转发模式(对应 ssh -L)
    
    # --- SSH 连接参数(跳板机)---
    ssh_host: "your-jump-server.com"   # 跳板机的域名或 IP(你能够直接 SSH 到的公网服务器)
    ssh_port: 22                       # 跳板机的 SSH 端口,默认 22
    ssh_user: "your_username"          # 登录跳板机的用户名
    ssh_pkey: "~/.ssh/id_rsa"          # 私钥路径(推荐),也可以改用 ssh_password 字段
    
    # --- 转发规则(本地 → 内网目标)---
    local_port: 8080                   # 你本地电脑上将要监听的端口(例如访问 http://localhost:8080)
    remote_host: "internal-server.local"  # 内网目标的地址(从跳板机的视角能访问到的内网主机名或 IP)
    remote_port: 80                    # 内网目标上真正提供服务的端口(这里是 HTTP 服务)

工作机制图解

你的电脑 (本地)               跳板机 (SSH Server)              内网服务器
+-------------+              +------------------+           +-----------------+
|             | SSH 隧道加密  |                  |  明文转发  |                 |
| localhost:8080| ==========> | your-jump-server | ---------> | internal-server:80 |
|             | (动态端口)     |                  |   (端口80)  |                 |
+-------------+              +------------------+           +-----------------+
  1. 建立 SSH 连接:脚本(或 ssh 命令)用你的私钥登录跳板机。
  2. 本地监听:在你的电脑上启动一个 TCP 监听,端口为 local_port (8080)。
  3. 流量转发:当有程序访问 localhost:8080 时,SSH 客户端会通过加密隧道将数据发送给跳板机。
  4. 跳板机请求:跳板机解密后,作为客户端去连接 remote_host:remote_port (internal-server.local:80)。
  5. 数据回传:目标服务的响应原路返回。

关键注意事项

字段 注意点
ssh_host 必须是你能够 直接 SSH 登录 的机器,它通常拥有访问内网其他机器的网络权限。
remote_host 这个地址是 从跳板机角度 能解析/访问的。可以是内网 IP(如 192.168.1.100),也可以是内网域名。
local_port 确保本地 8080 端口没有被其他程序占用(可用 netstat -tulnp | grep 8080 检查)。
ssh_pkey vs ssh_password 强烈建议使用密钥认证(更安全);如果必须用密码,在配置中写 ssh_password: "your_password"(注意密码会明文存在配置文件中)。

实际效果对比

  • 没有隧道时:你无法直接访问 http://internal-server.local,因为它位于内网,不可路由。
  • 有了这个隧道后:你在浏览器打开 http://localhost:8080,就能看到内网 Web 服务的内容。对内网服务器来说,请求的来源是跳板机。

1.2 Remote 转发 — 将本地服务暴露到外网

作用:通过公网跳板机,将你本地电脑上的服务暴露给外部网络访问。类似 ssh -R

配置示例

tunnels:
  - id: expose_api
    name: "暴露本地Flask服务给公网"
    type: remote
    ssh_host: "public-server.com"    # 公网跳板机(有固定IP)
    ssh_port: 22
    ssh_user: "deploy"
    ssh_pkey: "~/.ssh/id_rsa"
    remote_port: 2222                # 跳板机上对外监听的端口
    local_host: "localhost"          # 本地服务的地址(通常为 localhost 或 127.0.0.1)
    local_port: 5000                 # 本地服务的端口
    # remote_bind_address: "0.0.0.0" # 可选:让跳板机监听所有网络接口(需服务器 GatewayPorts yes)

字段详解

字段 含义
type: remote 指定为远程端口转发模式
ssh_host/port/user/pkey 连接公网跳板机的参数(同 local)
remote_port 跳板机上将要监听的端口。外部用户访问 跳板机IP:remote_port 即连接到你的本地服务
local_host 你本地服务的地址。通常是 localhost127.0.0.1,也可以是同一局域网的其他机器
local_port 你本地服务的端口(例如 Flask 的 5000)
remote_bind_address 可选。默认跳板机只监听 127.0.0.1(仅本机可访问)。设为 "0.0.0.0" 后,外网任何人都可访问。需要跳板机 SSH 服务配置 GatewayPorts yes

工作机制

你的电脑 (本地)               跳板机 (公网)                    外部用户
+-------------+              +------------------+            +-------------+
|             | SSH 隧道加密  |                  |  普通TCP    |             |
| localhost:5000| <========= | public-server:2222| <--------- | 任意客户端   |
| (Flask服务)  | (动态端口)   | (监听公网)         |            |             |
+-------------+              +------------------+            +-------------+
  1. 你建立 SSH 连接到公网跳板机,并请求在跳板机上监听 remote_port
  2. 当外部用户访问 跳板机IP:remote_port 时,跳板机将连接通过 SSH 隧道反向转发到你本地的 local_host:local_port
  3. 你的本地服务处理请求,响应原路返回。

典型使用场景

  • 演示/调试:把本地开发的网站临时给同事看,无需部署到服务器。
  • 穿透 NAT:你的电脑在公司内网或家庭宽带(无公网IP),通过一台有公网IP的云主机让外部访问本地服务。
  • 远程访问内网设备:本地有一个监控摄像头(RTSP 流),通过远程转发让外网观看。

注意事项

  1. 跳板机需允许 TCP 转发/etc/ssh/sshd_config 中确保 AllowTcpForwarding yes
  2. 监听地址问题:默认 remote_bind_address 为空(或 127.0.0.1),意味着只有登录到跳板机本机才能访问 remote_port。如果要公网访问,必须:
    • 设置 remote_bind_address: "0.0.0.0"
    • 并在 sshd_config 中开启 GatewayPorts yes(重启 sshd)。
  3. 防火墙:跳板机的防火墙需放开 remote_port 的入站连接。
  4. 安全性:暴露的服务应具备认证机制,防止未授权访问。

1.3 Dynamic 转发— SOCKS5 代理

作用:在本地创建一个 SOCKS5 代理端口,所有支持 SOCKS 的应用可动态请求代理访问任意目标。类似 ssh -D

配置示例

tunnels:
  - id: socks_proxy
    name: "SOCKS5代理"
    type: dynamic
    ssh_host: "my-server.com"
    ssh_port: 22
    ssh_user: "proxy_user"
    ssh_pkey: "~/.ssh/proxy_key"
    local_port: 1080                # 本地 SOCKS 代理端口
    # remote_bind_address: ""       # 动态转发无需此项

字段详解

字段 含义
type: dynamic 指定为动态端口转发模式
local_port 你在本地电脑上开启的 SOCKS5 代理端口(例如 1080)
其他 SSH 连接参数 同 local,用于登录跳板机

工作机制

你的电脑 (本地)                跳板机 (SSH Server)                 互联网/内网
+------------------------+    +------------------+            +-----------------+
| SOCKS5代理 localhost:1080| => | my-server.com     | ========> | 任意目标:任意端口 |
| (浏览器/curl配置代理)    |    | (解密请求,按需连接)|            | (根据应用请求)  |
+------------------------+    +------------------+            +-----------------+
  1. SSH 客户端在本地 localhost:1080 启动一个 SOCKS5 代理服务器。
  2. 应用程序(浏览器、curl、即时通讯工具等)配置使用该代理(socks5://127.0.0.1:1080)。
  3. 应用程序发起连接时,会先通过 SOCKS 协议告诉代理“我要连接的主机和端口”。
  4. SSH 客户端将这一请求加密后发给跳板机,由跳板机真正去连接目标服务器。
  5. 跳板机返回的数据原路返回。

典型使用场景

  • 浏览器翻墙/访问内网:配置浏览器 SOCKS 代理,即可访问跳板机所在网络内的任意网站(如公司内部 Wiki、GitLab)。
  • 命令行工具:使用 proxychainscurl --socks5 让命令行程序走代理。
  • 临时调试:一个代理端口可访问多种服务,无需逐个配置 local 转发。

与 local 转发的本质区别

维度 local dynamic
目标指定 预先固定 主机:端口 动态由应用告知
应用要求 无需特殊支持 必须支持 SOCKS5 或配合 proxychains 使用
一个端口能连多少个目标 1个 无数个
典型用途 固定服务映射(数据库、内网站点) 浏览网页、多种服务通吃

注意事项

  1. 应用支持:并非所有程序都能原生使用 SOCKS5。老旧的数据库客户端、部分命令行工具需要搭配 proxychains 或类似工具。
  2. DNS 解析:默认 DNS 解析是在本地完成的,可能导致内网域名无法解析。可以配置远程 DNS(如 ssh -D 1080 -o "ProxyCommand=none" 或使用 --socks5-hostname 在 curl 中)。
  3. 服务端无额外配置:动态转发只需要服务端 AllowTcpForwarding yes(通常默认开启),无需 GatewayPorts

二、配置说明

  • 本地转发 (type: local):将远程服务映射到本地端口,类似 ssh -L
  • 远程转发 (type: remote):将本地服务暴露到远程服务器,类似 ssh -R
  • 动态转发 (type: dynamic):创建 SOCKS5 代理,类似 ssh -D

远程转发如需监听所有网络接口,需在远程 SSH 服务器上设置 GatewayPorts yes, 并在配置中添加 remote_bind_address: "0.0.0.0"

config.yaml示例:

tunnels:
  - id: web_server
    name: "本地访问内网Web服务"
    type: local
    ssh_host: "your-jump-server.com"
    ssh_port: 22
    ssh_user: "your_username"
    ssh_pkey: "~/.ssh/id_rsa"      # 或使用密码
    local_port: 8080
    remote_host: "internal-server.local"
    remote_port: 80

  - id: expose_api
    name: "暴露本地Flask服务到公网"
    type: remote
    ssh_host: "public-server.com"
    ssh_port: 22
    ssh_user: "deploy"
    ssh_password: "your_password"
    remote_port: 2222
    local_host: "localhost"
    local_port: 5000
    # remote_bind_address: "0.0.0.0"   # 如需监听所有接口(需服务器GatewayPorts yes)

  - id: socks_proxy
    name: "SOCKS5代理"
    type: dynamic
    ssh_host: "my-server.com"
    ssh_port: 22
    ssh_user: "proxy_user"
    ssh_pkey: "~/.ssh/proxy_key"
    local_port: 1080

三、使用方法

​ 根据实际环境修改 config.yaml 中的隧道配置。

3.1 从项目中运行

  1. 列出所有可用的隧道:

    uv run pyssh_tunnel -l
    
  2. 启动一个或多个隧道(通过 -c 指定 ID,可重复):

    uv run pyssh_tunnel -c web_server -c socks_proxy
    
  3. Ctrl+C 停止所有隧道。

3.2 安装pyssh_tunnel

  1. 使用pip install pyssh_tunnel

  2. 使用命令行执行

    pyssh_tunnel -c web_server -c socks_proxy
    

四、命令行参数

  • -c, --config-id:要启动的隧道 ID(可多次使用)
  • -l, --list:列出所有隧道配置
  • --config-file:指定配置文件路径(默认 config.yaml
  • --log-file:日志文件路径(默认输出到控制台)
  • --log-level:日志级别(DEBUG/INFO/WARNING/ERROR)
$ pyssh_tunnel -h
usage: pyssh_tunnel [-h] [-c IDS] [-l] [--config-file CONFIG_FILE] [--log-file LOG_FILE]
                    [--log-level {DEBUG,INFO,WARNING,ERROR}]

SSH隧道管理器

options:
  -h, --help            show this help message and exit
  -c IDS, --config-id IDS
                        选择要启动的隧道ID (可多次使用)
  -l, --list            列出所有可用隧道配置
  --config-file CONFIG_FILE
                        配置文件路径 (默认: config.yaml)
  --log-file LOG_FILE   日志文件路径
  --log-level {DEBUG,INFO,WARNING,ERROR}
                        日志级别

该实现支持同时运行多个不同类型的隧道,每个隧道独立运行在后台线程中,收到中断信号时会优雅关闭所有连接。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyssh_tunnel-0.1.0.tar.gz (40.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyssh_tunnel-0.1.0-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

Details for the file pyssh_tunnel-0.1.0.tar.gz.

File metadata

  • Download URL: pyssh_tunnel-0.1.0.tar.gz
  • Upload date:
  • Size: 40.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.9

File hashes

Hashes for pyssh_tunnel-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d2ffe7b901674ef76f0c411fb1fb0462b000fd4dcda0e8ad67dd2934b0121e34
MD5 c8258aff005412347f32fb537835d5ce
BLAKE2b-256 c7318831e4e454003e569994df8a067dcce060a13b93a64510f40d3648b0e6fa

See more details on using hashes here.

File details

Details for the file pyssh_tunnel-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pyssh_tunnel-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6a0eba8fa71f6de70419a3ff11c24b49e22ccdf6ddb6abfd5856ef82fe3f6f27
MD5 16e8b55b69b9e48ff4e0b4e6a397871c
BLAKE2b-256 14a36119b8ba12c84e4b287b8211e4ade0285602c8380ff5d6210116de60d596

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page