部署DNSmasq

安装dnsmasq

  • 各发行版都包含了dnsmasq,安装十分方便便捷:

Arch Linux 安装dnsmasq:

pacman -S dnsmasq

Ubuntu Linux 安装dnsmasq:

apt install dnsmasq

RedHat Linux 安装dnsmasq (fedora或centos/rhel 8):

dnf install dnsmasq

配置dnsmasq

  • 检查配置语法,这个基本步骤可以确保配置没有基础的语法错误:

    dnsmasq --test
    
  • 现代发行版,在 /etc/default/dnsmasq 提供了对dnsmasq服务对基本控制,例如:

    • 启用或关闭dnsmasq: ENABLED=1 (关闭是设置 0)

    • 设置DNS后缀(默认域名): DOMAIN_SUFFIX=`dnsdomainname

    • 选择一个替代配置文件: DNSMASQ_OPTS="--conf-file=/etc/dnsmasq.alt"

    • 告知dnsmasq读取配置文件目录: CONFIG_DIR=/etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new (默认启用,配置集中在 /etc/dnsmasq.d )

    • 如果系统安装了 resolvconf 软件包,dnsmasq就会使用 resolvconf 的输出而不是 /etc/resolv.conf 配置来 查找 upstream nameservers 。如果要关闭这个特性,就激活 IGNORE_RESOLVCONF=yes

  • 在我的 zcloud 服务器上,安装了多个网卡,其中内网采用有线网络,网段是 192.168.6.x ,所以需要设置dnsmasq监听特定地址,只监听内部网络网段和回环地址:

    listen-address=192.168.6.200,127.0.0.1
    

注解

Libvirt虚拟机管理器 已经启动了 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf ... 专用于 virbr0 (NAT网络)的服务,提供KVM虚拟机的DHCP IP分配。这个dnsmasq是专门监听 interface=virbr0 ,和本文配置不冲突

也可以通过设置监听接口来确保限制在指定网口上:

interface=enp0s25,anbox0

或者仅指定不包括哪些接口 except-interface=

注解

我这里采用 listen-address=192.168.6.200,127.0.0.1 是因为我这个服务将针对整个 私有云架构 ,并且我会在多个接口上使用这个网段的IP

  • 设置缓存大小:通常dnsmasq是作为本地局域网的DNS缓存服务器运行,并且默认只缓存150条DNS记录,可以将这个缓存扩大:

    cache-size=1000
    

DNS地址文件和转发

在配置了dnsmasq之后,你需要添加一个localhost地址到 /etc/resolv.conf ,这样本机的DNS请求才会发送被本机运行的dnsmasq。

由于dnsmasq是一个stub解析器(resolver)但不是一个recusive解析器,所以你必须设置一个转发解析到外部DNS服务器。这个设置可以使用 openresolv 自动实现(也可以在dnsmasq的配置文件中手工设置,但我们通常都使用openresolv)。

  • resolvconf

  • systemd-resolved 是目前主流操作系统默认配置,例如我在 zcloud 上部署的 Ubuntu Linux 服务器版本就采用 systemd-resolved

openresolv

如果你的network manager支持 resolvconf ,就不需要直接修改 /etc/resolv.conf ,可以使用 openresolv 来为dnsmasq生成配置文件。

注解

注意, resolvconf 的基础配置 DOMAINNAME 是从 NetworkManager 获取的,会影响下面所有的 domain 配置。所以如果要修订域名搜索,需要修改Network Manager的配置。这块我还没有实践,待后续补充

  • 编辑 /etc/resolvconf.conf 添加一个回环地址作为域名解析服务器,并配置 openresolv 来输出dnsmasq配置:

    resolv_conf=/etc/resolv.conf
    # If you run a local name server, you should uncomment the below line and
    # configure your subscribers configuration files below.
    name_servers=127.0.0.1
    
    # Write out dnsmasq extended configuration and resolv files
    dnsmasq_conf=/etc/dnsmasq-conf.conf
    dnsmasq_resolv=/etc/dnsmasq-resolv.conf
    
  • 执行 resolvconf -u 命令生成上述配置文件。注意,如果没有上述文件存在, dnsmasq.service 启动会失败。

请注意,此时原先 /etc/resolv.conf 配置文件会修订成使用本机dns:

# Generated by resolvconf
domain staging.huatai.me
nameserver 127.0.0.1

/etc/dnsmasq-resolv.conf 配置则是之前 resolv.conf 内容,也就是说DNSmasq会使用这个 dnsmasq-resolv.conf 来请求外部DNS服务器:

# Generated by resolvconf
nameserver 202.96.209.133  # 注意:之后这个外部DNS将修改成我部署的bind服务器IP

/etc/dnsmasq-conf.conf 配置是dnsmasq的配置:

# Generated by resolvconf
server=/staging.huatai.me/202.96.209.133

Manual forwarding

  • 首先需要确保 /etc/resolv.conf 配置中只设置 localhost 作为唯一的nameserver:

    # Generated by resolvconf
    domain staging.huatai.me
    nameserver 127.0.0.1
    # 如果是IPv6还需要如下行
    # nameserver ::1
    
  • /etc/dnsmasq.conf 配置 server=server_address 指定上级DNS,并且添加 no-resolv 这样dnsmasq就不会读取 /etc/resolv.conf ,因为这个配置中实际只包含了它自己的localhost地址:

    ...
    no-resolv
    ...
    # Google's nameservers, for example
    server=8.8.8.8
    server=8.8.4.4
    

注解

一定要配置 server= ,将所有非本地域名的DNS解析都通过上一级DNS来提供

添加定制域名

可以为本地局域网添加一个domain,也就是我们内部域名:

local=/staging.huatai.me/
domain=staging.huatai.me
expand-hosts

完整 /etc/dnsmasq.conf 配置:

dnsmasq简易配置
 1# 本地默认域名
 2local=/staging.huatai.me/
 3# 转发上游域名解析服务器,请求DNS解析
 4server=8.8.8.8
 5# 监听DNS请求的网卡接口
 6listen-address=192.168.6.200,127.0.0.1
 7# 扩展主机域名,也就是请求 zcloud 默认扩展成 zcloud.staging.huatai.me
 8expand-hosts
 9# 服务器提供解析的域名
10domain=staging.huatai.me
11# DNS解析缓存
12cache-size=1000
13# DHCP
14dhcp-range=192.168.6.21,192.168.6.50,255.255.255.0,12h
15dhcp-option=option:router,192.168.6.200
16dhcp-option=option:dns-server,192.168.6.200
17dhcp-authoritative

上述域名就是我们用于DHCP和内部域名,这样我们在 /etc/hosts 中配置主机名解析时候就只需要配置短域名主机名就可以了,会自动扩展成FQDN完整域名。例如, /etc/hosts 配置:

192.168.6.9  zcloud
192.168.6.10 jetson
192.168.6.11 pi-master1
192.168.6.12 pi-master2
192.168.6.13 pi-master3
192.168.6.15 pi-worker1
192.168.6.16 pi-worker2
192.168.6.17 pi-worker3

则自动会被加上 .staging.huatai.me 后缀域名,形成完成的域名 192.168.6.9 zcloud.staging.huatai.me

启动DNSmasq

  • 启动dnsmasq:

    systemctl start dnsmasq
    
  • 查询测试:

    host zcloud
    

可以看到输出的域名解析被自动展开:

zcloud.staging.huatai.me has address 192.168.6.9

DHCP服务器(推荐配置)

我在 私有云架构 采用的DNSmasq实现DNS解析,以及对局域网内部提供DHCP,提供 结合DNSmasq+iptables使用AirPort Express实现无线访问因特网 ,配置添加:

dhcp-range=192.168.6.21,192.168.6.50,255.255.255.0,12h
dhcp-option=option:router,192.168.6.200
dhcp-option=option:ntp-server,192.168.6.200
dhcp-option=option:dns-server,192.168.6.200
dhcp-authoritative

解析配置:

  • dhcp-range 设置了分配IP地址范围,注意,配置中结合了上文DNS配置,上文中已经配置 listen-address=192.168.6.200,127.0.0.1 ,也就是只监听局域网内部IP以及回环地址,所以不会和无线网络(另一个DHCP)冲突

  • dhcp-option 提供了DHCP的选项:

    • dhcp-option=option:router,192.168.6.200 指定DHCP客户端的默认路由

    • dhcp-option=option:ntp-server,192.168.6.200 指定DHCP客户端的NTP服务器

    • dhcp-option=option:dns-server,192.168.6.200 指定DHCP客户端的DNS服务器

    • dhcp-authoritative

DHCP服务器(anbox案例)

默认情况下,dnsmasq是关闭DHCP功能的,需要在配置中开启才可以使用dhcp。

注解

如果你的局域网内部已经使用了DHCP服务,例如宽带路由器对局域网就默认启用了DHCP。所以,一定要避免DHCP冲突,需要小心设置dnsmasq所使用对接口(参数 interface= )

在我的案例中,我启用了多个接口的DNS服务 ( enp0s25,anbox0 ) 但是只在内网接口 enp0s25 启用DHCP服务。

  • 重要配置案例:

    # If you want dnsmasq to listen for DHCP and DNS requests only on
    # specified interfaces (and the loopback) give the name of the
    # interface (eg eth0) here.
    # Repeat the line for more than one interface.
    interface=enp0s25,anbox0
    
    # If you want dnsmasq to provide only DNS service on an interface,
    # configure it as shown above, and then use the following line to
    # disable DHCP and TFTP on it.
    no-dhcp-interface=anbox0
    
    # On systems which support it, dnsmasq binds the wildcard address,
    # even when it is listening on only some interfaces. It then discards
    # requests that it shouldn't reply to. This has the advantage of
    # working even when interfaces come and go and change address. If you
    # want dnsmasq to really bind only the interfaces it is listening on,
    # uncomment this option. About the only time you may need this is when
    # running another nameserver on the same machine.
    bind-interfaces
    
    # Uncomment this to enable the integrated DHCP server, you need
    # to supply the range of addresses available for lease and optionally
    # a lease time. If you have more than one network, you will need to
    # repeat this for each network on which you want to supply DHCP
    # service.
    # This is an example of a DHCP range where the netmask is given.
    dhcp-range=192.168.6.201,192.168.6.254,255.255.255.0,12h
    
    # 也支持根据以太网MAC地址来分配IP地址,适合需要固定IP地址分配场景
    # 在企业内部网络,可以通过这种方式来。
    # 以下为举例(设置主机名以及对应IP地址,并且45分钟释放):
    # dhcp-host=11:22:33:44:55:66,fred,192.168.6.254,45m
    
    # DHCP有很多重要选项,以下是一些常用案例:
    
    # 设置默认网关,以下2种配置都可以,任选一种
    #dhcp-option=3,192.168.6.9
    dhcp-option=option:router,192.168.6.9
    
    # 设置NTP服务器地址:
    #dhcp-option=option:ntp-server,192.168.6.9
    
    # 可以通过DHCP设置静态路由,注意要配置网络netmask
    #dhcp-option=121,192.168.7.0/24,192.168.6.10,10.0.0.0/8,192.168.6.8
    
    # 设置DNS服务器(待验证,配置文件只显示DHCPv6的dns-server)
    dhcp-option=option:dns-server,192.168.6.9
    

完整的配置需要查看 dnsmasq.conf 配置注释,后面我会在部署 Raspberry Pi Cluster 的diskless集群尝试实践。

  • 启动dnsmasq之后,要观察有哪些DHCP地址被分配出去,请检查 /var/lib/misc/dnsmasq.leases

  • 启动dnsmasq之后,请检查 systemctl status dnsmasq 输出,正常情况下显示类似:

    ● dnsmasq.service - dnsmasq - A lightweight DHCP and caching DNS server
         Loaded: loaded (/usr/lib/systemd/system/dnsmasq.service; enabled; vendor preset: disabled)
         Active: active (running) since Thu 2020-10-08 22:23:52 CST; 14min ago
           Docs: man:dnsmasq(8)
        Process: 36760 ExecStartPre=/usr/bin/dnsmasq --staging.(code=exited, status=0/SUCCESS)
       Main PID: 36761 (dnsmasq)
          Tasks: 1 (limit: 19050)
         Memory: 1.3M
         CGroup: /system.slice/dnsmasq.service
                 └─36761 /usr/bin/dnsmasq -k --enable-dbus --user=dnsmasq --pid-file
    
    Oct 08 22:23:52 zcloud dnsmasq[36760]: dnsmasq: syntax check OK.
    Oct 08 22:23:52 zcloud systemd[1]: Started dnsmasq - A lightweight DHCP and caching DNS server.
    Oct 08 22:23:52 zcloud dnsmasq[36761]: started, version 2.82 cachesize 1000
    Oct 08 22:23:52 zcloud dnsmasq[36761]: compile time options: IPv6 GNU-getopt DBus no-UBus i18n IDN2 DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop->
    Oct 08 22:23:52 zcloud dnsmasq[36761]: DBus support enabled: connected to system bus
    Oct 08 22:23:52 zcloud dnsmasq-dhcp[36761]: DHCP, IP range 192.168.6.201 -- 192.168.6.254, lease time 12h
    Oct 08 22:23:52 zcloud dnsmasq-dhcp[36761]: DHCP, sockets bound exclusively to interface enp0s25
    Oct 08 22:23:52 zcloud dnsmasq[36761]: using only locally-known addresses for domain staging.huatai.me
    Oct 08 22:23:52 zcloud dnsmasq[36761]: using nameserver 202.96.209.133#53
    Oct 08 22:23:52 zcloud dnsmasq[36761]: read /etc/hosts - 12 addresses
    

请注意,这里输出的信息都反映了我们上述配置中的设置参数

TFTP服务器

dnsmasq内建了TFTP服务器。也准备在 Raspberry Pi Cluster 的diskless集群实践。

参考