用于本地开发使用的 DNS 方案

1,041 阅读9分钟

本篇文章,我将介绍一个方便本地开发和调试的方案,本地 DNS 代理服务器。

写在前面

不论是你做前端还是后端开发,本地调试带有域名的接口或页面是大概率绕不开的事情。甚至,如果你使用了自签名证书或者使用了“虚拟域名”进行 HomeLab 服务搭建,在某些不能使用网络默认 DNS 服务器时,也需要一些“灵活”的方案来动态切换一系列域名的指向。

不过,也不能因为手持锤子就看哪里都是钉子。简单的场景下,比如就修改一次的情况下,直接修改 hosts 文件解决问题会是更简单的方案,关于 “Hosts Editor” 类的工具的推荐,可以阅读文末章节。

言归正传,先来聊一个我使用了六个多月的方案。

方案一:带有界面的 dnsmasq 容器

dnsmasq 作为 DNS Server 被广泛用于 Linux 发行版。我们常见的 Ubuntu Server 版以及 Open WRT 路由器固件中,不少版本默认使用的都是它。

但是它是一个命令行软件,默认并不支持自动重载有修改后的配置文件,配置文件的编辑和我们常规修改 /etc/hosts 别无二致,国外有一个工程师为了解决这个问题,开发了一个简单的带有界面的配置工具 docker-dnsmasq,在配置文件被修改后,能够发送命令重启或重载 dnsmasq 主程序,达到“方便使用”的目的。

因为作者许久不更新软件,在今年二月的时候,我做了一个 fork 版本,soulteary/docker-dnsmasq,你可以使用下面的配置快速运行一个属于你的本地 DNS 服务器。

以往我们编辑 hosts 文件,会用下面的形式来进行域名绑定:

10.11.12.123 docker.lab.com
10.11.12.123 maven.lab.com
10.11.12.123 npm.lab.com
10.11.12.123 pypi.lab.com
...

所以当域名很多的时候,使用起来就会非常麻烦,相比之下 dnsmasq 的配置文件就会简单许多,因为它允许使用“泛解析”的方式,除此之外还能指定上游服务器,近一步扩展能力,下面就是一个 dnsmasq.conf 的配置文件的例子:

# HomeLab
## Use Home DNS Upstream
server=10.11.12.13

