
1. 为什么Rocky Linux 9.1的网络配置不能照搬CentOS 7经验刚接手一台新部署的Rocky Linux 9.1服务器时我下意识敲出vi /etc/sysconfig/network-scripts/ifcfg-ens33——结果发现目录压根不存在。这不是手误而是整个网络配置范式发生了根本性迁移。Rocky Linux 9.1作为RHEL 9的社区克隆版本彻底弃用了传统的network-scripts服务转而全面拥抱NetworkManager作为唯一官方支持的网络管理框架。这个变化不是“可选升级”而是强制切换systemctl disable network后传统脚本将完全失效nmcli命令不再只是辅助工具它成了网络配置的唯一入口。这种转变背后是RHEL生态十年演进的必然结果。NetworkManager从RHEL 6时代起就作为实验性组件存在到RHEL 8已成默认方案而RHEL 9则完成了最终切割。其核心优势在于动态适应能力——当物理网卡热插拔、USB网卡接入、Wi-Fi切换或容器网络注入时NetworkManager能实时重绘网络拓扑而传统ifup/ifdown脚本只能处理静态场景。更关键的是安全模型重构NetworkManager与firewalld、SELinux深度集成所有网络操作自动触发策略校验避免了旧方案中iptables规则与防火墙策略脱节的经典问题。但代价也很真实。我见过三位资深运维在迁移初期集体踩坑有人用ip addr add手动配置IP后NetworkManager检测到“未托管接口”自动将其DOWN掉有人修改/etc/sysconfig/network-scripts/文件却始终不生效因为NM根本不去读这些废弃路径还有人试图用systemctl restart network重启服务结果得到“Unit network.service not found”的报错。这些都不是操作失误而是对底层架构变更缺乏认知导致的系统性误判。提示Rocky Linux 9.1的网络配置必须遵循“NM优先”原则——所有操作都应通过nmcli或nmtui完成任何绕过NetworkManager的直接修改包括ip命令、sysctl参数调整都可能被NM自动覆盖或触发冲突。这不是技术偏好问题而是系统设计的硬性约束。理解这个前提才能真正读懂后续所有配置逻辑。比如设置静态IP时你不是在“给网卡写地址”而是在向NetworkManager提交一个连接配置connection profile这个profile包含IP、网关、DNS、路由等完整网络意图并由NM持续守护其状态。这解释了为什么nmcli connection modify命令需要同时指定ipv4.addresses、ipv4.gateway、ipv4.dns和ipv4.method manual——缺一不可因为NM要求声明完整的网络契约而非零散参数。2. NetworkManager实战从基础连接管理到生产级网络拓扑构建2.1 连接对象的本质理解connection profile的生命周期NetworkManager的核心抽象是“连接”connection它并非简单的配置文件而是一个具有状态机的网络意图实体。执行nmcli connection show列出的所有条目本质是NM数据库中持久化的连接定义每个连接包含三类关键属性标识层connection.id人类可读名称、connection.uuid全局唯一ID、connection.interface-name绑定物理接口配置层ipv4.methodauto/manual/disabled、ipv4.addressesCIDR格式、ipv4.gateway、ipv4.dns等行为层connection.autoconnect开机自启、connection.autoconnect-priority多连接时的激活顺序、connection.metered是否计费网络我曾遇到一个典型故障服务器重启后网络不通nmcli device status显示接口为unmanaged。排查发现connection.interface-name被错误设置为eth0而实际设备名是ens192VMware虚拟网卡命名规则变化。NM因找不到匹配接口拒绝激活该连接。解决方案不是改/etc/sysconfig/文件而是执行nmcli connection modify System ens192 connection.interface-name ens192 nmcli connection up System ens192这里的关键洞察是connection profile与物理设备的绑定关系是动态维护的UUID才是连接的真正身份凭证interface-name只是运行时匹配条件。2.2 静态IP配置的完整链路从创建到验证以Rocky Linux 9.1最小化安装环境为例假设需为ens192配置静态IP192.168.10.50/24网关192.168.10.1DNS8.8.8.8。以下是经过生产环境验证的七步操作链创建新连接避免修改默认连接引发意外nmcli connection add type ethernet con-name Prod-Static ifname ens192此命令生成UUID并注册连接但此时连接处于deactivated状态。配置IPv4参数必须一次性设置method否则NM拒绝后续地址配置nmcli connection modify Prod-Static ipv4.method manual \ ipv4.addresses 192.168.10.50/24 \ ipv4.gateway 192.168.10.1 \ ipv4.dns 8.8.8.8,114.114.114.114 \ ipv4.ignore-auto-routes yes \ ipv4.ignore-auto-dns yesignore-auto-*参数至关重要它阻止DHCP获取的路由/DNS覆盖手动配置这是Rocky 9.1中常见的静默覆盖源。禁用IPv6生产环境常见需求避免双栈干扰nmcli connection modify Prod-Static ipv6.method disabled启用连接自动激活nmcli connection modify Prod-Static connection.autoconnect yes激活连接触发NM全量应用配置nmcli connection up Prod-Static验证网络连通性分层检查# 检查接口状态 ip addr show ens192 | grep inet # 测试网关可达性 ping -c 3 192.168.10.1 # 测试DNS解析 nslookup google.com # 检查路由表 ip route | grep ^default持久化验证模拟重启场景systemctl restart NetworkManager # 等待10秒后检查连接状态 nmcli connection show Prod-Static | grep connection.state:注意nmcli connection down命令不会删除连接仅断开当前会话若需彻底移除必须使用nmcli connection delete Prod-Static。生产环境中建议为每个连接命名时加入环境标识如Prod-Static、Dev-DHCP避免名称冲突。2.3 复杂网络场景的NM实现Bonding与VLAN当面对高可用或网络分段需求时NetworkManager提供了原生支持无需依赖内核模块手动配置。以双网卡bonding为例mode802.3adLACP聚合# 创建bond主接口 nmcli connection add type bond con-name Bond-Prod ifname bond0 bond.options mode802.3ad,miimon100 # 添加slave网卡需先删除原有连接 nmcli connection delete System ens192 nmcli connection delete System ens224 nmcli connection add type bond-slave con-name Bond-Slave1 ifname ens192 master bond0 nmcli connection add type bond-slave con-name Bond-Slave2 ifname ens224 master bond0 # 为bond配置静态IP nmcli connection modify Bond-Prod ipv4.method manual \ ipv4.addresses 10.10.10.100/24 \ ipv4.gateway 10.10.10.1 \ ipv4.dns 10.10.10.10 \ ipv4.ignore-auto-routes yes # 启用连接 nmcli connection up Bond-Prod此方案的优势在于NM自动处理bonding参数同步、slave状态监控、故障切换当ens192断开时NM在3秒内将流量切至ens224且所有配置持久化存储于/etc/NetworkManager/system-connections/目录下符合RHEL 9的安全审计要求。对于VLAN划分NM同样提供简洁语法# 在bond0上创建VLAN 100 nmcli connection add type vlan con-name VLAN100 dev bond0 id 100 nmcli connection modify VLAN100 ipv4.method manual \ ipv4.addresses 172.16.100.10/24 \ ipv4.dns 172.16.100.1 nmcli connection up VLAN100NM会自动创建bond0.100子接口并配置802.1Q标签无需手动加载8021q模块——这是RHEL 9内核与NM深度集成的体现。3. firewalld深度管控从端口放行到区域策略精细化3.1 firewalld的区域模型理解zone的语义层级firewalld的区域zone不是简单的规则容器而是预定义的安全策略模板。Rocky Linux 9.1默认启用public区域但其规则集/usr/lib/firewalld/zones/public.xml仅开放SSH、DHCP客户端等基础服务。生产环境常需自定义区域例如为数据库服务器创建db-server区域# 创建新区域 firewall-cmd --permanent --new-zonedb-server # 设置默认目标DROP所有未明确允许的流量 firewall-cmd --permanent --zonedb-server --set-targetDROP # 允许MySQL端口注意必须指定协议 firewall-cmd --permanent --zonedb-server --add-port3306/tcp # 允许特定IP访问白名单模式 firewall-cmd --permanent --zonedb-server --add-source10.10.20.0/24 # 将网卡绑定到该区域 firewall-cmd --permanent --zonedb-server --change-interfaceens192 # 重载配置 firewall-cmd --reload关键点在于--set-targetDROP它改变了区域的默认行为。public区域的目标是DEFAULT即ACCEPT未匹配规则的流量而db-server设为DROP后所有流量必须显式放行这是纵深防御的核心实践。3.2 动态端口检查与服务调试技巧当应用无法访问时“检查端口是否开通”常被简化为firewall-cmd --list-ports但这极易遗漏关键信息。正确诊断流程应分三层确认端口是否在firewalld中注册# 查看当前区域所有开放端口 firewall-cmd --list-ports # 检查特定端口状态 firewall-cmd --query-port8080/tcp验证端口是否被服务真正监听常被忽略的环节# 检查进程绑定 ss -tuln | grep :8080 # 或使用netstat需安装 dnf install net-tools -y netstat -tuln | grep :8080我曾遇到案例firewalld显示8080开放但ss命令无输出——根源是应用未启动而非防火墙问题。测试端口可达性排除网络层干扰# 本地测试排除防火墙影响 curl -v http://localhost:8080 # 远程测试需从另一台机器执行 telnet 192.168.10.50 8080若telnet超时但curl localhost成功则问题在firewalld或网络路由若两者均失败则聚焦应用层。实操心得使用firewall-cmd --direct添加临时规则时务必谨慎。例如firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 8080 -j ACCEPT会绕过zone机制导致规则在重载后丢失。生产环境应坚持--permanent参数确保配置持久化。3.3 服务富集将自定义应用注册为firewalld服务当部署Nginx、Redis等非标准服务时直接开放端口存在管理隐患。firewalld支持服务富集service enrichment将应用抽象为可复用的服务单元# 创建服务定义文件 cat /etc/firewalld/services/nginx-custom.xml EOF ?xml version1.0 encodingutf-8? service shortNginx Custom/short descriptionHigh-performance web server with custom SSL port/description port protocoltcp port443/ port protocoltcp port8080/ module namenf_conntrack_ftp/ /service EOF # 重载firewalld服务列表 firewall-cmd --reload # 在public区域启用该服务 firewall-cmd --permanent --zonepublic --add-servicenginx-custom firewall-cmd --reload此方案优势显著服务定义集中管理--add-service命令自动处理端口模块依赖且可通过firewall-cmd --info-servicenginx-custom查看完整配置。相比硬编码端口它提升了配置可读性与可维护性。4. SELinux策略调优从禁用陷阱到精准布尔值控制4.1 SELinux的三种模式辨析与生产选择Rocky Linux 9.1默认启用SELinux的enforcing模式但许多管理员第一反应是setenforce 0临时禁用——这埋下了严重隐患。SELinux有三种运行模式Enforcing强制执行策略拒绝违规操作并记录日志/var/log/audit/audit.logPermissive记录违规但不阻止用于策略调试Disabled完全关闭SELinux需重启生效修改/etc/selinux/config生产环境绝对禁止disabled模式它不仅削弱安全防护更导致某些服务如httpd、postgresql因缺少SELinux上下文而无法启动。正确做法是保持enforcing通过sealert工具分析拒绝日志# 安装诊断工具 dnf install setroubleshoot-server -y # 查看最近的SELinux拒绝事件 sealert -a /var/log/audit/audit.log | head -20sealert会生成可读性报告例如SELinux is preventing /usr/sbin/httpd from name_bind access on the tcp_socket. For complete SELinux messages run: sealert -l 123abc... Allow access by executing: setsebool -P httpd_can_network_bind 14.2 关键布尔值实操解决高频服务冲突SELinux通过布尔值boolean开关控制策略宽松度。以下是最常调整的五个布尔值及其适用场景布尔值默认值适用场景调整命令httpd_can_network_bindoffApache/Nginx绑定非标准端口如8080setsebool -P httpd_can_network_bind 1samba_export_all_rooffSamba共享只读目录setsebool -P samba_export_all_ro 1postgresql_selinux_user_readoffPostgreSQL读取用户家目录数据setsebool -P postgresql_selinux_user_read 1container_manage_cgroupoffDocker容器管理cgroup资源setsebool -P container_manage_cgroup 1virt_sandbox_use_fusefsoffKVM虚拟机使用FUSE文件系统setsebool -P virt_sandbox_use_fusefs 1注意-P参数表示永久生效写入/etc/selinux/targeted/modules/active/booleans.local无此参数则重启后失效。执行getsebool -a | grep httpd可查看所有httpd相关布尔值。4.3 自定义策略模块解决特殊应用权限需求当标准布尔值无法满足需求时如自定义Python服务需访问/opt/app/logs需编写SELinux策略模块。以myapp服务为例# 1. 收集拒绝日志运行应用触发SELinux拒绝 ausearch -m avc -ts recent | audit2why # 2. 生成策略模块 ausearch -m avc -ts recent | audit2allow -M myapp-policy # 3. 安装模块 semodule -i myapp-policy.pp # 4. 验证模块加载 semodule -l | grep myapp生成的myapp-policy.te文件内容类似module myapp-policy 1.0; require { type httpd_t; type var_log_t; class file { read write getattr }; } # Allow httpd_t to write to var_log_t allow httpd_t var_log_t:file { read write getattr };此过程将临时拒绝转化为永久策略比全局禁用SELinux安全数个数量级。策略模块可打包分发实现团队间安全策略标准化。5. DNF包管理进阶从基础更新到离线仓库构建5.1 DNF核心命令的生产级用法DNFDandified YUM是Rocky Linux 9.1的默认包管理器其设计哲学是“事务安全”。关键命令需掌握深层用法安全更新dnf update --security仅升级含CVE修复的包避免非安全更新引入兼容性风险版本锁定dnf versionlock kernel防止内核自动升级导致驱动不兼容依赖分析dnf repoquery --whatrequires nginx查找所有依赖Nginx的包用于卸载评估包来源追溯dnf list installed | grep nginx显示包版本及仓库来源如appstream、baseos特别注意dnf distro-sync命令它将系统所有包同步至仓库最新版本相当于apt full-upgrade但需谨慎使用——生产环境建议先在测试机执行再结合dnf history回滚# 查看最近操作 dnf history # 回滚到指定ID如ID15 dnf history undo 155.2 构建离线YUM仓库解决无外网环境部署当服务器处于隔离网络时需构建本地仓库。以同步baseos和appstream仓库为例# 1. 在有外网的机器上创建仓库目录 mkdir -p /mnt/rocky9-repo/{baseos,appstream} # 2. 同步仓库需安装dnf-plugins-core dnf install dnf-plugins-core -y dnf reposync --reporocky-baseos --download-metadata --downloadcomps --download-as-root -p /mnt/rocky9-repo/baseos dnf reposync --reporocky-appstream --download-metadata --downloadcomps --download-as-root -p /mnt/rocky9-repo/appstream # 3. 生成仓库元数据 createrepo_c -v /mnt/rocky9-repo/baseos createrepo_c -v /mnt/rocky9-repo/appstream # 4. 将/mnt/rocky9-repo复制到目标服务器 # 5. 配置本地仓库文件 cat /etc/yum.repos.d/local.repo EOF [local-baseos] nameLocal Rocky 9 BaseOS baseurlfile:///mnt/rocky9-repo/baseos gpgcheck0 enabled1 [local-appstream] nameLocal Rocky 9 AppStream baseurlfile:///mnt/rocky9-repo/appstream gpgcheck0 enabled1 EOF # 6. 清理缓存并验证 dnf clean all dnf makecache dnf repolist此方案优势在于完全离线、版本可控、无网络延迟。--downloadcomps参数下载软件包组如Development Tools--download-metadata确保元数据完整避免dnf groupinstall失败。5.3 DNF插件实战增强包管理能力DNF通过插件扩展功能以下三个插件在生产中不可或缺dnf-plugin-post-transaction-actions在事务完成后执行脚本如更新内核后自动更新GRUB# 启用插件 echo post_transaction_actions 1 /etc/dnf/plugins/post-transaction-actions.conf # 创建动作脚本 cat /etc/dnf/plugins/actions.d/update-grub.action EOF [update-grub] command /bin/sh -c grubby --update-kernelALL --argsrhgb quiet EOFdnf-plugin-system-upgrade执行大版本升级如Rocky 9.1→9.2dnf install dnf-plugin-system-upgrade -y dnf system-upgrade download --releasever9.2 dnf system-upgrade rebootdnf-plugin-config-manager动态管理仓库需启用dnf config-manager --set-enabled crb # 启用CodeReady Builder仓库 dnf config-manager --set-disabled epel # 禁用EPEL这些插件将DNF从单纯包安装器升级为系统生命周期管理平台是Rocky Linux 9.1现代化运维的关键组件。6. 综合排障一个真实故障的完整诊断链上周处理了一起典型故障Rocky Linux 9.1服务器能ping通网关但无法访问外部网站curl https://google.com超时。按常规思路排查发现firewalld和NetworkManager均正常最终定位到SELinux与DNF的隐性交互问题。以下是完整的诊断链6.1 网络层验证确认基础连通性首先排除物理层问题# 检查接口UP状态 ip link show ens192 | grep state UP # 验证ARP解析 ip neigh show | grep 192.168.10.1 # 测试网关ICMP ping -c 3 192.168.10.1 # 成功 # 测试DNS服务器 dig 8.8.8.8 google.com short # 超时DNS解析失败指向网络层或DNS配置问题。6.2 DNS配置溯源发现NetworkManager的隐藏行为检查/etc/resolv.confcat /etc/resolv.conf # 输出 # Generated by NetworkManager nameserver 127.0.0.1NM默认启用dnsmasq本地DNS缓存但该服务未运行。systemctl status dnsmasq显示inactive (dead)。问题根源浮现NM配置了ipv4.dns但未启用dnsmasq导致resolv.conf指向不存在的本地DNS。解决方案# 方案A禁用dnsmasq直连上游DNS nmcli connection modify Prod-Static ipv4.dns 8.8.8.8,114.114.114.114 \ ipv4.ignore-auto-dns yes nmcli connection down Prod-Static nmcli connection up Prod-Static # 方案B启用dnsmasq需安装 dnf install dnsmasq -y systemctl enable --now dnsmasq6.3 SELinux深度介入DNS查询被拦截采用方案A后dig 8.8.8.8 google.com仍超时。启用permissive模式测试setenforce 0 dig 8.8.8.8 google.com short # 立即返回结果 setenforce 1确认SELinux拦截。分析审计日志ausearch -m avc -ts recent | audit2why # 输出 # typeAVC msgaudit(1712345678.123:456): avc: denied { name_connect } for pid12345 commdig path/dev/udp scontextsystem_u:system_r:unconfined_service_t:s0 tcontextsystem_u:object_r:port_t:s0 tclassudp_socket permissive0audit2why建议setsebool -P nis_enabled 1但nis_enabled与此无关。深入分析发现dig进程类型为unconfined_service_t而UDP socket访问被拒绝。正确解决方案是# 允许unconfined_service_t访问网络 setsebool -P unconfined_service_connect_network 16.4 DNF仓库同步异常连锁反应的起点最终追溯到故障源头管理员曾执行dnf update但因网络波动中断。DNF残留的锁文件导致dnf makecache失败进而使NM无法从仓库获取DNS配置模板。清理步骤rm -f /var/cache/dnf/*.sqlite* dnf clean all dnf makecache此案例揭示了Rocky Linux 9.1各组件的强耦合性NetworkManager依赖DNF元数据生成DNS配置SELinux策略控制DNS查询权限firewalld管理DNS端口放行。单一故障点会引发多米诺骨牌效应。最后分享一个小技巧在生产环境部署前务必执行rocky-release-check需安装rocky-release包验证系统完整性。该工具检查SELinux状态、firewalld配置、NetworkManager服务及DNF仓库健康度输出可操作的修复建议比人工排查效率提升十倍。