本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 [署名 4.0 国际 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/deed.zh) 本文作者: 苏洋 创建时间: 2026年01月03日 统计字数: 5733字 阅读时间: 12分钟阅读 本文链接: https://soulteary.com/2026/01/03/split-dns-for-cross-platform-dual-machine-dev.html ----- # 用 Split DNS 提升跨系统双机开发体验 这篇文章记录一个很“朴素”的诉求:我希望把 macOS 当作主力输入设备,把 Ubuntu 设备当作移动工作站与服务承载机。两台设备通过雷电网桥或同一热点互联后,Mac 侧可以像在本机一样访问 Ubuntu 上的各种站点和服务,同时不牺牲 macOS 的日常网络体验。 ## 写在前面 不论是出差还是在办公室,在保证数据安全和私密性的前提下,我希望打开 Mac 就能够像在本地一样访问各种开发服务。 更具体一点: - 我希望不用改 hosts 文件,不用手工维护 DNS 服务里的几十上百条域名记录 - 我希望设备之间数据联通是高效的,能用最少的时间成本做实验验证 - 我希望 Mac 少跑一些“不必要的服务”,减少兼容性与维护成本,做到“开盖打字,合盖走人” 连上雷电数据线,或者连上同一个手机 Wi-Fi 热点,一切就顺其自然发生。 ## 硬件环境 我使用一台 MacBook Air 作为主力打字设备,不希望它承担太多后台服务,尽量维持轻量、稳定、响应快。 另外一台设备是一台安装了 Ubuntu 的移动工作站。它原本是 Windows 设备(ROG 幻 X 旧款,《[便携移动工作站,端侧 AI 大模型设备折腾笔记:ROG 幻 X 和 4090 扩展坞](https://soulteary.com/2024/07/30/portable-mobile-workstation-edge-ai-device-notes-rog-flow-x13-and-4090-docking-station.html)》有提及),后来切换到 Ubuntu 并持续升级,目前系统版本为 Ubuntu 25.10。它承担的职责很明确:跑服务、跑 CI、跑各种需要 Linux 环境才能更省事的东西。 两台设备通过雷电网桥天然可以建立高速点对点网络,稳定性也很不错。我测试过不同品牌的雷电主动线与被动线,连续连接过夜第二天仍能正常工作。简单来说,雷电网桥在这个场景里是可靠的“物理基础设施”。 关于雷电连接,在之前的文章中有提到过:《[廉价的全闪存雷电 NAS 折腾笔记:组网方案的选择](https://soulteary.com/2023/08/31/cheap-pure-flash-thunderbolt-nas-tossing-notes-the-choice-of-networking-solutions.html)》、《[MacBook 与其他设备的低成本高性能数据传输方案(一)](https://soulteary.com/2023/01/01/low-cost-high-performance-data-transfer-solution-for-macbook-and-other-devices.html)》、《[MacBook 与其他设备的低成本高性能数据传输方案(二)](https://soulteary.com/2023/01/03/low-cost-high-performance-data-transfer-solution-for-macbook-and-other-devices-part-2.html)》,感兴趣可以翻阅。 ## 软件环境与目标 简单概括,这个是典型的“很多本地域名 → 同一台开发机”的场景。 Ubuntu 设备上运行了很多网站和服务,提供给内网环境使用。通过雷电网桥连接后,我会把 Ubuntu 侧固定在一个稳定的 IP,比如 `192.168.123.200`。macOS 侧只要在同网段即可,IP 地址本身并不重要。 这里我们不希望在任何一台设备上再绑定 hosts,维护起来太麻烦了,少一两个还行,特别多的子域名和持续迭代过程中,体验太差了。要做到只让“开发域名”走 Ubuntu 的本地 DNS,其它正常上网域名仍然走 macOS 默认 DNS,不会互相影响。整个场景类似我们的设备连接到虚拟专用网络后,获取特别的 DNS。但因为雷电网络特性,我们通常只需要一次设置就能够持续性的使用。 真正想解决的是域名维护成本: - 不想在任意设备上维护 hosts - 不想在 macOS 上改全局 DNS,避免影响日常网络体验 - 希望开发域名解析规则可迁移、可复制、可排错 最终想要的效果是: - 开发域名只走 Ubuntu 的本地 DNS - 公网域名仍然走 macOS 的默认 DNS - 配置一次长期使用,插上雷电线/网线,连上手机Wi-Fi就能工作 核心思路是: 1. Ubuntu 上跑一个轻量 DNS(dnsmasq / CoreDNS),把要用的域名(或一整个后缀)解析到 `192.168.123.200` 2. macOS 用 “按域名分流的 DNS”(`/etc/resolver` 机制)把某些域名的查询定向到 Ubuntu,其它域名不动 ## 相关概念 ### Split DNS 是什么 Split DNS 可以理解为“分流 DNS”。不同域名使用不同的 DNS 服务器去解析,最常见的分流方式是公网与内网分离: - 公网域名例如 `apple.com`、`soulteary.com`,使用系统默认 DNS,通常来自运营商或公共 DNS 服务 - 内网或开发域名例如 `*.dev.test`、`*.corp.example.com`,使用内网 DNS 或本地 DNS,把域名解析到内网 IP 这样做的好处是,不影响日常上网,内网域名能稳定解析到内网 IP,不需要大量维护 hosts 文件。 本文就是第二种方案的典型应用:只让开发域名走 Ubuntu 本地 DNS,其它域名不动。 ### macOS 的 resolver 机制是什么 macOS 有一套系统级 DNS 解析器,也就是 resolver。它会根据配置与网络环境决定: 1. 解析某个域名时该用哪一组 DNS 服务器 2. 是否命中按域名分流规则 3. 缓存与优先级如何处理 macOS 原生支持“按域名分流”。最容易上手的一种方式就是在 `/etc/resolver/` 目录中创建配置文件,用声明式方式告诉系统: - 某个域名后缀应当使用哪个 DNS nameserver - 其它域名保持默认行为 另外一种,则是通过网络配置下发配置(各种公司使用的专用网络方案),后续文章我们再涉及。而 macOS 之外,其他系统也基本支持类似特性:Windows 有 NRPT(Name Resolution Policy Table);Ubuntu / Linux 中有 `systemd-resolved` 的路由域名,有NetworkManager 的 `per-connection DNS` + 搜索域,有“传统一些的” `resolv.conf`;Android 中有 Private DNS、以及类似 macOS 的网络下发配置方案。 所以,如果你想使用 Windows 设备、Android 平板作为打字设备,只要两台(或几台)设备联通,就能够实现一样的效果啦。 实际使用非常简单,创建一个配置文件 `/etc/resolver/dev.test` ,在其中设置以下内容: ```apache nameserver 192.168.123.200 port 53 ``` 当我们访问 `*.dev.test` 时,这些域名的解析就会被定向到 192.168.123.200,而其他域名依旧走系统默认 DNS。 如果你依旧想使用一台设备进行本地开发域名的管理维护,那么还是可以参考下面几篇文章:《[在线分享 Hosts 规则工具:Remote Hosts Server](https://soulteary.com/2022/10/24/online-sharing-hosts-rules-tool-remote-hosts-server.html)》、《[用于本地开发使用的 DNS 方案](https://soulteary.com/2021/08/19/dns-for-local-development.html)》、《[快速切换 Mac 设备的 DNS 配置](https://soulteary.com/2016/01/20/switch-dns-profile-quickly.html)》。 ## 实战开始 下面以 `dev.test` 作为开发后缀示例。`.test` 是保留给测试用途的域名后缀,使用它可以避免误伤真实公网域名。需要注意的是,在 macOS 系统里 `.local` 会被 Bonjour mDNS 特殊处理,不建议用 `.local` 作为你的开发后缀。 ### 在 Ubuntu 上安装 dnsmasq 并配置“通配解析” 在 Ubuntu 上安装 dnsmasq: ```bash sudo apt update sudo apt install -y dnsmasq ``` 创建配置文件: ```bash sudo tee /etc/dnsmasq.d/dev-domains.conf >/dev/null <<'EOF' # 把 *.dev.test 全部指到 Ubuntu address=/.dev.test/192.168.123.200 # 上游 DNS(避免 dnsmasq 无法解析公网域名时卡住) server=1.1.1.1 server=8.8.8.8 # 只在本机与雷电网桥接口上监听(按需改) listen-address=127.0.0.1,192.168.123.200 bind-interfaces EOF ``` 如果你希望 Ubuntu 设备内的网站的私有网络环境有单独的解析,`listen-address` 部分可以只填 `192.168.123.200` 即可。 重启服务并设置开机启动: ```bash sudo systemctl restart dnsmasq sudo systemctl enable dnsmasq ``` 在 Ubuntu 上进行验证: ```bash dig @127.0.0.1 foo.dev.test +short # 应返回 192.168.123.200 ``` 如果你曾经在 `/etc/hosts` 中绑定过相关测试域名,记得删除对应记录,否则 hosts 的优先级会让你误判问题来源。 ### 在 macOS 上为这个“开发后缀”做 DNS 分流 在 macOS 中创建 resolver 配置文件: ```bash sudo mkdir -p /etc/resolver sudo tee /etc/resolver/dev.test >/dev/null <<'EOF' nameserver 192.168.123.200 port 53 EOF ``` 刷新系统 DNS 缓存: ```bash sudo dscacheutil -flushcache sudo killall -HUP mDNSResponder ``` 接下来进行验证。这里有一个容易踩坑的细节: 在 macOS 上,`dig` 往往不会完全遵循系统 resolver 的分流逻辑,所以用 `dig foo.dev.test` 可能会得到“看起来不对”的结果。更可靠的验证方式是让系统 resolver 亲自参与解析,例如用 `ping` 或 `dscacheutil`: ```bash ping -c 1 foo.dev.test ``` 如果分流生效,你会看到它解析到 `192.168.123.200`: 能够看到 DNS 记录已经正确了。 ```text PING foo.dev.test (192.168.123.200): 56 data bytes 64 bytes from 192.168.123.200: icmp_seq=0 ttl=64 time=1.391 ms ``` 也可以用 `dscacheutil`: ```bash dscacheutil -q host -a name foo.dev.test ``` 想确认系统侧到底加载了哪些 DNS 规则,可以用: ```bash scutil --dns ``` 如果你确实想用 `dig`,建议显式指定 DNS 服务器,这样你测到的是 Ubuntu DNS 的回答,而不是 macOS 默认 resolver 的选择: ```bash dig @192.168.123.200 foo.dev.test +short # 应返回 192.168.123.200 ``` 到这里,Split DNS 的核心配置就完成了。 ## 常见问题与排错 这套方案很稳定,但排错时最好遵循一个顺序:先确认 Ubuntu 是否答对,再确认 macOS 是否问对。 ### 先确认 Ubuntu 是否答对 无论 macOS 侧发生什么,先直接问 Ubuntu: ```bash dig @192.168.123.200 foo.dev.test +short ``` - 如果这里都不对,优先查 Ubuntu 的 DNS 服务配置、监听地址、端口与防火墙 - 如果这里正确,再看 macOS 侧的分流是否生效 ### 再确认 macOS 是否问对 macOS 侧优先使用系统解析器验证: ```bash dscacheutil -q host -a name foo.dev.test ``` 如果你看到解析结果正确,但浏览器访问仍然不对,通常是浏览器启用了 DoH 之类的“安全 DNS”绕过了系统 resolver。这个时候你需要在浏览器中关闭或改为使用系统解析器。 ### 为什么有的子域名正常有的域名不正常 最常见的原因是“更精确的记录优先级更高”。一个典型例子是: - 通配规则把 `*.dev.test` 指到 `192.168.123.200` - 但你可能曾经在 `/etc/hosts` 或 DNS 配置里为某个特定域名写过精确记录,例如把它指到了 `127.0.0.1` 这会导致: - `a.foo.dev.test` 走通配规则正常 - `foo.dev.test` 因为精确记录被抢先命中,解析到你意料之外的地址 排查这种问题最简单的方法仍然是直接问 Ubuntu DNS: ```bash dig @192.168.123.200 foo.dev.test +short dig @192.168.123.200 a.foo.dev.test +short ``` 如果 Ubuntu 自己答复的就是 `127.0.0.1`,那就说明问题在 Ubuntu 的 DNS 配置或 hosts,而不是 macOS。 ## 最后 把开发域名解析这件事从“每次临时改 hosts”升级成“声明式分流规则”,带来的收益很直接: - 配置一次长期可用 - 日常网络零干扰 - 开发服务迁移或增减域名几乎不再产生维护成本 - 排错路径清晰,系统边界明确 如果你也在使用两台设备协同开发,无论是雷电网桥、同一热点还是家庭局域网,只要网络可达,就可以用同样的思路把体验做得更顺滑。 --EOF