私有云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# 本地默认域名
 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

上述配置:

  • 执行一个简单的脚本,生成 /etc/hosts ,这个配置将被 dnsmasq 加载作为域名解析配置:

hosts配置提供dnsmasq域名解析配置
 1#!/bin/env bash
 2
 3. /etc/profile
 4
 5hosts_csv=/home/huatai/github.com/cloud-atlas/source/real/private_cloud/priv_cloud_infra/hosts.csv
 6
 7function init {
 8    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
 9}
10
11function cp_hosts {
12    sudo cp /tmp/hosts /etc/hosts
13}
14
15function restart_dnsmasq {
16    sudo systemctl restart dnsmasq
17}
18
19init
20cp_hosts
21restart_dnsmasq

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

./deploy_dnsmasq.sh
netplan 802.1x配置
 1network:
 2  version: 2
 3  renderer: networkd
 4  ethernets:
 5    eno4:
 6      dhcp4: yes
 7      dhcp6: no
 8      macaddress: xx:xx:xx:xx:xx:xx
 9      auth:
10        key-management: 802.1x
11        method: peap
12        identity: "USERNAME"
13        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# squid transparent proxy
 2sudo iptables -t nat -A PREROUTING -i br0 -p tcp --dport 80 -j DNAT --to 192.168.6.200:3128
 3sudo iptables -t nat -A PREROUTING -i br0:1 -p tcp --dport 80 -j DNAT --to 192.168.6.200:3128
 4sudo iptables -t nat -A PREROUTING -i eno4 -p tcp --dport 80 -j REDIRECT --to-port 3128
 5
 6# masquerade 192.168.6.0/24 & 192.168.7.0/24
 7sudo iptables -A FORWARD -o eno4 -i br0 -s 192.168.6.0/24 -m conntrack --ctstate NEW -j ACCEPT
 8sudo iptables -A FORWARD -o eno4 -i br0:1 -s 192.168.7.0/24 -m conntrack --ctstate NEW -j ACCEPT
 9sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
10sudo iptables -t nat -A POSTROUTING -o eno4 -j MASQUERADE
11sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"