SmartDNS 是一个功能丰富的本地 DNS 服务器,具体支持的特性可以看一下他们的官方网站,支持 Linux 和 Windows 平台。
虽然 RouterOS 是不能直接运行 Linux 软件的,但是从 RouterOS 7.4beta4 开始,MikroTik 针对部分比较现代的架构(arm, arm64, x86)增加了容器(Container)的支持,通过这个机制我们可以比较高效的直接在 RouterOS 设备上运行一些 Linux 应用,例如我们这边将要演示的 SmartDNS。
开启容器支持
出于安全因素考虑,RouterOS 并没有默认开启容器的支持,我们需要用以下命令开启:
|
|
完成后输出会提醒用户去重启设备,以 CCR2004
为例,就去按一下设备上的 reset 键即可。对于 CHR,进行一次冷重启也能达到相同的效果。重启完成后,可以使用命令 /container/print
来查看是否有已经开启容器功能。
准备网络接口
RouterOS 官方的文档中使用了 veth
为容器提供网络接入。如果之前用过 Linux 的 netns(network namespace)相关的功能对 veth 这个概念肯定有所了解,如果没有用过也不用担心。Linux 官方的手册中如此描述:
The veth devices are virtual Ethernet devices. They can act as tunnels between network namespaces to create a bridge to a physical network device in another namespace, but can also be used as standalone network devices.
所以我们可以简单粗暴的把 veth 理解为一组直接用网线相连的网卡,一头“插在”设备上,另一头“插在”容器,或是另一个 netns 中,也就是一个设备上的虚拟 L2 点对点连接。
RouterOS 和 Linux 的 netns 并无区别(毕竟 RouterOS 的的确确使用了 Linux 内核),只不过创建和使用的流程有一些小区别。使用如下命令创建一个 veth 接口:
|
|
其中,address 是容器中接口的 IP 地址,gateway 则是容器的默认路由,也就是我们 RouterOS 本身的 IP 地址。
因为我希望我局域网内的设备可以直接访问 smartdns,所以我们可以直接将 ether-pihole
加入 LAN 的 bridge 中,就不需要任何端口转发之类的额外操作了:
|
|
这样我们的容器就和我们的局域网处在同一个二层网络中了。
创建容器和配置服务
为了避免容器内应用日志和拉取镜像时产生的写入对路由器的 nand 造成太多的负担,可以创建一个内存盘用来存放这些文件:
|
|
同时,为了方便后续对网络进行一些自定义的调整,我不打算直接用网上现成的 dockerfile
来创建我们的 SmartDNS 容器,而是直接使用 alpine:latest
为基础镜像,直接进入这个容器内下载 SmartDNS:
|
|
这里写的 cmd 随便准备的一个可以执行很久,不会主动退出的命令,这样我们就有充足的时间来完成容器的配置。执行创建命令后可以用 /container/print
观察状态,完成之后可以使用 /container/start 0
来启动容器。
|
|
到这里我们就能和像在普通的 Linux 环境一样下载和安装 SmartDNS 了:
|
|
具体的配置细节这里就不细说了,大家可以查看官方的文档。配置完成后可以在容器中直接启动 smartdns 来验证配置是否正确,一切正常之后,我们可以准备开始创建我们的启动脚本了。因为我的容器直接暴露在家庭局域网的 L2 内,所以我希望直接对容器增加 IPv6 地址,好在 SLAAC 和 DHCPv4 中直接分发容器的 IPv4/v6 配置。我的方案很粗暴,直接准备一个 /start.sh
文件用来完成相关的配置:
|
|
然后更新一下容器配置,并重启容器即可:
|
|
最后,我们可以找一个别的设备来验证一下 DNS 服务:
|
|
实际上,通过类似的方法我们几乎可以运行任何 Linux 应用来拓展 RouterOS 的功能,例如 BIND 或者是 pi-hole 等等。