本项目提供一个名为 msh 的命令行工具,用于在无法直接进行 TLS 连接到 Headscale 服务器的情况下,通过建立 SSH 隧道来安全地注册和连接 Tailscale 节点。
与普通脚本不同,本项目注重易用性、健壮性和���全性,内置了完整的交互式配置向导、环境检查和进程管理机制。
在某些网络环境中,服务提供商可能会对出站的 TLS 连接进行深度包检测(DPI)或特征审查,这可能导致标准的 Headscale 连接被中断或失败。
为了绕过这种审查,本工具采用了一种 SSH 隧道技术:
- 建立隧道:通过 SSH 在本地机器和您的 Headscale 服务器之间建立一个安全的隧道。
- 端口转发:它将本机的
443端口转发到 Headscale 服务器上的localhost:443。这意味着,当 Tailscale 客户端尝试连接https://<你的域名>时,由于/etc/hosts文件的配置,流量实际上被导向到127.0.0.1:443,也就是 SSH 隧道的入口。 - 安全通信:流量通过 SSH 隧道安全地传输到您的服务器,然后在服务器内部直接访问 Headscale 服务。由于流量被封装在 SSH 协议内,外部网络无法审查其内部的 TLS 握手过程,从而成功规避了连接问题。
整个过程可以简化为:
Tailscale 客户端 -> 本地 443 端口 -> SSH 隧道 -> Headscale 服务器 -> Headscale 服务
- 交互式配置:首次运行时自动引导用户完成所有必要配置,无需手动编辑文件。
- 智能的环境检查:启动前自动检查
tailscale,ssh,nc,lsof等核心依赖,并验证/etc/hosts文件配置。 - 极其健壮的进程管理:
- 杜绝僵尸进程:在启动前和结束后,使用
lsof强制查找并清理任何残留的隧道进程,彻底解决了因断网、异常退出导致的端口占用问题。 - 精确的 PID 识别:通过查询
/proc文件系统来识别由lsof找到的进程,避免了ps命令在不同系统间的兼容性问题。
- 杜绝僵尸进程:在启动前和结束后,使用
- 可靠的
sudo环境执行:能够智能地以原始用户身份检查 SSH Agent,确保在sudo环境下认证过程的正确性。 - 清晰的错误处理:在 SSH 密钥认证失败时会立即报错退出,而不是挂起等待密码输入,让问题定位更简单。
- 优雅的退出机制:通过
trap捕获中断信号,确保任何情况下都能清理残留进程。 - 状态检查:提供
status命令,快速了解隧道和节点的当前状态。
-
克隆或下载项目 首先,获取项目文件。
git clone https://github.com/your-repo/msh.git cd msh -
为脚本添加可执行权限 在运行安装脚本之前,您需要先为其添加可执行权限:
chmod +x install.sh chmod +x msh.sh # 主脚本也需要可执行权限 -
运行安装脚本 使用
sudo权限运行安装脚本。该脚本会将msh命令安装到/usr/local/bin,并设置必要的权限。sudo ./install.sh
安装完成后,您可以在任何地方直接使用 msh 命令。如果这是您第一次运行,工具会启动一个交互式的设置向导。
msh start [options]- 描述: 这是最常用的命令。它会清理旧进程、获取预授权密钥、建立 SSH 隧道,并激活本地 Tailscale 节点。
- 选项:
--port <端口号>: 临时指定隧道的本地端口,覆盖配置文件中的TUNNEL_PORT。适用于需要动态端口的场景(例如 WSL2 Mirrored 网络模式)。--expiration <时长>: 指定预授权密钥的有效期,例如12h(12 小时),30d(30 天)。默认为8h。
示例:
# 使用默认配置启动
msh start
# 在 WSL 中使用,将隧道建立在 10443 端口,并设置密钥有效期为30天
msh start --port 10443 --expiration 30dmsh stop- 描述: 关闭由
msh启动的 SSH 隧道并清理所有相关进程。
msh status- 描述: 检查 SSH 隧道和 Tailscale 节点的当前状态。
msh activate [options]- 描述: 此命令仅获取预授权密钥并激活节点,它不会创建新的 SSH 隧道。适用于多个客户端(例如 Windows 和 WSL)共享同一个隧道的情况。
- 选项:
--expiration <时长>: 指定预授权密钥的有效期。
msh link <预授权密钥> [--port <端口号>]- 描述: 直接使用一个已经存在的预授权密钥来激活节点。此命令非常智能:它会先检查 SSH 隧道是否存在,如果不存在,则会自动为您启动一个。
- 选项:
--port <端口号>: 在自动启动隧道时,可以临时指定一个端口。
- 示例:
msh link hskey-e-a1b2c3d4e5f6...
msh config <sub-command> [options]- 描述: 提供了一组用于查看和修改本地配置文件的便捷命令,避免了手动编辑的麻烦。
- 子命令:
get [KEY]: 查看全部或单个配置项的值。# 查看所有配置 msh config get # 只看 SSH_USER 的值 msh config get SSH_USER
set <KEY> <VALUE>: 修改一个配置项的值。# 将 SSH 用户改为 'ubuntu' msh config set SSH_USER ubuntu
edit: 使用默认的命令行编辑器 ($EDITOR,vim,nano) 打开配置文件进行手动编辑。msh config edit
在 Windows 11 (22H2 或更高版本) 上使用 WSL2 时,推荐启用 mirrored 网络模式。这允许 WSL 和 Windows 共享网络接口,从而实现更高级的协作。
在这种模式下,正确的做法是:在 Windows 上建立主隧道,然后在 WSL 中“借用”该隧道来激活节点。
工作流程:
-
在 Windows PowerShell 中启动主隧道:
# 切换到 win-powershell 目录 cd win-powershell # 运行 start 命令 .\msh.ps1 start
这会在 Windows 上建立唯一的 SSH 隧道,并激活 Windows 的 Tailscale 节点。
-
在 WSL 终端中激活节点:
# 直接运行 activate 命令,它会自动借用 Windows 的隧道 msh activate这不会创建新隧道,而是通过 Windows 的隧道来激活 WSL 的 Tailscale 节点。
完成后,您的 Windows 和 WSL 将作为两个独立的设备出现在 Headscale 网络中,并且都能正常通信。
如果您希望从系统中移除本工具,请在项目目录中运行卸载脚本:
sudo ./uninstall.sh在运行工具前,请确保您已完成以下配置。工具会自动检查这些条件,并在不满足时给出提示。
-
修改 Hosts 文件: 在您的 本地客户端机器 上,编辑
/etc/hosts文件 (需要sudo权限),添加以下行:127.0.0.1 your.headscale.domain.com(工具会自动检查该配置是否存在) 注意: 如果您使用自定义端口(例如在 WSL 中),此步骤依然是必需的,因为 Tailscale 客户端需要通过域名来验证 TLS 证书。
-
配置
TUNNEL_PORT(推荐): 在首次运行时,配置向导会提示您输入TUNNEL_PORT,默认为443。v4.1 建议:- 标准 Linux 环境:使用默认的 443 端口
- WSL2 的
mirrored网络模式:建议设置为10443,避免权限和冲突问题
-
配置 SSH 免密登录: 确保您可以从本地机器通过 SSH 密钥免密码登录到您的 Headscale 服务器。
-
SSH Agent 配置: 工具会检查您的 SSH Agent 中是否已加载私钥。在运行前,请确保执行了以下命令来加载密钥:
eval $(ssh-agent -s) ssh-add /path/to/your/private_key
-
错误:/etc/hosts 文件缺少必要的条目。 -> 请按照“前提条件”中的说明,编辑
/etc/hosts文件。 -
错误:缺少核心依赖 'xxx'。 -> 请根据提示安装缺失的命令行工具。例如,在 Debian/Ubuntu 上:
sudo apt-get install openssh-client netcat-openbsd。 -
错误:未能从服务器获取有效的预授权密钥 (或 Permission denied)。 -> 这个错误通常意味着 SSH 密钥认证失败。请检查:
- 您的 SSH 免密登录是否配置正确且仍然有效。可以通过
ssh -i <您的密钥路径> <用户名>@<服务器IP>手动测试。 - 确保运行脚本前,您的 SSH 密钥已通过
ssh-add添加到 SSH Agent 中。 - 您在交互式配置中输入的服务器 IP、SSH 用户名和 Headscale 用户名是否正确。
- 服务器上的 Headscale 服务是否正在正常运行。
- 您的 SSH 免密登录是否配置正确且仍然有效。可以通过
-
错误:SSH 隧道在 10 秒内未能成功监听端口 443。 -> 请检查:
- 本地的
443端口是否已被其他程序占用 (sudo lsof -i:443)。 - 服务器的防火墙是否允许 SSH 连接。
- v4.1 新增: 尝试使用其他端口,如
msh start --port 10443
- 本地的
-
错误:无法连接到 Windows 上的 SSH 隧道 -> v4.1 解决方案:
- 在 Windows 上检查隧道状态:
.\msh.ps1 status - 在 WSL 中手动指定端口:
msh activate --port 10443 - 检查端口连通性:
nc -z 127.0.0.1 10443 - 查看 SSH 监听端口:
sudo lsof -i -P -n | grep LISTEN | grep ssh
- 在 Windows 上检查隧道状态:
-
错误:未检测到活动的 SSH 隧道 -> v4.1 智能检测:
- 确保 Windows 隧道已启动:
.\msh.ps1 start - 使用手动端口指定:
msh activate --port 10443 - 检查防火墙设置,确保允许本地连接
- 确保 Windows 隧道已启动: