通过自建 DNS 给仅内网访问的群晖 NAS 做域名解析
我对 NAS 的使用态度一向是尽量不开放外网访问,因为它最重要的功能是备份文件。我存放的就是家庭照片、影音,和各种记录。这些文件的安全性要远比安装其他服务带来的便利重要得多。
但是只能内网访问的 NAS 有一个麻烦,就是使用内网 IP 或内网域名无法申请 SSL 证书,访问时浏览器总会有个不安全警告。自签名证书虽然可以解决这个问题,但需要在每个客户端上安装证书,还是比较麻烦。另一个解决方案是内网自建 DNS,把自有的顶级域名指向内网地址,并能使用这个域名申请 SSL 证书,实现安全访问。
如果你也只是需要绑定域名和 HTTPS,那么完全没有必要因此而设置 DDNS 开启外网访问。可以根据本文方法使用 Pi-hole 在内网解析自定义域名,避免 NAS 不必要的联网,又允许了域名证书的使用,告别“不安全”警告。本文也介绍了通过反向代理给 NAS 内其他服务绑定二级域名,实现 HTTPS 且无需端口号的访问。
先看要实现的目标效果:

通过 https://home.guangyang.li/ 和 https://ha.guangyang.li/ 可以访问到我的 NAS 和上面的 Home Assistant 服务,不需要输入端口号,浏览器没有“不安全”警告,只允许内网访问。
1. Pi-hole 简介
Pi-hole 是一款开源的支持广告拦截的 DNS 服务器。它原本是为运行在树莓派上而开发,但现在已经支持多个平台,包括群晖 DSM。在网关上部署自己的 DNS 服务优诸多好处,包括:
- 实现将指定域名解析到某个内网 IP,而无需在所有客户端上修改 hosts 文件。
- 对所有客户端的默认 DNS 服务器控制。通过指定 upstream DNS,绕开默认使用的 ISP 服务商的 DNS,避免将访问记录暴露给不信任的 ISP。
- 对屏蔽列表的集中管理。在 DNS 层面将广告地址屏蔽是一种比较便捷的方式,可以作用于系统或浏览器没有广告屏蔽功能的设备上。但随着家庭设备增加,在多设备中维护一份屏蔽列表变得困难,因此需要集中管理。
2. 使用 Pi-hole 在群晖 NAS 中搭建 DNS 服务
在群晖 DSM 中安装 Pi-hole 的最便捷方法是 Docker。
先在 docker 目录下创建 pihold 文件夹,并在里面创建 config 和 dnsmasq 文件夹。
再修改下面命令中的 <YOUR_TIMEZONE>
,<YOUR_WEB_PASSWORD>
和 <YOUR_WEB_PORT>
后执行即可。DNSSEC
变量可以自行判断是否开启,如果不启用,还可以给变量 CUSTOM_CACHE_SIZE 设置更高的值以提升性能,默认是 10000
。
IP=$(echo ${SSH_CONNECTION}|cut -d ' ' -f 3)
sudo docker run -d \
--name=pihole \
-e TZ=<YOUR_TIMEZONE> \
-e WEBPASSWORD=<YOUR_WEB_PASSWORD> \
-e FTLCONF_LOCAL_IPV4=${IP} \
-e DNSSEC=true \
-v /volume1/docker/pihole/config:/etc/pihole \
-v /volume1/docker/pihole/dnsmasq:/etc/dnsmasq.d \
-p <YOUR_WEB_PORT>:80/tcp \
-p 67:67/udp \
-p 53:53/tcp \
-p 53:53/udp \
--cap-add=NET_ADMIN \
--restart=unless-stopped \
pihole/pihole
如果是通过 Docker GUI 创建,就需要手动添加上 TZ
,WEBPASSWORD
和 FTLCONF_LOCAL_IPV4
三个变量,至少将容器的 53 端口映射到本地的 53 端口,并手动加载上面创建的两个文件夹。

运行后可用通过 http://<NAS_IP>:<YOUR_WEB_PORT>
确认 Pi-hole 已经启动。
之后在路由器中将 DNS 服务器修改为 Pi-Hole 所在的 NAS 的 IP 地址,就无需在各终端设备上指定 DNS 服务器。
Pi-hole 启动后,在 Web UI 的 Local DNS -> DNS Records 里绑定你的域名。例如可以将 example.com 解析到 NAS 的内网 IP。保存后你就可用通过 example.com 访问 NAS,当然仅作用于内网。

能成功访问后,可以根据我的文章群晖 NAS 上快速申请与自动部署 SSL 证书给这个域名申请 SSL 证书。这样就实现了通过域名和有效证书访问内网 NAS。
3. 给 NAS 上的其他服务绑子域名并启用 HTTPS
有了自建 DNS 服务器,可用很方便地给 NAS 上的其他服务绑定子域名,就无需通过端口号来区分不同服务了。搭配反向代理,可以实现通过 https://ha.example.com 访问 Home Assistant,https://jellyfin.example.com 访问 Jellyfin 这样的效果。
在 DSM 的控制面版中 Login Portal -> Advanced -> Reverse Proxy 里添加反向代理记录。在 Source 下选择 HTTPS 并输入绑定的子域名,如 ha.example.com。端口可用使用 HTTPS 的默认端口 443,因为这个子域名下只有一个服务。Destination 下选择 HTTP 协议,指定内网 IP 和对应服务的 HTTP 端口。

之后,在同窗口下的 Custom Header 下选择 Create -> WebSocket,然后保存确认即可。
在 Pi-hole 中,还需要将子域名绑定到 NAS 的 IP。

对于大部分服务,这样的反代设置和域名绑定就足够了。但对于下面的服务,还需要一些额外设置。
Home Assistant
到 Home Assistant 的配置目录找到 configuration.yaml,添加如下配置:
http:
use_x_forwarded_for: true
trusted_proxies:
- 192.168.0.10
将其中的 192.168.0.10
替换为 Pi-hole 的地址。之后重启 Home Assistant 即可。
Jellyfin
在 Jellyfin Web UI 中 Advanced -> Networking 下勾选 “Allow remote connections to this server”。