Docs/ 安全/ 通过 SSH 隧道访问面板

通过 SSH 隧道访问面板

无法从互联网访问的面板,也就无法从互联网发起攻击。

概述

您的应用由 sh0 在 80 和 443 端口上提供服务。而控制所有应用的面板无需对外暴露。在仅隧道模式下,面板只监听 127.0.0.1:9000:唯一的入口是到服务器的 SSH 连接,而您的防火墙已经限制了 SSH,您也已经用密钥保护了它。

为什么不使用公共面板域名

每张 TLS 证书都会发布到公开的证书透明度(Certificate Transparency)日志中,因此像 panel.example.com 这样的面板域名会在证书签发几分钟后出现在 crt.sh 上。扫描器会读取这些日志:公开的面板会被发现并被探测,无论其密码策略如何。

以仅隧道模式安装

在一台新服务器上,以 root 身份运行,且防火墙已限制为仅开放 SSH、80 和 443:

bash
curl -fsSL https://get.sh0.dev | bash -s -- --harden --panel-tunnel-only

在 sh0 首次启动之前,安装程序会写入一个 systemd drop-in,将面板绑定到 127.0.0.1,关闭 *.sh0.app 注册(代理无法访问 localhost 上的面板),并在使用 --harden 时不在 ufw 中开放 9000 端口。安装结束时,它会打印出可直接粘贴到您自己电脑上的 ssh 命令。

Warning
在此模式下,您的应用会失去免费的 *.sh0.app 地址。*.sh0.app 代理通过 9000 端口访问服务器,而仅隧道模式会关闭该端口,因此每个应用都必须使用您自己的域名提供服务。如果您或您的开发者没有域名,请保留默认安装:面板仍可通过 9000 端口访问,每个应用也会保留其免费地址。
Note
创建第一个所有者账户仍然需要安装令牌,可在服务器上通过 sudo sh0 setup-token 读取。在隧道之后虽然没有其他人能访问面板,但规则在任何地方都一样。

打开隧道

1. 在您自己的电脑上(而不是服务器上)打开隧道,并保持命令运行:

bash
ssh -N -L 9000:127.0.0.1:9000 root@SERVER_IP

2. 打开 http://localhost:9000。流量在 SSH 内部传输:即使地址以 http:// 开头,也没有任何内容以明文形式经过网络。按 Ctrl+C 关闭隧道。

3. 为了不必每次重新输入,请在您电脑的 ~/.ssh/config 中添加一个配置块:

text
Host sh0-panel
    HostName SERVER_IP
    User root
    LocalForward 9000 127.0.0.1:9000
    SessionType none
    ExitOnForwardFailure yes

之后运行 ssh sh0-panel 即可打开隧道。SessionType none 需要 OpenSSH 8.7 或更高版本;如果客户端较旧,请删除该行并运行 ssh -N sh0-panel。

常见故障

现象原因与解决方法
ssh 卡住,随后提示 “Connection timed out”SSH 本身被过滤:您的 IP 未被服务商防火墙允许,或服务器监听在其他端口(添加 -p 端口)。问题不在隧道。
“bind [127.0.0.1]:9000: Address already in use”您电脑上的 9000 端口已被占用,通常是另一个隧道。请换一个本地端口:-L 9001:127.0.0.1:9000,然后访问 http://localhost:9001。
浏览器在 localhost:9000 上提示 “连接被拒绝”隧道未打开(ssh 命令已停止),或服务器上的 sh0 未运行:systemctl status sh0。
ssh 窗口中出现 “channel 2: open failed: connect failed”SSH 正常,但服务器上的 127.0.0.1:9000 没有响应,或 sshd 中关闭了 AllowTcpForwarding。请检查 ss -ltn | grep 9000 和 sshd -T | grep allowtcpforwarding。

切换现有服务器

已经运行 sh0 的服务器,只需用相同选项再次运行安装程序即可切换。它会保留您的应用,写入 drop-in,移除已有的 9000 端口 ufw 规则(使用 --harden 时),并重启 sh0 一次,这也会撤销其 *.sh0.app 地址。之后为更新而再次运行安装程序时,只要 drop-in 存在,服务器就会保持仅隧道模式。

bash
curl -fsSL https://get.sh0.dev | bash -s -- --harden --panel-tunnel-only

您的应用会继续在其域名上响应:它们由 Caddy 在 80 和 443 端口上提供服务,切换不会改动这两个端口。sh0 重启期间会有几秒钟的中断。如果已设置面板域名,安装程序会在做任何更改之前停止并说明原因(见下一节)。

隧道无法关闭的部分

Warning
仅隧道模式只是将面板自身的监听移到 127.0.0.1,并不会移除面板域名:如果 sh0 panel-domain 显示了一个域名,Caddy 会继续通过 443 端口在该域名上向整个互联网提供面板。若要真正做到仅隧道,请移除该域名。只要通过 sh0 panel-domain 或服务环境中的 SH0_PANEL_DOMAIN 设置了域名,安装程序就会拒绝 --panel-tunnel-only,并且需要 sh0 1.10.6 或更高版本;以其他方式配置的域名不会被检测到,请自行检查。
bash
sudo sh0 panel-domain          # show
sudo sh0 panel-domain clear    # remove the route and the setting

不使用隧道的浏览器访问

如果您的团队无法使用隧道,可以保留面板域名,但要在其前面放置 Cloudflare Access(或同类身份感知代理),并在服务商防火墙上将 443 端口限制为 Cloudflare 的 IP 段。缺少第二步,直接连接服务器 IP 就能绕过 Access。该限制会影响服务器上的所有应用:它们的每个域名也都必须经过 Cloudflare 代理,否则将无法访问。不要将此方式与 --panel-tunnel-only 一起使用。

检查结果

在服务器上,面板必须只监听回环地址,不得设置面板域名,sh0 doctor 不得报告任何失败。从其他网络访问时,9000 端口必须是关闭的。

bash
ss -ltn | grep ':9000'          # 127.0.0.1:9000 only
cat /etc/systemd/system/sh0.service.d/panel-tunnel-only.conf
sudo sh0 panel-domain            # Domain: not set
sudo sh0 doctor

恢复原状

如需让面板重新通过服务器地址访问,请删除 drop-in、重启 sh0 并重新开放端口:

bash
rm /etc/systemd/system/sh0.service.d/panel-tunnel-only.conf
rm /etc/systemd/system/sh0.service.d/cloud-registration.conf   # only to get *.sh0.app back
systemctl daemon-reload && systemctl restart sh0
ufw allow 9000/tcp                                              # if the firewall is ufw

主机的其余部分(SSH 密钥、防火墙、fail2ban)请参阅 保护您的服务器