# HomeLab Domain Example:
address=/.lab.com/10.11.12.123
address=/*.lab.com/10.11.12.123
address=/*.demo.lab.com/10.11.12.123
address=/*.api.lab.com/10.11.12.123
address=/*.some.api.lab.com/10.11.12.123

# localhost
address=/.lab.io/127.0.0.1
address=/*.lab.io/127.0.0.1

在上面的例子中,将 lab.com 和一些子域名指向了内网的一台机器,而将 lab.io 全部指向了本机,将上面的内容保存为 dnsmasq.conf,我们来编写容器编排文件:

version: "3"
services:

  dns:
    image: soulteary/docker-dnsmasq
    restart: always
    # 如果你需要一个简单的 Basic Auth 认证
    #environment:
    #  - HTTP_USER=user
    #  - HTTP_PASS=pass
    ports:
      - "53:53/udp"
      - "53:53/tcp"
      - "8080:8080"
    volumes:
      - ./dnsmasq.conf:/etc/dnsmasq.conf:rw

将上面的内容保存为 docker-compose.yml,然后使用 docker-compose up -d 启动服务,接着使用浏览器访问 8080 端口,就能看到控制面板了,开始使用啦。

一个简单的 dnsmasq 管理面板

需要额外注意的是,为了减少后续设置的复杂,我们默认使用 53 端口来提供服务,管理面板默认使用的端口是 8080,如果你有端口冲突,建议进行调整或修改。

软件界面比较简单,使用方式就是使用所见即所得的编辑器修改内容,然后点击保存等待配置生效。如果你在配置存放一些不同环境的配置,然后批量选中某个环境的记录,通过快捷键(CMD+/)切换记录的注释状态,就能进行不同环境 DNS 记录的快速切换了。(最近半年里,我就是这么解决不同环境的 DNS 记录切换的,配置示例):

# HomeLab
## Use Home DNS
server=10.11.12.13

# Office
## Use Dev NS Servers
# server=219.141.136.10
# server=219.141.140.10

## Use CloudFlare NS Servers
# server=1.0.0.1
# server=1.1.1.1


# Local
address=/.lab.io/127.0.0.1
address=/*.lab.io/127.0.0.1

address=/.lab.com/10.11.12.123
address=/*.lab.com/10.11.12.123
address=/*.demo.lab.com/10.11.12.123
address=/*.api.lab.com/10.11.12.123
address=/*.some.api.lab.com/10.11.12.123

# address=/.lab.com/192.11.12.123
# address=/*.lab.com/192.11.12.123
# address=/*.demo.lab.com/192.11.12.123
# address=/*.api.lab.com/192.11.12.123
# address=/*.some.api.lab.com/192.11.12.123

当然,这个程序同时会读取容器内的 /etc/hosts,你也可以通过左侧侧边栏切换编辑器打开 hosts 文件,用传统的方式添加修改 DNS 记录。

在软件使用过程中,也会有一些体验不好的地方,比如程序重载需要几秒的时间,过程中会有服务不可用的状态,编辑器只有最基础的功能,缺少快捷键等。

偶尔有的时候程序会出现一些异常的资源使用,经过查找,发现社区里也有人反馈,虽说重启一下容器就能解决问题,但是毕竟有瑕疵,所以我开始考虑对这个方案进行替换调整。

结合系统使用

当我们启动了本地服务之后,默认请求并不会有任何改变,除非我们将这个配置应用到系统网络配置中。

以 macOS 为例,打开网络设置,选择当前网络,点击“高级”按钮,然后切换到 DNS 选项卡,在左侧的 DNS 服务器里,添加 “127.0.0.1”即可。

调整 macOS 的网络DNS配置

这里有一个小技巧,为了保证网络完全不间断(比如重启服务的时候),这里可以除了添加我们指定的 DNS 服务之外,将当前网络的 DNS 服务器也添加进去。

配合Traefik 使用 dnsmasq

如果你是我的老读者,那么应该对 Traefik 不会感到陌生,这里提供一个简单的配置,方便你使用 Traefik:

version: "3"
services:

  dns:
    image: soulteary/docker-dnsmasq
    restart: always
	# 如果你需要一个简单的 Basic Auth 认证
    # 使用 Traefik 推荐使用 Forward Auth 进行取代
    #environment:
    #  - HTTP_USER=user
    #  - HTTP_PASS=pass
    ports:
      - "53:53/udp"
      - "53:53/tcp"
      - "8080:8080"
    volumes:
      - ./dnsmasq.conf:/etc/dnsmasq.conf:rw
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik"
      - "traefik.http.routers.dnsmasq-web.entrypoints=http"
      - "traefik.http.routers.dnsmasq-web.rule=Host(`dns.lab.io`)"
      - "traefik.http.routers.dnsmasq-ssl.entrypoints=https"
      - "traefik.http.routers.dnsmasq-ssl.tls=true"
      - "traefik.http.routers.dnsmasq-ssl.rule=Host(`dns.lab.io`)"
      - "traefik.http.services.dnsmasq-backend.loadbalancer.server.scheme=http"
      - "traefik.http.services.dnsmasq-backend.loadbalancer.server.port=8080"
    networks:
      - traefik

networks:
  traefik:
    external: true

关于 “Traefik 鉴权”话题,之前有提到过,感兴趣可以自取(上篇/下篇),另外,最近有做一个小项目,可以进一步简化这个场景的操作。

接下来,来聊聊新的方案。

方案二:使用 go-dnsmasq 方案

go-dnsmasq 是一个轻量到只有 1.2MB 的 DNS 缓存/转发工具,但是可惜的是作者在 16 年之后就没有继续进行项目维护了。在翻阅了几十个 fork 衍生版之后,我最终将两个国外的改进版本合并成了一个新的版本 github.com/soulteary/g…,并制作了一个 2.7 MB 左右的容器镜像。

使用方法其实比上面还要简单,先来看配置文件:

127.0.0.1 lab.com
127.0.0.2 *.lab.com

平凡无奇的 hosts 记录的语法中,支持了泛解析,比 dnsmasq.conf 少了不少符号记忆的负担。虽然日常使用肯定会使用复制粘贴,但是少一个字符,出错的可能就少了一分,不是吗?将上面的内容保存为 hosts.conf,稍后使用。

先来继续编写容器配置文件:

version: "3"
services:

  dns:
    image: soulteary/go-dnsmasq
    command: dnsmasq -l 0.0.0.0:53 -f /hosts.conf -p 1s --nameservers 10.11.12.13:53
    restart: always
    ports:
      - "53:53/udp"
      - "53:53/tcp"
    volumes:
      - ./hosts.conf:/hosts.conf:rw

相比较方案一,这个方案显然更“轻量环保”。至于切换环境配置,只需要准备多份不同环境的配置文件,使用 docker 挂载的时候切换文件就可以啦。

配置中的启动命令中,我定义了几个参数,只需要关注最后一个参数即可:

dnsmasq -l 0.0.0.0:53 -f /hosts.conf -p 1s --nameservers 10.11.12.13:53

参数中的 --nameservers 需要设定为你的网络环境中的默认 DNS,当然如果你参考上文中提到的“结合系统使用”的方式,不进行指定也不会影响使用。

接着,来聊聊文章开头聊到的编辑本地 Hosts 文件。

其他:如何简单的修改 Hosts 文件

如果你只需要管理几个域名,也不太想启动一个服务(哪怕它只有2M),可以尝试编辑系统的 Hosts 文件来完成域名指向,如果你厌倦了命令行或者记事本修改文件,也可以考虑下载一些 Hosts Editor 类的工具。

最初的时候,我使用过 Gas MaskHostsMan,以及一些类似的软件,在第一次去淘宝工作的时候,被安利了一个内网神器“iHosts”(不是搜索引擎搜索出的同名软件),除了多了清新的界面之外,还支持记录分组,以及本地 DNS 服务器,对于调试移动端场景、或者虚拟机场景还是挺方便的。

Switch Hosts 默认界面

在许多年前离开淘宝后,因为无法再从内网下载“ihosts”,于是就切换到了 “SwitchHosts!”(最新版本改名字去掉了“!”),虽然没有内置 DNS 服务、请求日志等功能,但是胜在功能简单够用,加上作者靠谱,也就一直用了下来。

为什么说作者靠谱呢?早些时候和刚从淘宝离开的作者季札大神一起吃饭,聊起招聘困难,当时玩笑的说要不要在 SwitchHosts README 里加个招聘广告,季札说希望这个软件能够一直纯粹下去,然后这些年这个软件,至今为止就一直这么干净纯粹着,还是挺难得的。

但是,在使用过程中难免会遇到需要做“泛解析”的场景,批量改动记录总归是比较麻烦的事情,以及我的电脑常年不关机,经常休眠唤醒,基于 Electron 的 SwitchHosts 经常会出现内存溢出的问题,所以只好忍痛把主力方案切换到了上文中的 DNS 方式。

其实解决的方案也很简单,和方案一一样,就是每次使用完 SwitchHosts 之后,把它的进程彻底关掉,再重启就好了。后续我应该会继续使用 SwitchHosts 这个功能,不过,应该不会再作为主力工具,毕竟泛解析能够省不少事儿。

其他:如何制作和使用自签名证书

HTTPS 时代中,本地调试有的时候也躲不开配置证书,关于如何方便的制作和使用自签名证书,我曾写过一篇文章进行介绍,如果你有这方面的需求,可以自行取用。

最后

原本以为离职休假能够把草稿箱里的文章清理一下,没想到积累的草稿更多了,感谢令人头疼的好奇心,和追求最优解的倔强。

--EOF


如果你觉得内容还算实用,欢迎点赞分享给你的朋友,在此谢过。


我们有一个小小的折腾群,里面聚集了几百位喜欢折腾的小伙伴。

在不发广告的情况下,我们在里面会一起聊聊软硬件、HomeLab、编程上的一些问题,也会在群里不定期的分享一些技术沙龙的资料。

喜欢折腾的小伙伴欢迎扫码添加好友。(添加好友,请备注实名,注明来源和目的,否则不会通过审核)

关于折腾群入群的那些事


本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

本文作者: 苏洋

创建时间: 2021年08月19日 统计字数: 6401字 阅读时间: 13分钟阅读 本文链接: soulteary.com/2021/08/19/…