局域网路的服务中,最重要的就是 DHCP, DNS 这两个!另外,时间同步的 NTP 也挺重要的!
不论是在家里、小型办公室、企业内分部门的办公室,大部分的环境都还是需要网络的。那网络参数主要由谁分配呢? 当然就是 IP 分享器后端的 DNCP 服务所提供!我们在介绍网络设置时,都还有主机名称的设置呢!那要由谁提供? 基本上当你由 DHCP 取得 IP 地址后,自然就可以通过 DNS 对应的正反解来取得正确的主机名称了!所以,主要的局域网路的网络参数分配, 就得要 DHCP 与 DNS 服务喔!DNS 我们在前章已经介绍过,所以这里主要介绍 DHCP 喔! 另外,不同主机间的时间同步非常重要!例如目前互联网通用的 https 协定中, 数字签章凭证就是以时间戳记来确认是否为合法的主机名称!此时,如果时间戳记有误,就可能产生很多问题! 所以,在局域网路内架设一部给内部主机同步的时间服务器,也是可以思考的一个方向!
还记得第四章我们谈到过每一部可以连上网络的主机,应该都要有相关的网络参数与主机名称吧!网络参数有自动取得与手动设置, 想想看,如果你的局域网路内有 50 部主机需要管理好了,那你会跟所有的用户说好他们的主机参数,然后再教导你的用户们如何设置? 还得要随时注意用户有没有设置错误网络参数?否则,可能会影响到整体工作的进行啊!想想就很烦对吧!如果有服务器可以提供这个功能, 我们只要让用户在开机时,选择『自动取得 IP』的功能,那网络参数主机名称就可以自动设置妥当! 这样也不会有网络参数手动设置错误的情况!想想看,这样比较轻松愉快吧!
只是要注意是,IP 地址、子网络遮罩、通信闸、DNS 服务器的参数都是由 DHCP (Dynamic Host Configuration Protocol, 动态主机设置协定) 服务提供的,主机名称则是由其他 DNS (Domain Name Service, 领域名称服务) 服务提供的! 所以要分两部份来设置。而某些企业对员工连外的限制比较高,甚至于连网络时间校正的服务通通得要放到企业内部! 所以,那个 NTP (Network Time Protocol) 时间服务器的设置也是需要处理的。
在局域网路里面,当你的用户端电脑开机或者是重新启动网络,然后使用的是自动取得 IP 地址的模式, 那就是激活 dhcp client 功能的意思!此时用户端电脑会向整个局域网路进行广播!这就有点像是你刚刚进到班上, 然后就开始大叫:『我可以坐在哪个位置上?那个谁谁谁可以跟我说一下座位表』这样的感觉。那你应该就会想到啊, 那个『谁谁谁』应该是要存在的吧?当然,那个就是 DHCP 服务器本身!你当然可以说那就是班长大人! 整体运作的情况我们可以用下图来表示:
整体流程大概可以这样解释:
完成这整组流程之后,用户端将收下来的网络参数设置到自己的系统上!于是就有 IP 地址与相关的 TCP/IP 网络参数了。然后再通过 IP 地址与 DNS 查找数据的结果,来直接设置好自己的主机名称! 所以,最终还是需要 DNS 服务!这也是为啥我们在前一章先讨论了 DNS 的缘故。
根据图 9.1.1 以及上述的说明当中,DHCP server 在进行 DHCP offer 的动作时,会去自己的设置档当中找寻这个用户的数据。 那从上面的 broadcast 与 unicast 的动作当中,我们也能理解,事实上 DHCP 大概只会知道用户端的网卡卡号 (MAC Address) 而已。 所以,我们在 DHCP 服务器的设置上,就可以通过用户端的卡号来提供该网卡一个固定的 IP 地址,这就是所谓的固定 IP 地址方式。 如果没有特殊的指定,那么通常 DHCP 就会依据设置,提供一连续的 IP 地址当中的一个来 offer 给用户端而已, 这种情况就是所谓的动态 IP 地址设置方式啰。
由于 DHCP 服务通常是利用一个池子 (pool) 保存一段 IP 地址,然后大部分都是通过动态分配的方式分配给来要求网络参数的用户群。 客户群总是可能来来去去的,因此,这些网络参数必须要能够回收才行!于是,就有所谓的租约时间。当用户端使用这组网络参数超过租约时间, 那 IP 地址与网络参数就会被 DHCP server 回收了。问题是,用户端使用电脑的时间可能会超过租约时间啊! 所以,一般来说,用户端系统都会主动的去续约 (renew) 啦!
如果说租约时间是 3600 秒的话,那么在到达一半的租约时间,也就是 3600/2 = 1800 秒的时候,用户端就会进行 renew 的动作! 进行租约延期~此时 DHCP server 就会重新订定租约时间,于是,用户端电脑又可以有 3600 秒的时间来使用了。当然, 3600 秒只是一个范例, 你可以将租约时间想成 T 小时,所以每隔 0.5T 小时,用户端电脑就会主动去跟 DHCP server 更新租约的意思啦!所以, 只要用户端电脑还激活着,理论上,就不会有租约到期的问题。
那什么时候租约会到期呢?大概有两个情况,一个是用户电脑关闭 (power off),DHCP 服务器在租约时间到期前, 并没有发现用户端来更新租约,自然就过期了。另一种则是用户端主动告知 server 说要发布租约!在 windows 系统可以使用『 ipconfig /release 』释放,在 Linux 则能使用『 dhclient -r [网卡] 』来释放。
在无人管理的环境中,或者是比较多实验室的复杂网络环境下,用户为了自己的应用,可能会自行安插 IP 分享器, 或者是 wifi AP 访问点在有线网络环境中。然后可能因为安插的网络线错误 (应该安插到 WAN 却插到 LAN),将可能导致局域网路内有多个 DHCP server 的窘境,偏偏这种窘境还真的挺常发生的...这时网络环境会发生什么问题呢?
因为 DHCP client 的第一步是『 DHCP Discover 的广播』情况,所以是对整个区网做广播!于是,DHCP server 是先回应的先赢! 所以,你的用户端不会知道局域网路里面的那一部 DHCP server 才是正确的,而是有人回应就大部分接受...也因为这样,在多部 DHCP server 存在时,你接到的网络参数,有可能就会是错误的!那将可能导致你的电脑没有互联网的状况。所以,不要随便在你无法控制的网络环境中加上 DHCP server...,否则最后被查到有问题的凶手~可能会被吊起来打~
回到前一个小节的图标中,我们知道 DHCP client/server 都是在同一个局域网路里面,毕竟是通过广播的方式来进行 DHCP 的探索 (Discover)。 但是,如果你有多个局域网路呢?举例来说,我们目前的规划,就有 ap, lan, dmz 等三个内部的局域网路,这样,要每个局域网路都放一台 DHCP 服务器吗?你可能会说,没关系啊!反正我们的 DHCP server 直接架在 master 骨干系统上就好!不就解决了!问题是,许多的骨干系统, 其实是高端的 switch 交换器耶!并不是操作系统啊!那妳就很想要整个环境只搭建一部 DHCP server 而已,不想要这么多台啊! 未来比较好维护啊!那怎办?这时就得要通过 DHCP relay (DHCP 中继服务) 了!
以我们的环境来说,在 master 骨干系统上面设置好 DHCP relay,然后将所有的 DHCP 封包信息通通丢给实际负责的 DHCP server 就好了! 其他不用理会~而 DHCP server 就得要设置好不同的区网分享的设置~这样就好!但是...如同前一小节说的,DHCP 封包并没有 IP 地址啊! 你也知道网卡卡号不能跨路由~那到底 DHCP relay 是怎么达到 DHCP 中继的?基本上可以这样看:
如上图所示,步骤还是分成 4 个,只是 DHCP relay 在帮用户端发送 DHCP 的时候,必须要知道 DHCP server 的实际 IP 地址, 然后传输的 DHCP 数据里面,可能还得要包含特别的参数,常见使用的参数是 circuit id 这个电路识别码~一般来说, 骨干交互器 (switch) 会在封包上面加上端口口号码这个 circuit id 信息,让 DHCP server 去判段封包来自于那一个端口口, 也就知道来自于那一个网段了!而在我们的 Linux DHCP relay 环境下,可以加上用户端所在网卡的卡号来作为 circuit id! 这样也能知道用户端发起的来源位置!
所以,在上图左边的画面跟一般的 DHCP 流程一致,但是在右侧 DHCP relay 与 server 之间的交谈,就主要通通是 unicast 的沟通方式了! 毕竟彼此都知道对方的实际网络位置啊~
在我们的虚拟环境中,目前共有 4 个网段,除了外部的 192.168.201.0/24 需要配合你的实际网络环境之外, 其他的无线网络(AP)、LAN 网络、DMZ 网络,都是我们可以自己设置的!而 AP 与 LAN 网络的『用户端』就像我们说到的情境! 需要自动取得网络参数较佳。DNS 与 NAT 服务倒是可以直接设置到 DMZ 没有问题!但是 DHCP 服务器却通常得要放置到同一个区网内, 这是因为 DHCP 主要是通过局域网路广播来询问网络参数提供者的!所以,比较正常的情况下,我们会将 DHCP 服务设置在 master 骨干系统上!不过呢,骨干系统的服务是越单纯越好,所以原则上,在这份文档中,我们希望所有的服务都不要架设在 master 上面!
所以,底下我们会将 DHCP 独自放在 DMZ 的网域中,而 NTP 同样架设在同一部系统上。但是由于还是需要 DHCP relay 的协助, 因此 master 骨干系统还是得要安装 DHCP relay 服务才行!只是为了管理方便,我们会将 DHCP relay 的 log 分别放置到不同的注册表中, 以方便未来的侦测与维护,让 master 的登录纪录信息会比较单纯~
根据上述的说明,我们的局域网路与服务器连接的相关性有点像底下这样~DHCP/NTP 放置到 DMZ 的网域内, 设置的 DNS 系统则为 192.168.30.211, 192.168.30.212 这样。DNS 服务器的架设请参考前一章。
要先记得,我们的母系统是在 cloud 的主机底下,然后我们拷贝的服务器来源文件,主要是由 server_raw 来的! 现在就让我们来处理 XML 以及映像档数据:
# 1. 拷贝 server_raw 给 server_dhcp 服务器档 [root@cloud ~]# cd /kvm/img/ [root@cloud img]# cp server_raw.img server_dhcp.img # 2. 前往设置 xml 设置档 [root@cloud img]# cd /kvm/xml/ [root@cloud xml]# cp server_raw.xml server_dhcp.xml [root@cloud xml]# vim server_dhcp.xml <name>server_dhcp</name> <loader readonly="yes" type="pflash" secure="no">/usr/share/edk2/ovmf/OVMF_CODE.fd</loader> <nvram>/kvm/xml/server_dhcp.uefi.fd</nvram> <source file="/kvm/img/server_dhcp.img"/> <mac address="52:54:00:00:30:c3"/> <graphics type="vnc" port="5933" listen="0.0.0.0" passwd="rocky9"> # 3. 启动虚拟机并观察 [root@cloud xml]# virsh create server_dhcp.xml [root@cloud xml]# virsh list Id Name State ----------------------------------- 1 master running 2 client_raw running 13 server_dns_master running 15 server_dns_slave running 16 server_dhcp running [root@cloud xml]# netstat -tlunp | egrep '^Pro|qemu' Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:5909 0.0.0.0:* LISTEN 786802/qemu-kvm tcp 0 0 0.0.0.0:5920 0.0.0.0:* LISTEN 786920/qemu-kvm tcp 0 0 0.0.0.0:5933 0.0.0.0:* LISTEN 1015366/qemu-kvm tcp 0 0 0.0.0.0:5932 0.0.0.0:* LISTEN 985321/qemu-kvm tcp 0 0 0.0.0.0:5931 0.0.0.0:* LISTEN 984148/qemu-kvm
搭建 DHCP 服务器的硬件不难啊~只是要注意的是,我们的网络参数大概会设置成这样:
底下的动作需要在刚刚激活的虚拟机底下实做,这是因为我们会修改网络参数的缘故啊!
# 在 DHCP 虚拟机 (VNC 环境) 完成如下的参数设置: [root@server001 ~]# hostnamectl hostname dhcp.server.vbird [root@dhcp ~]# nmcli connection modify enp1s0 ipv4.method manual ipv4.addresses 192.168.30.213/24 \ > ipv4.gateway 192.168.30.254 ipv4.dns 192.168.30.211,192.168.30.212 \ > ipv4.dns-search server.vbird,lan.vbird,ap.vbird [root@dhcp ~]# nmcli connection up enp1s0 [root@dhcp ~]# curl http://vbird.cn # 有回应网页信息就对了!
因为我们多了一个主机名称的对应,为了让这部主机的名称与 IP 地址能对应,所以我们就得要去修改 master DNS 的 server.vbird 的 zone file 内容才行!你应该要在 master DNS (dns1) 上面处理 intranet 的 server.vbird zone file,也就是 /var/named/named.server.vbird 这个文件内容才对!
# 底下所有的动作都应该要在 dns1 (master DNS) 上面动作: [root@dns1 ~]# vim /var/named/named.server.vbird @ IN SOA dns1.server.vbird. adm.mail.server.vbird. ( 2023120301 3H 15M 1D 600 ) .... dhcp IN A 192.168.30.213 .... [root@dns1 ~]# vim /var/named/named.192.168.30 @ IN SOA dns1.server.vbird. adm.mail.server.vbird. ( 2023120301 3H 15M 1D 600 ) ... 213 IN PTR dhcp.server.vbird. ... [root@dns1 ~]# systemctl restart named-chroot [root@dns1 ~]# dig +short dhcp.server.vbird 192.168.30.213 [root@dns1 ~]# dig +short -x 192.168.30.213 dhcp.server.vbird. [root@dns1 ~]# dig +short dhcp.server.vbird @dns2 192.168.30.213 [root@dns1 ~]# dig +short -x 192.168.30.213 @dns2 dhcp.server.vbird. # 从两部 DNS 系统上面都看到相同的 IP 地址与主机名称了!
有 DHCP server 后,当然需要有 client 的硬件才行~我们的 client_raw 系统还活着!所以可以作为 lan 网段的测试, 但那个得要到 DHCP relay 才会用到...目前需要的是在 DMZ 里面的用户端!因此,我们还额外制作出一个 DMZ 的测试环境~ 硬件的配置得要在 cloud 母系统喔!
# 1. 拷贝 server_raw 给 server_dhcp 服务器档 [root@cloud ~]# cd /kvm/img/ [root@cloud img]# cp server_raw.img server_10.img # 2. 前往设置 xml 设置档 [root@cloud img]# cd /kvm/xml/ [root@cloud xml]# cp server_raw.xml server_10.xml [root@cloud xml]# vim server_10.xml <name>server_10</name> <loader readonly="yes" type="pflash" secure="no">/usr/share/edk2/ovmf/OVMF_CODE.fd</loader> <nvram>/kvm/xml/server_10.uefi.fd</nvram> <source file="/kvm/img/server_10.img"/> <mac address="52:54:00:00:30:10"/> <graphics type="vnc" port="5940" listen="0.0.0.0" passwd="rocky9"> # 3. 启动虚拟机并观察 [root@cloud xml]# virsh create server_10.xml [root@cloud xml]# virsh list Id Name State ----------------------------------- 1 master running 2 client_raw running 13 server_dns_master running 15 server_dns_slave running 16 server_dhcp running 17 server_10 running
这部用户端系统比较有趣,因为 server_10 是跟 server_dhcp 在同一个网域内,所以可以简单的通过原先 dhcp server 缺省的情况来架设好! 这样大家比较有 full 啦!
DHCP 这个功能有非常多的软件可以达成,ISC 官网建议使用新的 Kea DHCP 软件,功能比较强大!不过,在 RHEL 官网中,目前建议还是使用原本的 ISC DHCP 软件~相关数据请查阅文末的参考数据中。另外,Kea DHCP 目前并没有推出 DHCP relay 的软件,所以,relay 还是得用原有的 DHCP relay 就是了。不过,总的来说,对于 DHCP 任务影响不大!我们还是使用原先的 DHCP 服务器软件。 另外,跟 DHCP 有关的还有 IP 的版本,IPv4 与 IPv6 使用的服务与设置档并不相同~IPv6 的设置较为复杂~ 所以,我们底下主要先以 IPv4 为主来介绍的喔~
在 RHEL 9 的衍生产品中,安装的 DHCP 服务器软件为 dhcp-server,让我们来安装好之后瞧瞧这个软件配置吧!
先将软件装起来!
# 安装/查看 dhcp-server [root@dhcp ~]# yum -y install dhcp-server [root@dhcp ~]# rpm -ql dhcp-server /etc/dhcp /etc/dhcp/dhcpd.conf # DHCP 主设置档:针对 IPv4 /etc/dhcp/dhcpd6.conf # DHCP 主设置档:针对 IPv6 .... /usr/sbin/dhcpd # DHCP 主程序 ... /usr/share/doc/dhcp-server/dhcpd.conf.example # DHCP 设置范例档 ... /var/lib/dhcpd/dhcpd.leases # DHCP 租约纪录档:针对 IPv4 /var/lib/dhcpd/dhcpd6.leases # DHCP 租约纪录档:针对 IPv6
主设置档为 /etc/dhcp/dhcpd.conf,不过,这个文件基本内容是空的!可以查看的应该是上面表格当中的 dhcpd.conf.example 文件。 你可以将上述的文件拷贝成为 dhcpd.conf,然后再去一个一个修改即可。在设置档当中的基本语法大致上是这样:
DHCP 的原理要花比较多时间来处理,设置则相对简单!假设我们想要达成底下的功能:
基本项目大概就上面这些而已~接下来就让我们来一项一项设置好吧!注意喔,底下的主设置档其实就是搭配上面的清单项目内容建置的! 所以可以搭配着看喔!
# 1. 先设置主设置档 [root@dhcp ~]# vim /etc/dhcp/dhcpd.conf ddns-update-style none; log-facility local7; subnet 192.168.30.0 netmask 255.255.255.0 { default-lease-time 3600; max-lease-time 28800; range 192.168.30.1 192.168.30.10; option routers 192.168.30.254; option domain-name-servers 192.168.30.211, 192.168.30.212; option domain-name "server.vbird"; } # 每个设置的说明,都请参考上面的清单项目!有搭配清单项目喔! [root@dhcp ~]# systemctl enable --now dhcpd [root@dhcp ~]# journalctl -xeu dhcpd.service .... Dec 03 22:24:46 : Config file: /etc/dhcp/dhcpd.conf Dec 03 22:24:46 : Database file: /var/lib/dhcpd/dhcpd.leases Dec 03 22:24:46 : PID file: /var/run/dhcpd.pid Dec 03 22:24:46 : Internet Systems Consortium DHCP Server 4.4.2b1 .... Dec 03 22:24:46 : Wrote 0 leases to leases file. Dec 03 22:24:46 : Listening on LPF/enp1s0/52:54:00:00:30:c3/192.168.30.0/24 Dec 03 22:24:46 : Sending on LPF/enp1s0/52:54:00:00:30:c3/192.168.30.0/24 Dec 03 22:24:46 : Sending on Socket/fallback/fallback-net Dec 03 22:24:46 : Server starting service. # 可以看到主设置档、租约时间档、监听界面数据等! [root@dhcp ~]# netstat -tlunp Proto Recv-Q Send-Q Local Address Foreign Address PID/Program name udp 0 0 0.0.0.0:67 0.0.0.0:* 12637/dhcpd [root@dhcp ~]# firewall-cmd --list-services cockpit dhcpv6-client ftp http https ssh [root@dhcp ~]# firewall-cmd --remove-service={cockpit,dhcpv6-client,ftp,http,https} [root@dhcp ~]# firewall-cmd --add-service=dhcp [root@dhcp ~]# firewall-cmd --list-services dhcp ssh [root@dhcp ~]# firewall-cmd --runtime-to-permanent # 最后将防火墙设置妥当就 OK 啦!
基本上,主设置档就这样处理完毕啦!接下来就等待用户端来要求 IP 地址等网络参数而已!
现在,让我们来到 server_10 的系统中,该系统我们已经在 9.1.3 当中创建起来,直接使用 VNC 连接到终端机, 然后将 Network Manager 设置成为使用 dhcp 的功能,不过,还需要加入 domain search 喔!不然 /etc/resolv.conf 不会主动更新 search 的项目!不过我们曾经设置过 NetworkManager 了,所以需要将一些数据移除才行!
# 底下的工作全部都在 server_10 上面完成!缺省主机名称会是 server001 [root@server001 ~]# nmcli connection show enp1s0 | grep ipv4 ipv4.method: manual ipv4.dns: 120.114.100.1,168.95.1.1 ipv4.dns-search: -- ipv4.addresses: 192.168.30.1/24 ipv4.gateway: 192.168.30.254 # 上面这几个项目,很多都要清空!要增加的是 dns-search 而已 [root@server001 ~]# nmcli connection modify enp1s0 ipv4.method auto ipv4.dns '' \ > ipv4.dns-search 'server.vbird,lan.vbird,ap.vbird' ipv4.addresses '' ipv4.gateway '' [root@server001 ~]# nmcli connection up enp1s0 [root@server001 ~]# nmcli connection show enp1s0 IP4.SEARCHES[1]: server.vbird IP4.SEARCHES[2]: lan.vbird IP4.SEARCHES[3]: ap.vbird DHCP4.OPTION[1]: dhcp_client_identifier = 01:52:54:00:00:30:10 DHCP4.OPTION[2]: dhcp_lease_time = 3600 DHCP4.OPTION[3]: dhcp_server_identifier = 192.168.30.213 DHCP4.OPTION[4]: domain_name = server.vbird DHCP4.OPTION[5]: domain_name_servers = 192.168.30.211 192.168.30.212 DHCP4.OPTION[6]: expiry = 1701618387 DHCP4.OPTION[7]: ip_address = 192.168.30.1 .... DHCP4.OPTION[25]: routers = 192.168.30.254 DHCP4.OPTION[26]: subnet_mask = 255.255.255.0 # 可以看到 IP 地址,还有 DHCP server 与租约的相关讯喔!
很简单的,你的 client 未来都可以拥有这个 IP 地址了~只要不断线或者因为 IP 地址池子内的 IP 数量被用完, 那你都能使用该 IP 地址啦!通常 DHCP server 都会从 range 的第一个 IP 地址开始发放!所以我们就拿到 192.168.30.1/24 这个 IP 地址啰。
回到 DHCP server 上面,我们来看看租约时间文件呈现什么效果:
[root@dhcp ~]# date Sun Dec 3 23:00:14 CST 2023 [root@dhcp ~]# cat /var/lib/dhcpd/dhcpd.leases .... lease 192.168.30.1 { starts 0 2023/12/03 14:46:27; < 时间都在以前!现在变成未来? ends 0 2023/12/03 15:46:27; cltt 0 2023/12/03 14:46:27; binding state active; next binding state free; rewind binding state free; hardware ethernet 52:54:00:00:30:10; < 会纪录这部系统的 MAC 卡号喔! uid "\001RT\000\0000\020"; client-hostname "server001"; }
首先,时间不太对劲~怎么会是过去式?原来 dhcpd 缺省纪录的是 UTC 时间,并不是本地端时间!所以,我们可以尝试修改成为本地时间。 再来,用户端主机名称之前被我们设计过,所以目前的主机名称并不会随着 IP 地址与 DNS 的查找而改变!这就怪怪的! 有个简单的方法是,直接删除用户端的 /etc/hostname 即可!如果想要固定主机名称,未来可再使用 hostnamectl 重新设置回来即可!
在我们的规划中,之前建置的 server_10 这部用户端系统,基本上应该是需要取得 192.168.30.10/24 这样的 IP 地址才对! 也就是说,我们需要将该系统的 IP 地址对照为固定 IP 地址,而不是随机的!那要如何处理?其实就是通过硬件地址来指定而已! 另外,我们也想要使用本地端时间取代 UTC 的时间参数设计在租约文件当中!所以,我们应该要这样做个修改比较好:
# [root@dhcp ~]# vim /etc/dhcp/dhcpd.conf ddns-update-style none; log-facility local7; db-time-format local; subnet 192.168.30.0 netmask 255.255.255.0 { default-lease-time 3600; max-lease-time 28800; range 192.168.30.1 192.168.30.10; option routers 192.168.30.254; option domain-name-servers 192.168.30.211, 192.168.30.212; option domain-name "server.vbird"; } host "server10" { hardware ethernet 52:54:00:00:30:10; fixed-address 192.168.30.10; } # host 就是固定 IP 地址的设置!要注意 host 需要写在 global 当中喔! [root@dhcp ~]# systemctl restart dhcpd [root@dhcp ~]# journalctl -xeu dhcpd.service # 尽量不要出现红字的错误!虽然有的错误是可忽略的~
上面的特殊字体部份,就是这次添加的设置!host 可以重复出现多次~一个代表一部主机。现在,回到用户端重新取得 DHCP 传来的 IP 参数看看:
# 请在 server10 的环境下实做 [root@server10 ~]# nmcli connection up enp1s0 [root@server10 ~]# ip addr show enp1s0 | grep 'inet ' inet 192.168.30.10/24 brd 192.168.30.255 scope global dynamic noprefixroute enp1s0
这样,未来这部系统无论进行什么动作,只要网络卡不变,那么它取得的 IP 地址,应该就不变了!那么这时候的 DHCP server 显示的租约文件会变怎样?
[root@dhcp ~]# journalctl -xeu dhcpd.service .... Dec 04 09:16:10 : DHCPDISCOVER from 52:54:00:00:30:10 via enp1s0 Dec 04 09:16:10 : DHCPOFFER on 192.168.30.10 to 52:54:00:00:30:10 via enp1s0 Dec 04 09:16:10 : Dynamic and static leases present for 192.168.30.10. Dec 04 09:16:10 : Remove host declaration server10 or remove 192.168.30.10 Dec 04 09:16:10 : from the dynamic address pool for 192.168.30.0/24 Dec 04 09:16:10 : uid lease 192.168.30.1 for client 52:54:00:00:30:10 is duplicate on 192.168.30.0/24 .... [root@dhcp ~]# cat /var/lib/dhcpd/dhcpd.leases ... lease 192.168.30.1 { starts epoch 1701650416; # Mon Dec 04 08:40:16 2023 ends epoch 1701652570; # Mon Dec 04 09:16:10 2023 tstp epoch 1701652570; # Mon Dec 04 09:16:10 2023 cltt epoch 1701650416; # Mon Dec 04 08:40:16 2023 binding state free; hardware ethernet 52:54:00:00:30:10; uid "\001RT\000\0000\020"; }
事实上,我们的设置不是很好!因为 192.168.30.0/24 分配的动态网段就是 192.168.30.1 ~ 192.168.30.10,但是固定的 IP 地址却又提供了 192.168.30.10 这个 IP 地址,于是就冲突了!虽然最终还是发放给用户端正确的固定 IP 地址,但是在 journalctl 的登录消息中, 你可以发现其实这样不太妥当!一般来说,我们会有预留的 IP 地址以及动态分享出去的 IP 地址范围,这两者应该不要重复比较好! 另外,租约档的时间参数有更新了~使用的是 unix time 的格式,不过后面有提供本地端的正确时间喔!这样也比较好观察!
接下来开始思考,那么我们的 AP 网段以及 LAN 网段该如何处理相关的 DHCP 任务?其实也非常简单,两个动作! 一个是在 DHCP server 上面设置好分享的方式,这会使用到规范来源类别的 class 部份,以及将动态 IP 分配给特定用户的 pool 功能。 然后在 master 骨干上面激活 dhcp-relay 服务即可!就让我们来测试测试。
就如同图 9.1.3 提到的,我们的用户端来源可能还有来自 AP 以及 LAN 两个网段,现在,我们大略将用户端来源分为三群组:
判断来源可以使用 class 的分式来分群,其中比较有趣的是 any 这一群,里面是空的!代表来源都符合的意思!放在最前面的部份就会变这样:
[root@dhcp ~]# vim /etc/dhcp/dhcpd.conf ddns-update-style none; log-facility local7; db-time-format local; stash-agent-options true; class "myap" { match if option agent.circuit-id = "wlp7s0u1"; # 判断代理的电路名称是否为 wlp7s0u1。若为交换器,这边通常是端口口号码 } class "mylan" { match if option agent.circuit-id = "enp2s0"; } class "any" { } ....
我们需要避免 192.168.30.0/24 这一个 DMZ 网段的 IP 地址不会分配给其他两段,所以需要拒绝 myap, mylan 来源的 DHCP 封包要求~ 所以这一段 subnet 我们可以改成这样:
[root@dhcp ~]# vim /etc/dhcp/dhcpd.conf subnet 192.168.30.0 netmask 255.255.255.0 { default-lease-time 3600; max-lease-time 28800; option routers 192.168.30.254; option domain-name-servers 192.168.30.211, 192.168.30.212; option domain-name "server.vbird"; pool { deny members of "myap"; deny members of "mylan"; allow members of "any"; range 192.168.30.1 192.168.30.10; # 前面三行在设置拒绝其他两个网段的封包,最后则全部放行!然后 pool 需要有 range 设置! } }
最后,将分享的其他两个网段丢上来即可!
[root@dhcp ~]# vim /etc/dhcp/dhcpd.conf shared-network vbirdlan { subnet 192.168.10.0 netmask 255.255.255.0 { default-lease-time 1800; max-lease-time 7200; option routers 192.168.10.254; option domain-name-servers 192.168.30.211, 192.168.30.212; option domain-name "ap.vbird"; pool { allow members of "myap"; deny members of "any"; range 192.168.10.1 192.168.10.100; } } subnet 192.168.20.0 netmask 255.255.255.0 { default-lease-time 3600; max-lease-time 14400; option routers 192.168.20.254; option domain-name-servers 192.168.30.211, 192.168.30.212; option domain-name "lan.vbird"; pool { allow members of "mylan"; deny members of "any"; range 192.168.20.1 192.168.20.100; } } }
观察看看有没有设置错误的问题:
[root@dhcp ~]# systemctl restart dhcpd [root@dhcp ~]# journalctl -xeu dhcpd.service # 不能看到错误消息啊!
基本上这样就设置妥当了!基本上,要注意的就是 (1)class 搭配 match 的符合用户端特征的分群纪录,(2)通过 pool 将不同的来源进行拒绝与放行, (3)通过 shared-network 设置好非在本地端局域网路的其他网域参数设置。这样就搞定了!等待 master 骨干系统的 dhcp-relay 设置吧!
master 骨干系统激活 dhcp-relay 挺简单~大致的步骤就是 (1)安装软件,(2)设置服务并且修改参数,(3)查看防火墙有无接受 port 67/udp 这样即可。让我们一步一步处理看看:
# 1. 在 master 系统上,安装好 dhcp-relay,并且查看相关文件位置: [root@master ~]# yum -y install dhcp-relay [root@master ~]# rpm -ql dhcp-relay /usr/lib/systemd/system/dhcrelay.service /usr/sbin/dhcrelay # 上面是服务设置参考档,以及实际运作数据档 # 2. 拷贝服务至开机运作位置,同时修改成为 agent 功能 [root@master ~]# cp /usr/lib/systemd/system/dhcrelay.service /etc/systemd/system/ [root@master ~]# vim /etc/systemd/system/dhcrelay.service [Unit] Description=DHCP Relay Agent Daemon Documentation=man:dhcrelay(8) Wants=network-online.target After=network-online.target [Service] Type=notify ExecStart=/usr/sbin/dhcrelay -d --no-pid -a 192.168.30.213 StandardError=null StandardError=journal StandardOutput=journal SyslogFacility=local5 [Install] WantedBy=multi-user.target [root@master ~]# systemctl daemon-reload [root@master ~]# systemctl enable --now dhcrelay.service [root@master ~]# journalctl -xeu dhcrelay [root@master ~]# netstat -tlunp Proto Recv-Q Send-Q Local Address Foreign Address PID/Program name udp 0 0 0.0.0.0:67 0.0.0.0:* 40897/dhcrelay # 3. 看看防火墙是否正确的运作: [root@master ~]# nft list chain inet mytable myinput table inet mytable { chain myinput { type filter hook input priority filter; policy drop; ct state established,related accept meta l4proto icmp accept iifname "lo" accept ip saddr 192.168.201.254 accept ip saddr { 10.30.30.0/24, 10.40.40.0/24 } reject with icmp port-unreachable iifname "enp1s0" ip saddr 192.168.201.0/24 tcp dport 22 accept iifname "enp2s0" tcp dport { 22, 53, 5901-5910 } accept iifname "enp2s0" udp dport { 53, 67, 123 } accept iifname "wlp7s0u1" tcp dport { 22, 53, 5901-5910 } accept iifname "wlp7s0u1" udp dport { 53, 67, 123 } accept } } # 没问题!之前就规划好会激活 dhcp 了!所以这里原本就放行 67/udp!
基本设置大概就是这样!不过,我们希望可以将个别的服务注册表分离出来,所以,接下来可以进行一些有趣的变化。
在 journalctl 可以轻松愉快的找到我们的服务来观察,那么能不能将登录信息移出 /var/log/messages 呢? 我们在 dhcrelay.service 当中,其实多加入了一个 syslog 的使用类别『SyslogFacility=local5』,所以, 就能够修改 rsyslog.conf 的内容来切出登录信息!简单作法如下:
# 记得是在 master 底下进行! [root@master ~]# vim /etc/rsyslog.conf *.info;mail.none;authpriv.none;cron.none;local5.none /var/log/messages local5.* /var/log/dhcrelay.log [root@master ~]# systemctl restart rsyslog [root@master ~]# systemctl restart dhcrelay [root@master ~]# cat /var/log/dhcrelay.log # 这样,就将 dhcrelay 切出来了!
接下来,请使用手机或其他 wifi 用户端软件,然后点击 masterap 之后,看看测试的情况如何!基本上, 应该要可以让手机上网了!同时在 lan 网段的 client_raw 系统中,运行如下的动作来激活 DHCP 看看:
# 底下的动作需要在 client_raw,缺省名称 client001 用户端系统上面实做! [root@client001 ~]# rm /etc/hostname [root@client001 ~]# nmcli connection modify enp1s0 ipv4.method auto ipv4.dns '' \ > ipv4.dns-search 'server.vbird,lan.vbird,ap.vbird' ipv4.addresses '' ipv4.gateway '' [root@client001 ~]# nmcli connection up enp1s0 [root@client001 ~]# hostnamectl Static hostname: (unset) Transient hostname: client001.lan.vbird Icon name: computer-vm ... [root@client001 ~]# nmcli connection show enp1s0 | grep DHCP DHCP4.OPTION[1]: dhcp_client_identifier = 01:52:54:00:00:20:01 DHCP4.OPTION[2]: dhcp_lease_time = 3600 DHCP4.OPTION[3]: dhcp_server_identifier = 192.168.30.213 DHCP4.OPTION[4]: domain_name = lan.vbird DHCP4.OPTION[5]: domain_name_servers = 192.168.30.211 192.168.30.212 DHCP4.OPTION[6]: expiry = 1701663139 DHCP4.OPTION[7]: ip_address = 192.168.20.1 .... DHCP4.OPTION[25]: routers = 192.168.20.254 DHCP4.OPTION[26]: subnet_mask = 255.255.255.0
看起来有真的接收到 DHCP server 提供的网络消息呢!接下来,到
来到 DHCP 服务器看看租约是否正常纪录?
[root@dhcp ~]# cat /var/lib/dhcpd/dhcpd.leases
lease 192.168.20.1 {
starts epoch 1701659539; # Mon Dec 04 11:12:19 2023
ends epoch 1701663139; # Mon Dec 04 12:12:19 2023
cltt epoch 1701659539; # Mon Dec 04 11:12:19 2023
binding state active;
next binding state free;
rewind binding state free;
hardware ethernet 52:54:00:00:20:01;
uid "\001RT\000\000 \001";
option agent.circuit-id "enp2s0";
client-hostname "client001";
}
lease 192.168.10.1 {
starts epoch 1701659844; # Mon Dec 04 11:17:24 2023
ends epoch 1701661644; # Mon Dec 04 11:47:24 2023
cltt epoch 1701659844; # Mon Dec 04 11:17:24 2023
binding state active;
next binding state free;
rewind binding state free;
hardware ethernet 6e:f9:1b:91:c0:04;
uid "\001n\371\033\221\300\004";
set vendor-class-identifier = "android-dhcp-13";
option agent.circuit-id "wlp7s0u1";
client-hostname "Pixel-4-XL";
}
看起来 OK 喔!这就是分享 DHCP relay 的整体流程啰!提供大家参考!
我们在前面的章节里面就谈到过,你的服务器 (尤其是我们内部主机) 应该要跟互联网的时间同步!每台主机都时间同步较佳! 那如果内部主机的电脑数量很多了,当然就是我们自己架设一部内部的时间服务器较佳啊!基本上,时间服务器使用所谓的 NTP 协定 (Network Time Protocol, NTP) 来互相同步时间~NTP 时间钟有所谓的阶层架构 (stratum),网络上有提供数台第一阶与第二阶的时间服务器, 您可以参考如下的网站:
在台湾,你也可以直接找到国家实验室的 time server: tock.stdtime.gov.tw, clock.stdtime.gov.tw 等。我们的测试机器目前摆在昆山科大, 所以也可以使用 ntp.ksu.edu.tw 这部 NTP 服务器作为主要参考源!
如前所述,我们建议 NTP 放置到与 dhcp 同一部系统上,所以前往 dhcp 服务器,然后安装好 chrony 软件吧!之后就来设置一下相关的参数:
[root@dhcp ~]# yum -y install chrony [root@dhcp ~]# vim /etc/chrony.conf #pool 2.rocky.pool.ntp.org iburst server ntp.ksu.edu.tw iburst server tock.stdtime.gov.tw iburst server time.stdtime.gov.tw iburst driftfile /var/lib/chrony/drift makestep 1.0 3 rtcsync allow 192.168.10.0/24 allow 192.168.20.0/24 allow 192.168.30.0/24 keyfile /etc/chrony.keys ntsdumpdir /var/lib/chrony leapsectz right/UTC logdir /var/log/chrony [root@dhcp ~]# systemctl restart chronyd [root@dhcp ~]# chronyc sources MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^? ntp.ksu.edu.tw 0 7 0 - +0ns[ +0ns] +/- 0ns ^? 211-22-103-157.hinet-ip.> 0 7 0 - +0ns[ +0ns] +/- 0ns ^? 118-163-81-61.hinet-ip.h> 0 7 0 - +0ns[ +0ns] +/- 0ns [root@dhcp ~]# netstat -tlunp | egrep '^Proto|chrony' Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 0 0 0.0.0.0:123 0.0.0.0:* 13611/chronyd udp 0 0 127.0.0.1:323 0.0.0.0:* 13611/chronyd udp6 0 0 ::1:323 :::* 13611/chronyd [root@dhcp ~]# firewall-cmd --add-service=ntp [root@dhcp ~]# firewall-cmd --list-services dhcp ntp ssh [root@dhcp ~]# firewall-cmd --runtime-to-permanent [root@dhcp ~]# chronyc tracking Reference ID : 00000000 () Stratum : 0 Ref time (UTC) : Thu Jan 01 00:00:00 1970 System time : 0.000000001 seconds fast of NTP time Last offset : +0.000000000 seconds RMS offset : 0.000000000 seconds Frequency : 11.928 ppm fast Residual freq : +0.000 ppm Skew : 0.000 ppm Root delay : 1.000000000 seconds Root dispersion : 1.000000000 seconds Update interval : 0.0 seconds Leap status : Not synchronised
不过要注意的是,竟然无法同步!怎么回事?查了查,看起来非常有可能是因为 master 骨干系统的防火墙并没有放行 DMZ 的 NTP 对外的情况! 这真是伤脑筋了!所以,我们得要让 DMZ 内的系统能够向外要求 123/udp 的端口口才行!否则无法对外同步!
# 需要在骨干系统上面实做才行! [root@master ~]# vim /root/nftables.sh # part 3: 处理 DMZ 功能 nft add chain inet mytable myforward { type filter hook forward priority filter \; policy accept \; } nft add rule inet mytable myforward iifname ${dmzif} oifname ${wanif} ct state established,related accept nft add rule inet mytable myforward iifname ${dmzif} oifname ${wanif} udp dport { 53, 123 } accept nft add rule inet mytable myforward iifname ${dmzif} oifname ${wanif} tcp dport { 53, 80, 443 } accept nft add rule inet mytable myforward iifname ${dmzif} oifname ${wanif} reject nft add rule inet mytable myforward iifname ${dmzif} oifname ${lanif} ct state established,related accept nft add rule inet mytable myforward iifname ${dmzif} oifname ${lanif} reject [root@master ~]# sh /root/nftables.sh [root@master ~]# nft list chain inet mytable myforward table inet mytable { chain myforward { type filter hook forward priority filter; policy accept; iifname "enp3s0" oifname "enp1s0" ct state established,related accept iifname "enp3s0" oifname "enp1s0" udp dport { 53, 123 } accept iifname "enp3s0" oifname "enp1s0" tcp dport { 53, 80, 443 } accept iifname "enp3s0" oifname "enp1s0" reject iifname "enp3s0" oifname "enp2s0" ct state established,related accept iifname "enp3s0" oifname "enp2s0" reject } }
很快的设置妥当了!接下来就测试看看用户端能不能来更新啰!
前往 client001 系统去编辑 chrony.conf 看看!
# 测试用户端,所以都在 client001 上面实做喔! [root@client001 ~]# vim /etc/chrony.conf server dhcp.server.vbird iburst [root@client001 ~]# systemctl restart chronyd [root@client001 ~]# chronyc tracking Reference ID : C0A81ED5 (dhcp.server.vbird) Stratum : 4 Ref time (UTC) : Mon Dec 04 04:12:00 2023 System time : 0.000000016 seconds slow of NTP time Last offset : +0.000013772 seconds RMS offset : 0.000013772 seconds Frequency : 12.326 ppm fast Residual freq : +9.654 ppm Skew : 0.022 ppm Root delay : 0.007695264 seconds Root dispersion : 0.023577420 seconds Update interval : 2.0 seconds Leap status : Normal
记得最后需要 tracking 追踪一下!测试看看有没有问题喔!