UDM-SE 本地 DNS 记录设置
最近更新了家里的网络设备,用 UDM-SE(Dream Machine Special Edition) 替换了 ER-X。相较于 ER-X 上运行的 EdgeOS,UDM-SE 运行的是 Unifi OS,所有网络设置都收口到了 UniFi Network Application 中,界面更为友好,但是也缺少了一定的自由度。这篇文章记录了内网 DNS 配置的折腾过程。
最近更新了家里的网络设备,用 UDM-SE(Dream Machine Special Edition) 替换了 ER-X。相较于 ER-X 上运行的 EdgeOS,UDM-SE 运行的是 Unifi OS,所有网络设置都收口到了 UniFi Network Application 中,界面更为友好,但是也缺少了一定的自由度。这篇文章记录了内网 DNS 配置的折腾过程。
0
家里内网的服务器上跑了一些服务,比如 Plex、Home Assistant,为了使用方便,加了一层 Nginx 反向代理,并绑定了内网域名。在 EdgeOS 中可以通过 static-host-mapping 配置来设置本地 DNS 记录,在 Unifi Network Application 中,可以通过 UI 为客户端设置 Local DNS Record。
这种方式设置的 DNS 记录是设备纬度的,只支持设置 1 个域名,而我用 Nginx 反代需要给一个 IP 配置多个域名。于是在不额外部署 DNS 服务器的情况下,我开始了以下一系列对 Unifi OS 的探究😃。
1
首先,先要确认 Unifi OS 用的 DNS 服务是什么。
ps aux | grep dns
# 以下是结果
/usr/sbin/dnsmasq --conf-dir=/run/dnsmasq.conf.d/ --pid-file=/run/dnsmasq.pid --resolv-file=/etc/resolv.dnsmasq
可以看到用的是 dnsmasq,一般来说 dnsmasq 会读取 /etc/hosts 中的记录,那就容易了,立马把 dns 记录添加到 /etc/hosts 中,结果并没有生效😓。根据进程启动信息查看了 /run/dnsmasq.conf.d/ 目录下的配置文件:
- 目录下 share.conf 中配置了 no-hosts,所以忽略了 /etc/hosts 中的记录。
- 目录下 dns.conf 中存在 host-record 设置,上面通过 UI 设置的 Local DNS Record 记录也在内。
通过这几个配置文件中的备注可以确认该目录下的配置文件由 ubios-udapi-server 自动生成,每次 dnsmasq 服务启动前会重新生成。因此如果直接修改 share.conf 和 dns.conf ,配置生效需要重启 dnsmasq,而重启 dnsmasq 时 ubios-udapi-server 会重新覆盖配置文件,死循环了。
2
既然 dnsmasq 的配置文件是由 ubios-udapi-server 生成的,那么合理猜测 dnsmasq 进程可能也是由 ubios-udapi-server 管理的,通过查看 dnsmasq 进程的父进程信息验证了这个猜测。
接下来顺藤摸瓜看看 ubios-udapi-server 是什么:
ps aux | grep ubios-udapi-server
# 以下是结果
/usr/bin/ubios-udapi-server -c /data/udapi-config/ubios-udapi-server/ubios-udapi-server.state --silent
ubios-udapi-server --help
Usage: ubios-udapi-server [opts]
Options:
-h, --help show this help
-v, --verbose print more information
-x, --extremely-verbose print also UDAPI communication
-t, --timestamp print timestamp in milliseconds
-S, --silent stop logging to stdout
-c, --config [arg] configuration file (default /config/ubios-udapi-server/ubios-udapi-server.state)
-d, --default-config [arg] default/factory configuration file (default /usr/share/ubios-udapi-server/udm-pro-se-ea2c.default)
-f, --fallback-config [arg] fallback configuration file (default /usr/share/ubios-udapi-server/udm-pro-se-ea2c.fallback)
-s, --socket [arg] server socket (default /var/run/ubnt-udapi-server.sock)
-e, --event-socket [arg] event socket (default /var/run/ubnt-udapi-bridge-event.sock)
没有详细的介绍,但是根据参数的介绍可以猜测 ubios-udapi-server 是用来管理 Unifi OS 配置及对应服务的。
接下来看一下 /data/udapi-config/ubios-udapi-server/ubios-udapi-server.state 这个配置文件里面都有什么。文件比较大就不贴出来了,实际上就是一个 JSON 格式的配置文件,记录了 UDM-SE 用到的所有配置信息(比如拨号信息、DHCP 等),在 services.dnsForwarder.hostRecords 节点可以看到我们之前通过 UI 设置的 DNS 记录。
{
···
"services":{
"dnsForwarder": {
"cnameRecords": [],
"domainForwards": [],
"enabled": true,
"forwardBehavior": "allServers",
"hostRecords": [{
"address": {
"address": "192.168.100.10",
"origin": null,
"version": "v4"
},
"hostName": "appletv.mydomain.com",
"registerNonQualified": true
}]
}
}
···
}
到这里基本可以确认 Unifi OS 的运作逻辑了,系统启动时,ubios-udapi-server 会根据 ubios-udapi-server.state 去生成不同服务需要的配置文件(放在 /run 目录下),并启动相关服务。那么只要手动把 DNS 记录添加到 ubios-udapi-server.state 中,下次启动后就能生效了。折腾过程中在官方社区还找到了通过 ubios-udapi-client 修改配置的方法,可以实时生效不需要重启系统。由于 ubios-udapi-client 没有官方文档,有网友写了相关脚本 udm-host-records ,这里就不展开了。
3
到这里,已经可以实现配置内网 DNS 静态记录了,但是参考 udm-host-records 作者的描述,修改 ubios-udapi-server.state 的方式不可控,系统可能在某些时候会覆盖我们的配置。
This was a brief attempt at providing local network DNS resolution. But because it's clear that the hostRecords
are overwritten by Ubiquiti-owned code in a bunch of scenarios that don't seem to warrant it, it's clear that this approach to gaining a bit of local DNS control isn't sustainable. Please consider running your own local DNS, such as PiHole instead
于是,我还是回到了 dnsmasq 上,系统启动 dnsmasq 的时候设置了 --conf-dir=/run/dnsmasq.conf.d/,因此可以在该目录下新增配置文件:
# hosts.conf
host-record=a.mydomain.im,192.168.100.10
host-record=b.mydomain.im,192.168.100.10
/run 目录下的文件,每次系统启动时会被清空,我们可以放在个人目录下,在 /run/dnsmasq.conf.d 下创建软链接。那么什么时候去创建软链接呢,Unifi OS 2.x 以下版本可以参考 unifios-utilities 添加启动脚本,按作者所说 Unifo OS 3.x 失效了,所以我没有细看。退而求其次,可以在 /etc/ppp/ip-up.d 创建脚本,这样每次拨号成功后会自动执行。
#!/bin/sh
ln -sf /root/config/dnsmasq/hosts.conf /run/dnsmasq.conf.d/hosts.conf
kill -9 "$(cat /run/dnsmasq.pid)"
总结
- 单条 DNS 记录可以通过 UI 给客户端设置 Local DNS Records。
- 多条 DNS 记录可以新增 dnsmasq 配置文件来实现。