wstunnel ssh跳板
- 一、前言
- 二、wstunnel
- [三、ssh 跳板](#三、ssh 跳板)
- 四、可能的问题
-
- [4.1 客户端无法连接,或连接后立即断开](#4.1 客户端无法连接,或连接后立即断开)
- [4.2 隧道已建立,但 SSH 连接失败](#4.2 隧道已建立,但 SSH 连接失败)
一、前言
本篇主要介绍如何通过wstunnel建立ssh隧道,实现对于封闭内网机器的远程访问。适用条件:
- 有一台具有公网IP的ECS服务器(如阿里云)
- 公司封闭内网机器
- 家庭机器
二、wstunnel
wstunnel 是为了解决封闭网络环境中,常用协议被阻断这一痛点而生。它利用 WebSocket 协议将任意 TCP 或 UDP 流量封装在 WebSocket 连接中,将网络数据"伪装"成正常的网页浏览流量,从而轻松穿透绝大多数防火墙和代理服务器的封锁。
换言之这玩意也可以用来做你想的那个事,但这不是本文重点
2.1 服务端(Server)
服务器端是我们整个隧道的中转站。它需要拥有一个公网 IP 地址,并且能够自由访问互联网。在我们的场景中,这台服务器就是那台 ECS 云主机。它的核心任务是运行 wstunnel 的服务端程序,同时监听来自"公司电脑"和"家庭电脑"的连接请求。
安装 wstunnel
你可以用自己的方式去官方的 release 下载,然后上传到ECS服务器。假设你的服务器能够连 github,也可以直接操作:
bash
wget https://github.com/erebe/wstunnel/releases/download/v10.4.4/wstunnel_10.4.4_linux_amd64.tar.gz
tar -zxf wstunnel_10.4.4_linux_amd64.tar.gz
sudo mv wstunnel /usr/local/bin
sudo chmod +x /usr/local/bin/wstunnel
我们将 wstunnel 执行文件移动到 /usr/local/bin,这样就可以全局调用了。你可以用下面的语句确认是否安装成功:
bash
wstunnel --help
输出说明文档则成功。
配置防火墙
wstunnel 需要监听两个端口,因此我们需要确保服务器的防火墙(如 ufw, firewalld)或云服务商的安全组策略允许外部流量访问这两个端口。
- 端口 8080 (TCP): 用于 wstunnel 服务端监听来自公司电脑的 WebSocket 连接。这是隧道的入口。
- 端口 2222 (TCP): 用于我们从家庭电脑发起 SSH 连接。这是我们将要访问的目标端口。注意这里的端口你可以自行配置,如果需要多台机器,则需要开放多个端口
这里因为不同人的ECS配置不同,这里不给出具体的操作步骤。请查阅自己ECS供应商给出的教程。
运行 wstunnel server
配置好防火墙后,我们就可以启动 wstunnel 服务端了。你可以使用普通的 websocket 连接(ws://),为了增加一层额外的安全性,这里推荐使用加密的 wss:// 协议。
注意:你的客户端和服务端需要使用相同的协议,不能服务端加密,客户端不加密。
bash
wstunnel server wss://[::]:8080
server
: 表示以服务端模式运行。wss://[::]:8080
: 这是服务端的核心配置。wss://
: 指定使用 WebSocket Secure 协议。wstunnel 会自动生成一个自签名 TLS 证书来加密隧道流量。[::]/0.0.0.0
: 表示监听服务器上所有可用的网络接口(包括公网 IP 和内网 IP)。:8080
: 指定监听的端口号。
持久化服务端服务
建议创建一个持久化的服务,避免ECS重启后的断联。这里我们用 systemd 创建一个后台服务:
- 创建一个 service 文件
bash
sudo vim /etc/systemd/system/wstunnel-server.service
# 在 wstunnel-server.service 中,写入下面内容:
[Unit]
Description=wstunnel server for reverse tunnel (Secure)
After=network.target
[Service]
Type=simple
# 使用一个低权限用户运行服务,增强安全性
User=nobody
# 确保这里的路径和命令与你手动执行时的一致
ExecStart=/usr/local/bin/wstunnel server wss://0.0.0.0:8080
# 配置服务在失败时总是自动重启
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
- 保存退出后,执行以下命令来启用并启动这个新服务
bash
# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 设置服务开机自启
sudo systemctl enable wstunnel-server.service
# 立刻启动服务
sudo systemctl start wstunnel-server.service
- 检查一下是否运行
bash
sudo systemctl status wstunnel-server.service
如果你看到绿色的 active (running)
字样,那么服务器端的配置已经全部完成了!它现在正静静地等待着来自你公司电脑的连接。
2.2 客户端(Client)
客户端是指那台位于公司内网,我们最终希望通过 SSH 访问的电脑。由于它没有公网 IP,我们无法从外部直接连接它。因此,我们需要在这台电脑上运行 wstunnel 的客户端程序,让它主动"走出去",与我们部署在公网 ECS 上的服务端建立一条持久的连接。这条连接就是我们的"反向隧道"。
安装 wstunnel
操作同服务端,略。
你可能需要确保一下 ssh 服务是否已开启:
bash
sudo systemctl status ssh
如果服务未运行,使用 sudo systemctl start ssh
来启动它。
运行 wstunnel 客户端
在公司电脑的终端中,执行以下命令:
bash
wstunnel client -R tcp://:2222:localhost:22 wss://198.51.100.10:8080
让我们详细解读这个关键命令:
- client: 表示以客户端模式运行。
-R tcp://:2222:localhost:22
: 这是定义反向隧道 (Remote-to-Local) 的参数,也是整个魔法的核心。它的意思是:- 请求远端服务器 (Remote),即我们的公网 ECS 使用 tcp 协议,在它自己的所有网络接口 (0.0.0.0) 的 2222 端口上进行监听。当有任何流量进入该端口时,请将这些流量通过隧道转发到本地 (Local),即当前这台公司电脑的 localhost:22 地址上。localhost:22 正是这台公司电脑上 SSH 服务监听的地址。
wss://198.51.100.10:8080
: 指定要连接的 wstunnel 服务端地址。wss://
: 协议必须与服务端保持一致,这里我们使用加密的 WebSocket。198.51.100.10:8080
: 公网服务器的 IP 地址和 wstunnel 服务端监听的端口。
执行该命令后,如果一切顺利,它会连接到服务器并保持在前台运行,等待隧道流量。
持久化客户端服务
与服务端一样,我们不希望因为关闭终端或电脑重启而导致隧道中断。因此,我们也为客户端配置一个 systemd 服务,让它在后台持久运行。
- 创建 service 服务
bash
sudo vim /etc/systemd/system/wstunnel-client.service
# 在 wstunnel-client.service 中,添加以下内容:
[Unit]
Description=wstunnel client for reverse tunnel (Secure)
# 确保在网络连接建立之后再启动本服务
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
# 建议使用你自己的普通用户来运行此服务
User=your_company_user
# 确保这里的命令和 IP 地址都是正确的
ExecStart=/usr/local/bin/wstunnel client -R tcp://:2222:localhost:22 wss://198.51.100.10:8080
# 同样配置自动重启,重启间隔可以稍长一些
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
注意:请将
your_company_user
替换成您在公司电脑上登录的实际用户名。同时,务必再次检查 ExecStart 行中的公网服务器 IP 地址是否正确。
- 保存并退出后,启用并启动该服务。
bash
sudo systemctl daemon-reload
sudo systemctl enable wstunnel-client.service
sudo systemctl start wstunnel-client.service
三、ssh 跳板
配置到现在,你已经可以在 ECS 上直接 ssh 连接我们的公司电脑了:
bash
ssh your_company_user@localhost -p 2222
但是,据我对于 wstunnel 的文档阅读,它并不支持你直接将数据转发到 0.0.0.0:2222,仅能提供一个 localhost 的服务。因此,我们从家里的电脑连接到公司,需要通过 ssh跳板(Proxy) 实现。
- 添加一个 ssh 目标配置
在 Windows 中打开(或创建) C:/Users/user_name/.ssh
文件夹,找到里面的 config 文件,并添加如下内容:
ini
Host company # 一个昵称,之后可以直接用 ssh company 连接
HostName 127.0.0.1 # 作为跳板的机器上要连接的机器ip
Port 2222 # 作为跳板的机器上要连接的机器 ssh 端口
User your_company_user
ProxyJump ecs_user@198.51.100.10
这里由于我们使用 wstunnel 作为隧道,所以 HostName 直接填 127.0.0.1 即可。注意把 198.51.100.10 换成你的 ECS 公网IP。
- 尝试连接
bash
ssh company
这里需要输入两个密码,第一次是跳板机的密码,第二次是公司机器的密码。如果你不想总是输入密码,可以参考我之前的ssh免密博客,配置一下公钥。
四、可能的问题
首先,建议在配置为服务(Service)之前,现在终端中运行上面的语句,这样方便通过输出的日志检查错误原因。下面是一些可能出现的(我配置时遇到过)问题,简单整理一下。
4.1 客户端无法连接,或连接后立即断开
在公司电脑上启动 wstunnel client
后,它可能立即输出 "connection refused"、"connection timed out" 等错误。此时在服务器端查看日志,可能看到了有连接记录,但是报错。
可能的原因及解决方案:
-
协议不匹配 (最常见)
- 原因:这是最容易犯的错误。你在服务端启动时使用了 wss:// (加密),但在客户端连接时却用了 ws:// (未加密),或者反之。两者协议必须完全一致。
- 解决方案:仔细检查并统一服务器和客户端的启动命令。推荐全部使用更安全的 wss://。
- 服务器端应为: wstunnel server wss://0.0.0.0:8080
- 客户端连接地址应为: wss://你的公网IP:8080
-
服务器防火墙/安全组未放行
- 原因:公网服务器的防火墙(如 ufw)或云服务商的安全组策略没有放行 wstunnel 服务端监听的端口(本教程中为 8080)。
- 解决方案:登录你的云服务控制台或服务器,检查防火墙入站规则,确保 8080 端口的 TCP 流量是被允许的。
4.2 隧道已建立,但 SSH 连接失败
通过 systemctl status
检查,wstunnel 的服务端和客户端都显示 active (running),日志也没有报错。但当你从家里电脑尝试 ssh company
时,连接被拒绝 (Connection Refused) 或超时 (Timed Out)。
可能的原因及解决方案:
-
公网服务器未放行 SSH 入口端口
- 原因:你只放行了 wstunnel 隧道的 8080 端口,但忘记了放行我们用于 SSH 连接的入口端口 2222。
- 解决方案:再次检查公网服务器的防火墙/安全组,确保 2222 端口的 TCP 入站流量也被允许。
-
公司电脑上的 SSH 服务未运行
- 原因:隧道本身是通的,但流量被转发到公司电脑的 22 端口后,发现没有任何服务在监听,导致连接被拒绝。
- 解决方案:登录你的公司电脑,使用 sudo systemctl status ssh 命令检查 SSH 服务是否正在运行。如果未运行,使用 sudo systemctl start ssh 启动它。