家里跑了好几个服务,Home Assistant、SearXNG、Alist、Emby,还有签到之类的杂七杂八。每个服务一个端口,手机上记端口记到崩溃。

以前我用 HeoSafe 拦截方案做访问控制,检测到流量直接弹身份认证。能用,但本质上还是请求到了之后再拦,配置维护比较重,算不上好的解决方式。

后来想通了,干脆把链路整清楚:ZeroTier 组网 + DNS 域名解析 + iStore Nginx 反代 + certd 证书管理,一套走通。

硬件和系统

R5S 软路由刷的 iStoreOS,基于 OpenWrt。Nginx 通过 iStore 应用商店直接装,不是 Docker。这个很重要,因为 iStore 装的 Nginx 有自己一套 UCI 配置,和传统手动装的不一样。

装完之后 Nginx 自动接管 80/443,uHTTPd 原来的 LuCI 也被接管了,不用额外折腾。

nginx安装

ZeroTier 组网

ZeroTier 解决的是跨网络访问问题。装完客户端加入同一个网络,设备之间就像在同一个局域网里。

R5S 上 ZeroTier 分配的内网 IP 是 10.225.17.77。手机、电脑、iPad 加入同一个网络后都能直接访问这个 IP。

但 IP 记不住,所以需要 DNS。

DNS 解析

域名 zhheo.com 托管在腾讯云 DNSPod,直接在 DNSPod 加 A 记录:

1
2
3
4
5
6
s.zhheo.com        → 10.225.17.77
heohass.zhheo.com → 10.225.17.77
heodisk.zhheo.com → 10.225.17.77
emby.zhheo.com → 10.225.17.77
qiandao.zhheo.com → 10.225.17.77
certd.zhheo.com → 10.225.17.77

这里的 IP 是 ZeroTier 内网 IP,不是公网 IP。所以这些域名只有加入 ZeroTier 网络的设备才能访问,公网打不通。这反而是个安全优势。

Nginx 反向代理

Nginx 装好之后,配一个反代配置文件就行。我放在 /etc/nginx/conf.d/zhheo-services.conf,iStore 的 Nginx 会自动加载这个目录下的 .conf 文件。

每个域名对应一个后端端口:

1
2
3
4
5
6
s.zhheo.com        → 127.0.0.1:19080   # SearXNG
heohass.zhheo.com → 127.0.0.1:8123 # Home Assistant
heodisk.zhheo.com → 127.0.0.1:5244 # Alist
emby.zhheo.com → 127.0.0.1:18080 # Emby
qiandao.zhheo.com → 127.0.0.1:8923 # 签到
certd.zhheo.com → 127.0.0.1:12281 # certd

配置模板大概是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 443 ssl;
server_name heohass.zhheo.com;
ssl_certificate /etc/nginx/conf.d/wildcard.zhheo.com.crt;
ssl_certificate_key /etc/nginx/conf.d/wildcard.zhheo.com.key;

location / {
proxy_pass http://127.0.0.1:8123;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
}

Home Assistant 需要 WebSocket 支持,所以加了 UpgradeConnection 头。其他服务一般不需要,但加上也没坏处。

改完配置后:

1
nginx -t -c /etc/nginx/uci.conf && nginx -s reload -c /etc/nginx/uci.conf

iStore 的 Nginx 必须用 -c /etc/nginx/uci.conf,直接 nginx -t 会报找不到文件。

certd 证书管理

裸 HTTP 能用,但手机浏览器会弹不安全提示。所以用 certd 管理通配符证书。

certd 也是 Docker 部署在 R5S 上的,自动申请和续期证书。部署方式选的是「主机-部署证书到 SSH 主机」,直接把证书文件写到 R5S 宿主机:

添加步骤

1
2
/etc/nginx/conf.d/wildcard.zhheo.com.crt
/etc/nginx/conf.d/wildcard.zhheo.com.key

部署完成后 Nginx 不会自动读取新证书,必须手动 reload:

1
nginx -t -c /etc/nginx/uci.conf && nginx -s reload -c /etc/nginx/uci.conf

这里踩了个坑:iStore 的 Nginx UCI 配置里有个选项叫 uci_manage_ssl,默认值是 self-signed。不关掉它,Nginx reload 时会自动生成自签名证书,覆盖掉你刚部署的通配符证书。解决方法:

1
2
uci delete nginx._lan.uci_manage_ssl
uci commit nginx

删掉这个选项之后,Nginx 就不会自动搞证书了。

另外私钥权限设成 600

1
chmod 600 /etc/nginx/conf.d/wildcard.zhheo.com.key

完整链路

1
2
3
4
5
6
7
手机/电脑/iPad
↓ ZeroTier 组网
R5S 软路由(10.225.17.77)
↓ DNS 域名解析
Nginx 反向代理(80/443)
↓ 按域名分发
各服务后端端口

体验上就是:加入 ZeroTier 网络后,手机浏览器直接输入 https://heohass.zhheo.com,无警告、无拦截,直接到 Home Assistant。

比之前 HeoSafe 的方案清爽多了。

踩坑记录

  1. iStore Nginx 的 nginx -t 要加 -c /etc/nginx/uci.conf,否则直接报错。
  2. uci_manage_ssl='self-signed' 会覆盖证书文件,部署正式证书前必须删掉。
  3. Nginx 不会自动重新读取证书,部署后必须 reload。
  4. Home Assistant 的 X-Forwarded-* 头会导致 400,其他服务的转发头不要随便加到 HA 的 vhost 上。
  5. DNSPod 刷新有延迟,刚改完记录可能要等几分钟才能查到。
  6. Nginx reload 要用 nginx -s reload -c /etc/nginx/uci.conf,用 /etc/init.d/nginx reload 可能触发 iStore 的 SSL 自动生成逻辑。

相关地址