私有云DNS服务(dnsmasq)和共享因特网(ICS)

在少量部署的虚拟机环境中,通过简单维护各个主机 /etc/hosts 一致,就能够实现主机解析。但是,一旦开始大规模通过 Clone使用Ceph RBD的虚拟机 私有云基于 ZData Ceph 运行虚拟机 ,就很难实时更新每个虚拟机的 hosts 配置文件。更何况后续还会 私有云架构 构建 KVM嵌套虚拟化 ,构建数以百计的虚拟机。所以,我们需要构建一个因特网非常基础的 DNS服务 ,来提供整个基础架构的域名解析。

当然,大规模基础架构,我们会选择久经考验坚如磐石的 BIND (然而非常复杂),但是为了快速搭建 staging 环境,我首先选择 DNSmasq 来完成原型,待后续不断优化后再升级到 Bind 构建真正的因特网基础设施。

dnsmasq是小型网络的轻量级DNS/TFTP和DHCP服务器,特别适合小型网络的快速构建,以及宽带共享路由器的局域网基础服务。

安装

  • ubuntu安装:

    sudo apt install dnsmasq
    

配置dnsmasq

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

上述配置:

  • 执行一个简单的脚本,生成 /etc/hosts ,这个配置将被 dnsmasq 加载作为域名解析配置:
hosts配置提供dnsmasq域名解析配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/env bash

. /etc/profile

hosts_csv=/home/huatai/github.com/cloud-atlas/source/real/private_cloud/priv_cloud_infra/hosts.csv

function init {
    cat /home/huatai/github.com/cloud-atlas/source/real/private_cloud/priv_cloud_infra/hosts.csv | grep -v "主机" | awk -F, '{print $2"  "$3}' > /tmp/hosts
}

function cp_hosts {
    sudo cp /tmp/hosts /etc/hosts
}

function restart_dnsmasq {
    sudo systemctl restart dnsmasq
}

init
cp_hosts
restart_dnsmasq

执行该脚本,根据 私有云架构 规划的主机列表生成 /etc/hosts 文件:

./deploy_dnsmasq.sh
netplan 802.1x配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
network:
  version: 2
  renderer: networkd
  ethernets:
    eno4:
      dhcp4: yes
      dhcp6: no
      macaddress: xx:xx:xx:xx:xx:xx
      auth:
        key-management: 802.1x
        method: peap
        identity: "USERNAME"
        password: "PASSWD"

所以 netplan 会配置 systemd-resolved 服务使用DHCP获得的DNS服务器,我们需要覆盖这个配置,采用本地运行的 dnsmasq 来提供解析: 修订 /etc/systemd/resolved.conf

[Resolve]
DNS=127.0.0.1
Domains=staging.huatai.me

然后重启 systemd-resolved 服务:

sudo systemctl daemon-reload
sudo systemctl restart systemd-networkd
sudo systemctl restart systemd-resolved

(可选)命令行修订 systemd-resolv 配置:

sudo systemd-resolve --interface eno4 --set-dns 127.0.0.1 --set-domain staging.huatai.me

不过,我发现重启 systemd-resolved 服务后,上述配置是叠加在DHCP配置上的,检查 /run/systemd/resolve/resolv.conf 可以看到:

nameserver 127.0.0.1
nameserver 8.8.8.8
search staging.huatai.me office.com

但是, dig 命令查询是正常的, resolv.conf 配置的 nameserver 是始终访问第一个 nameserver 127.0.0.1 ,所以没有报错。(这和我很久以前学习 《DNS和Bind》 的记忆有差别,我记得是轮询所有 nameserver 的)

配置DNS客户端

所有VM都需要配置 systemd-resolved 采用 zcloud 上部署的DNS服务器(dnsmasq)

Ubuntu

修订VM以及模版VM /etc/netplan/01-netcfg.yaml

...
   nameservers:
       search: [ staging.huatai.me ]
       addresses:
           - "192.168.6.200"

然后执行:

sudo netplan apply

完成DNS解析器配置,采用 192.168.6.200 (zcloud) 的DNS进行域名解析。

Fedora

Fedora使用 NetworkManager 管理网络,使用以下命令修订DNS:

# nmcli可以直接修订配置
nmcli connection modify enp1s0 ipv4.dns "192.168.6.200" ipv4.dns-search "staging.huatai.me"
# 需要up刷新才能生效
nmcli connection up id "enp1s0"

上述命令会修订 /etc/NetworkManager/system-connections/enp1s0.nmconnection 对应配置

因特网共享连接

DNSmasq不仅提供了DNS解析,也同时为内部局域网提供了DHCP服务,以便 结合DNSmasq+iptables使用AirPort Express实现无线访问因特网 客户端能够访问Internet

  • zcloud 上执行 ics.sh 脚本为局域网内部主机提供共享因特网:
共享Internet
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# squid transparent proxy
sudo iptables -t nat -A PREROUTING -i br0 -p tcp --dport 80 -j DNAT --to 192.168.6.200:3128
sudo iptables -t nat -A PREROUTING -i br0:1 -p tcp --dport 80 -j DNAT --to 192.168.6.200:3128
sudo iptables -t nat -A PREROUTING -i eno4 -p tcp --dport 80 -j REDIRECT --to-port 3128

# masquerade 192.168.6.0/24 & 192.168.7.0/24
sudo iptables -A FORWARD -o eno4 -i br0 -s 192.168.6.0/24 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -o eno4 -i br0:1 -s 192.168.7.0/24 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -A POSTROUTING -o eno4 -j MASQUERADE
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"