Guangyang Li

通过自建 DNS 给仅内网访问的群晖 NAS 做域名解析

我对 NAS 的使用态度一向是尽量不开放外网访问,因为它最重要的功能是备份文件。我存放的就是家庭照片、影音,和各种记录。这些文件的安全性要远比安装其他服务带来的便利重要得多。

但是只能内网访问的 NAS 有一个麻烦,就是使用内网 IP 或内网域名无法申请 SSL 证书,访问时浏览器总会有个不安全警告。自签名证书虽然可以解决这个问题,但需要在每个客户端上安装证书,还是比较麻烦。另一个解决方案是内网自建 DNS,把自有的顶级域名指向内网地址,并能使用这个域名申请 SSL 证书,实现安全访问。

如果你也只是需要绑定域名和 HTTPS,那么完全没有必要因此而设置 DDNS 开启外网访问。可以根据本文方法使用 Pi-hole 在内网解析自定义域名,避免 NAS 不必要的联网,又允许了域名证书的使用,告别“不安全”警告。本文也介绍了通过反向代理给 NAS 内其他服务绑定二级域名,实现 HTTPS 且无需端口号的访问

先看要实现的目标效果:

通过自建 DNS 给仅内网访问的群晖 NAS 做域名解析效果

通过 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 创建,就需要手动添加上 TZWEBPASSWORDFTLCONF_LOCAL_IPV4 三个变量,至少将容器的 53 端口映射到本地的 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,当然仅作用于内网。

Pi-hole local DNS 的示例设置

能成功访问后,可以根据我的文章群晖 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。

在 Pi-hole 中绑定子域名

对于大部分服务,这样的反代设置和域名绑定就足够了。但对于下面的服务,还需要一些额外设置。

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”。