本篇文章,我将介绍一个方便本地开发和调试的方案,本地 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 端口,就能看到控制面板了,开始使用啦。
需要额外注意的是,为了减少后续设置的复杂,我们默认使用 53 端口来提供服务,管理面板默认使用的端口是 8080,如果你有端口冲突,建议进行调整或修改。
【图片】
界面比较简单,这里就不过赘述了,编辑器支持使用快捷键(CMD+/
)切换注释,所以,如果在配置存放一些不同环境的配置,通过快捷键就能进行批量快速切换啦,最近半年,我是这么解决不同环境的 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”即可。
【图片】
这里有一个小技巧,为了保证网络完全不间断(比如重启服务的时候),这里可以除了添加我们指定的 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
方案二:使用 go-dnsmasq 方案
go-dnsmasq 是一个轻量到只有 1.2MB 的DNS缓存/转发工具,但是可惜的是作者在 16 年之后就没有在继续维护项目,在翻阅了几十个 fork 衍生版之后,我最终将两个国外的改进版本合并成了一个新的版本 https://github.com/soulteary/go-dnsmasq,并制作了一个 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 挂载的时候切换文件就可以啦。
如何结合系统使用本地 DNS 服务器,上文有提过,这里不再赘述。接着来聊聊文章开头聊到的编辑本地 Hosts 文件。
其他:如何简单的修改 Hosts 文件
如果你只需要管理几个域名,也不太想启动一个服务(哪怕它只有2M),可以尝试编辑系统的 Hosts
文件来完成域名指向,如果你厌倦了命令行或者记事本修改文件,也可以考虑下载一些 Hosts Editor 类的工具。
最初的时候,我使用过 Gas Mask、HostsMan,以及一些类似的软件,在第一次去淘宝工作的时候,被安利了一个内网神器“iHosts”(不是搜索引擎搜索出的同名软件),除了多了清新的界面之外,还支持记录分组,以及本地 DNS 服务器,对于调试移动端场景、或者虚拟机场景还是挺方便的。
在许多年前离开淘宝后,因为无法再从内网下载“ihosts”,于是就切换到了 “SwitchHosts!”(最新版本改名字去掉了“!”),虽然没有内置 DNS 服务、请求日志等功能,但是胜在功能简单够用,加上作者靠谱,也就一直用了下来。
为什么说作者靠谱呢?早些时候和刚从淘宝离开的季札大神一起吃饭,聊起招聘困难,当时玩笑的说要不要在 SwitchHosts README 里加个招聘广告,季札大神说希望这个软件能够一直纯粹下去,然后这些年这个软件,至今为止就一直这么干净纯粹着,还是挺难得的。
但是,在使用过程中难免会遇到需要做“泛解析”的场景,批量改动记录总归是比较麻烦的事情,以及我的电脑常年不关机,经常休眠唤醒,基于 Electron 的 SwitchHosts 总是会出现内存溢出的问题,所以只好忍痛把主力方案切换到了上文中的 DNS 方式。其实解决的方案也很简单,就是每次使用完 SwitchHosts 之后,把它的进程彻底关掉。
后续我应该会继续使用 SwitchHosts 这个功能,不过不会再作为主力工具。
最后
原本以为离职休假能够把草稿箱里的文章清理一下,没想到积累的草稿更多了。
–EOF