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) | |
+-------------+ +------------------+ +-----------------+
- 建立 SSH 连接:脚本(或
ssh命令)用你的私钥登录跳板机。 - 本地监听:在你的电脑上启动一个 TCP 监听,端口为
local_port(8080)。 - 流量转发:当有程序访问
localhost:8080时,SSH 客户端会通过加密隧道将数据发送给跳板机。 - 跳板机请求:跳板机解密后,作为客户端去连接
remote_host:remote_port(internal-server.local:80)。 - 数据回传:目标服务的响应原路返回。
关键注意事项
| 字段 | 注意点 |
|---|---|
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 |
你本地服务的地址。通常是 localhost 或 127.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服务) | (动态端口) | (监听公网) | | |
+-------------+ +------------------+ +-------------+
- 你建立 SSH 连接到公网跳板机,并请求在跳板机上监听
remote_port。 - 当外部用户访问
跳板机IP:remote_port时,跳板机将连接通过 SSH 隧道反向转发到你本地的local_host:local_port。 - 你的本地服务处理请求,响应原路返回。
典型使用场景
- 演示/调试:把本地开发的网站临时给同事看,无需部署到服务器。
- 穿透 NAT:你的电脑在公司内网或家庭宽带(无公网IP),通过一台有公网IP的云主机让外部访问本地服务。
- 远程访问内网设备:本地有一个监控摄像头(RTSP 流),通过远程转发让外网观看。
注意事项
- 跳板机需允许 TCP 转发:
/etc/ssh/sshd_config中确保AllowTcpForwarding yes。 - 监听地址问题:默认
remote_bind_address为空(或127.0.0.1),意味着只有登录到跳板机本机才能访问remote_port。如果要公网访问,必须:- 设置
remote_bind_address: "0.0.0.0" - 并在
sshd_config中开启GatewayPorts yes(重启 sshd)。
- 设置
- 防火墙:跳板机的防火墙需放开
remote_port的入站连接。 - 安全性:暴露的服务应具备认证机制,防止未授权访问。
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配置代理) | | (解密请求,按需连接)| | (根据应用请求) |
+------------------------+ +------------------+ +-----------------+
- SSH 客户端在本地
localhost:1080启动一个 SOCKS5 代理服务器。 - 应用程序(浏览器、curl、即时通讯工具等)配置使用该代理(
socks5://127.0.0.1:1080)。 - 应用程序发起连接时,会先通过 SOCKS 协议告诉代理“我要连接的主机和端口”。
- SSH 客户端将这一请求加密后发给跳板机,由跳板机真正去连接目标服务器。
- 跳板机返回的数据原路返回。
典型使用场景
- 浏览器翻墙/访问内网:配置浏览器 SOCKS 代理,即可访问跳板机所在网络内的任意网站(如公司内部 Wiki、GitLab)。
- 命令行工具:使用
proxychains或curl --socks5让命令行程序走代理。 - 临时调试:一个代理端口可访问多种服务,无需逐个配置 local 转发。
与 local 转发的本质区别
| 维度 | local | dynamic |
|---|---|---|
| 目标指定 | 预先固定 主机:端口 |
动态由应用告知 |
| 应用要求 | 无需特殊支持 | 必须支持 SOCKS5 或配合 proxychains 使用 |
| 一个端口能连多少个目标 | 1个 | 无数个 |
| 典型用途 | 固定服务映射(数据库、内网站点) | 浏览网页、多种服务通吃 |
注意事项
- 应用支持:并非所有程序都能原生使用 SOCKS5。老旧的数据库客户端、部分命令行工具需要搭配
proxychains或类似工具。 - DNS 解析:默认 DNS 解析是在本地完成的,可能导致内网域名无法解析。可以配置远程 DNS(如
ssh -D 1080 -o "ProxyCommand=none"或使用--socks5-hostname在 curl 中)。 - 服务端无额外配置:动态转发只需要服务端
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 从项目中运行
-
列出所有可用的隧道:
uv run pyssh_tunnel -l
-
启动一个或多个隧道(通过
-c指定 ID,可重复):uv run pyssh_tunnel -c web_server -c socks_proxy
-
按
Ctrl+C停止所有隧道。
3.2 安装pyssh_tunnel
-
使用
pip install pyssh_tunnel -
使用命令行执行
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2ffe7b901674ef76f0c411fb1fb0462b000fd4dcda0e8ad67dd2934b0121e34
|
|
| MD5 |
c8258aff005412347f32fb537835d5ce
|
|
| BLAKE2b-256 |
c7318831e4e454003e569994df8a067dcce060a13b93a64510f40d3648b0e6fa
|
File details
Details for the file pyssh_tunnel-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pyssh_tunnel-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a0eba8fa71f6de70419a3ff11c24b49e22ccdf6ddb6abfd5856ef82fe3f6f27
|
|
| MD5 |
16e8b55b69b9e48ff4e0b4e6a397871c
|
|
| BLAKE2b-256 |
14a36119b8ba12c84e4b287b8211e4ade0285602c8380ff5d6210116de60d596
|