
前两篇已经把 FreshRSS 和 PaperHot 放到了 Cloudflare Tunnel 后面。
FreshRSS 解决的是“我在外面也能看自己的信息流”。PaperHot 解决的是“我在外面也能看自己跑起来的论文热榜”。这篇再往前走一步:不只是访问一个网页服务,而是直接从家里的 Mac 连回办公室 Fedora。
最后我想要的效果很简单:
ssh office-fedora
不用公网 IP,不用路由器端口转发,也不把 22 端口暴露到公网。
链路大概是这样:
家里 Mac
↓
cloudflared access ssh
↓
ssh-office.seis-jun.xyz
↓
Cloudflare Tunnel
↓
办公室 Fedora: 127.0.0.1:22
现有基础
我已经有一个 Cloudflare Tunnel 在办公室 Fedora 上运行,名字是:
freshrss-office
这个 Tunnel 之前已经承载了两个服务:
rss.seis-jun.xyz
paper-hot.seis-jun.xyz
所以这次不需要新建 Tunnel,只是在已有 Tunnel 里增加一个 SSH 入口:
ssh-office.seis-jun.xyz
这点很重要。FreshRSS、PaperHot、SSH 其实都可以走同一条 Tunnel,只是 ingress 规则不同。
先确认办公室 Fedora 的 SSH 服务
在办公室 Fedora 上先确认 OpenSSH server 已经安装并启动:
sudo dnf install -y openssh-server
sudo systemctl enable --now sshd
sudo systemctl status sshd --no-pager
正常应该能看到:
Active: active (running)
然后在 Fedora 本机测试一下:
ssh junxie@127.0.0.1
如果本机都连不上,就先修 SSH 服务。不要一上来就怀疑 Cloudflare。
给 Tunnel 增加 SSH 入口
Cloudflare Tunnel 的配置在办公室 Fedora 上:
/root/.cloudflared/config.yml
修改前先备份:
sudo cp /root/.cloudflared/config.yml /root/.cloudflared/config.yml.bak.$(date +%Y%m%d_%H%M%S)
然后在 ingress 里增加:
- hostname: ssh-office.seis-jun.xyz
service: ssh://127.0.0.1:22
最终结构类似这样:
tunnel: 5c3de280-c626-4bc4-83db-5eef8d13ce76
credentials-file: /root/.cloudflared/5c3de280-c626-4bc4-83db-5eef8d13ce76.json
ingress:
- hostname: rss.seis-jun.xyz
service: http://127.0.0.1:8080
- hostname: paper-hot.seis-jun.xyz
service: http://127.0.0.1:8000
- hostname: ssh-office.seis-jun.xyz
service: ssh://127.0.0.1:22
- service: http_status:404
注意最后一行:
- service: http_status:404
它必须放在最后。前面的规则都没匹配到时,才走 404。
添加 DNS 路由并重启 Tunnel
在办公室 Fedora 上执行:
sudo cloudflared tunnel route dns freshrss-office ssh-office.seis-jun.xyz
sudo systemctl restart cloudflared-freshrss.service
sudo systemctl status cloudflared-freshrss.service --no-pager -l
再检查 DNS:
dig @1.1.1.1 ssh-office.seis-jun.xyz +short
如果能解析,说明 Cloudflare 这一侧已经有记录了。
家里 Mac 安装 cloudflared
在家里的 Mac 上安装:
brew install cloudflare/cloudflare/cloudflared
确认路径:
which cloudflared
cloudflared --version
我这里的路径是:
/opt/homebrew/bin/cloudflared
这个路径后面要写进 SSH 配置里。如果你的机器上不是这个路径,就用实际路径。
配置家里 Mac 的 SSH
编辑 SSH 配置:
mkdir -p ~/.ssh
nano ~/.ssh/config
加入:
Host office-fedora
HostName ssh-office.seis-jun.xyz
User junxie
ProxyCommand /opt/homebrew/bin/cloudflared access ssh --hostname %h
ServerAliveInterval 60
ServerAliveCountMax 3
然后设置权限:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
这里的关键是 ProxyCommand。
平时 SSH 是直接连目标机器。现在不是。现在是 SSH 先调用 cloudflared,让它通过 Cloudflare Tunnel 把连接转到办公室 Fedora 的本地 22 端口。
正式连接
以后在家里只需要:
ssh office-fedora
第一次连接可能会提示确认 host key:
Are you sure you want to continue connecting?
输入:
yes
然后输入 Fedora 用户密码,或者用 SSH key 登录。
成功后就会进入办公室 Fedora:
junxie@fedora:~$
这一步打通之后,感觉就和机器在身边差不多了。
常用排查
如果连接失败,先按这个顺序查。
办公室 Fedora 上:
sudo systemctl status sshd --no-pager
sudo systemctl status cloudflared-freshrss.service --no-pager -l
sudo cat /root/.cloudflared/config.yml
家里 Mac 上:
which cloudflared
cloudflared --version
dig @1.1.1.1 ssh-office.seis-jun.xyz +short
ssh -v office-fedora
如果 Fedora 本机 ssh junxie@127.0.0.1 都不通,那问题在 SSH 服务。
如果 DNS 解析不了,那问题在 Cloudflare DNS 或 Tunnel route。
如果 Tunnel 通了但登录失败,那多半是用户名、密码或 SSH key 的问题。
安全上要克制一点
这个方案的好处是没有直接暴露办公室 Fedora 的 22 端口。
但也不要因此觉得可以随便加入口。
我现在的原则是:
公开域名入口尽量少
先接办公室 Fedora
再从 Fedora 跳到内网机器
如果以后要从家里继续连单位内网服务器,可以用 ProxyJump:
Host unit-server
HostName 10.xx.xx.xx
User unit_user
ProxyJump office-fedora
这样家里仍然只需要:
ssh unit-server
实际路径是:
家里 Mac
↓
Cloudflare Tunnel
↓
办公室 Fedora
↓
单位内网服务器
不建议一开始就把单位服务器直接做成一个新的公网 hostname。边界会更复杂,也更容易踩单位网络安全规定。
当前状态
这次最后完成的是:
1. 办公室 Fedora 的 sshd 已启动。
2. Fedora 本机 ssh junxie@127.0.0.1 测试成功。
3. Cloudflare Tunnel 增加了 ssh-office.seis-jun.xyz。
4. ssh-office.seis-jun.xyz 已指向 freshrss-office Tunnel。
5. 家里 Mac 已安装 cloudflared。
6. 家里 Mac 已配置 ~/.ssh/config。
7. 家里 Mac 可以通过 ssh office-fedora 连回办公室 Fedora。
最终日常使用命令就是:
ssh office-fedora
FreshRSS 和 PaperHot 让我在外面能访问自己的服务。这个 SSH 入口则更进一步:让我在外面能回到那台真正干活的办公室 Fedora。
这比单独部署一个网页服务更像是把工作环境接回来了。
Comments