Linux防火墙实战:firewalld与ufw配置Web与SSH安全策略

发布时间:2026/6/26 18:34:35
Linux防火墙实战:firewalld与ufw配置Web与SSH安全策略 1. 项目概述为什么防火墙配置是Linux运维的必修课在Linux服务器上部署Web服务或开启SSH远程管理就像是在自家院子里开了一家店铺并留了一扇后门。店铺Web服务需要开门迎客让来自互联网的访客能够访问你的网站后门SSH服务则只允许你信任的管理员进出进行维护和更新。防火墙就是那个站在门口手持名单和规则手册的“保安”。它的核心任务不是简单地“一关了之”而是执行精细化的“访问控制”决定谁可以进、从哪个门进、以及能进到多深。很多新手管理员容易陷入两个极端要么图省事直接关闭防火墙让服务器完全暴露在公网风险之下要么设置过于严苛的策略一不小心连自己都锁在门外。今天我们就来实战演练如何为最常见的Web服务器如Nginx/Apache和SSH远程服务配置一套既安全又实用的防火墙规则。无论你用的是CentOS/RHEL系列的firewalld还是Debian/Ubuntu系列的ufw甚至是更底层的iptables其核心思想都是相通的。我们将从需求分析开始逐步深入到具体命令和策略设计并分享我多年来在真实生产环境中总结的避坑指南。2. 核心防火墙技术选型与基础概念解析在动手之前我们必须搞清楚手上有哪些工具以及它们各自的定位。Linux世界的防火墙方案主要有三代演进。2.1 iptables经典但复杂的底层基石iptables是Linux内核中Netfilter框架的用户空间命令行工具它直接操作内核中的规则表是绝大多数Linux防火墙方案的底层基础。它的功能无比强大但规则语法也相对复杂需要管理员对网络协议有较深的理解。其规则结构可以概括为“四表五链”四张表Tablesfilter过滤最常用、nat网络地址转换、mangle包修改、raw连接跟踪。五条内置链ChainsINPUT处理到本机的数据包、OUTPUT处理从本机发出的数据包、FORWARD处理经过本机转发的数据包、PREROUTING、POSTROUTING。一条典型的iptables命令看起来像这样iptables -A INPUT -p tcp --dport 80 -j ACCEPT。这条命令的意思是在INPUT链的末尾追加-A一条规则对于TCP协议-p tcp目标端口为80--dport 80的数据包执行接受-j ACCEPT动作。虽然强大但直接管理iptables规则集尤其是在频繁变更时容易出错且难以维护。2.2 firewalldRHEL/CentOS/Fedora的现代守护进程firewalld是Red Hat系列发行版在RHEL 7/CentOS 7及以后版本中引入的动态防火墙管理器。它并不是iptables的替代品而是一个位于其之上的配置管理前端。它的核心优势在于“动态”和“区域”概念。动态管理firewalld作为一个守护进程运行规则的修改无需重启服务即可立即生效且不会中断现有连接。区域Zone这是一个极其好用的抽象概念。你可以为不同的网络接口或源IP地址分配不同的“区域”。例如将连接公司内网的eth0接口放在“trusted”信任区域允许所有流量将连接公网的eth1接口放在“public”公共区域只开放必要的服务。这大大简化了多网络环境下的策略管理。服务Servicefirewalld预定义了大量常见的服务如http、https、ssh这些服务本质上是一个端口和协议组合的别名。直接放行服务比记忆端口号更直观。2.3 ufw为人类设计的Uncomplicated Firewall如果你是Debian、Ubuntu或其衍生版的用户那么ufwUncomplicated Firewall是你的首选。正如其名它的设计目标就是简化防火墙配置。它同样是iptables的一个前端但提供了极其简洁的命令行接口。对于大多数单机服务器应用场景ufw提供的功能已经完全足够且极大地降低了学习成本和配置出错的风险。它的基本逻辑就是“默认拒绝按需放行”。选择建议对于新手和追求简洁高效的场景首选ufw对于运行在Red Hat生态下的服务器或者需要复杂多区域策略的环境firewalld是更集成的选择而当你需要实现非常定制化、精细到数据包级别的控制时才需要直接深入iptables。本次指南将重点覆盖firewalld和ufw的实战配置。3. 实战配置为Web服务器配置防火墙规则假设我们在一台新安装的CentOS 8服务器上部署了Nginx监听80HTTP和443HTTPS端口。我们的目标是允许全世界访问这两个端口同时禁止其他所有不必要的入站连接。3.1 使用firewalld配置Web服务首先确认firewalld正在运行sudo systemctl status firewalld如果未运行则启用并启动它sudo systemctl enable --now firewalld。默认情况下firewalld的public区域是激活的且默认策略是拒绝所有入站连接允许所有出站连接。这是一个非常安全的起点。步骤一查看当前区域和规则sudo firewall-cmd --list-all这会输出当前默认区域通常是public的详细配置包括接口、允许的服务、端口等。初始状态下允许的服务列表很可能是空的。步骤二将HTTP和HTTPS服务添加到永久规则firewalld的修改分为运行时--runtime和永久--permanent。运行时修改立即生效但重启后丢失永久修改写入配置但需要重载或重启服务才生效。生产环境建议直接使用--permanent然后重载。# 添加http服务端口80 sudo firewall-cmd --permanent --add-servicehttp # 添加https服务端口443 sudo firewall-cmd --permanent --add-servicehttps步骤三重载防火墙配置使永久规则生效sudo firewall-cmd --reload步骤四验证规则再次运行sudo firewall-cmd --list-all你应该在services:后面看到http https。也可以使用--list-services专门查看服务。实操心得firewalld的--permanent标志是关键。很多人在测试时只用运行时命令不加--permanent测试通过后忘了保存结果服务器一重启防火墙规则恢复原样服务无法访问排查半天才发现是规则没持久化。我的习惯是除非是紧急的临时调试否则一律使用--permanent参数并紧跟--reload。3.2 使用ufw配置Web服务在Ubuntu 22.04 LTS上操作更为直观。步骤一启用ufw默认情况下ufw是禁用的。首先启用它但在这之前务必确保SSH端口已被允许否则你可能被锁在服务器外。# 先允许SSH默认端口22这是你的生命线 sudo ufw allow ssh # 或者如果你自定义了SSH端口例如2222 # sudo ufw allow 2222/tcp # 现在可以安全地启用ufw了 sudo ufw enable系统会提示你“命令可能会中断现有的ssh连接”因为你已经提前放行了SSH所以可以输入y确认。步骤二放行HTTP和HTTPSsudo ufw allow http sudo ufw allow httpsufw同样预定义了http和https服务别名。步骤三查看规则状态sudo ufw status verbose这个命令会输出详细的防火墙状态显示默认策略Default: deny (incoming), allow (outgoing), disabled (routed)以及当前生效的规则列表。你应该能看到类似下面的行To Action From -- ------ ---- 22/tcp (SSH) ALLOW IN Anywhere 80/tcp (HTTP) ALLOW IN Anywhere 443/tcp (HTTPS) ALLOW IN Anywhere4. 深度安全SSH远程服务加固配置指南SSH是服务器管理的生命线也是最常被攻击的目标。粗暴地完全开放22端口无异于在公网上“裸奔”。我们必须对其进行加固。4.1 基础安全措施更改端口与限制源IP措施一修改默认SSH端口攻击者通常使用自动化工具扫描全网段的22端口。修改为一个高位端口如2222能立即过滤掉绝大部分无目标的自动化扫描。编辑SSH配置文件sudo vim /etc/ssh/sshd_config找到#Port 22这一行去掉注释#并将22改为你想要的端口例如Port 2222。你可以保留Port 22并新增一行Port 2222进行测试但最终应注释掉或删除Port 22。重启SSH服务sudo systemctl restart sshdUbuntu/Debian或sudo systemctl restart sshdRHEL/CentOS。重要在重启sshd前必须先在防火墙中放行新端口并确保你有一个保持活动的SSH连接用于测试新端口或者通过控制台操作。否则你会把自己关在门外。措施二使用防火墙限制SSH访问源绝对不要允许0.0.0.0/0即全世界访问你的SSH端口。只允许来自可信IP地址段的连接例如你的办公室IP或家庭宽带IP注意家庭宽带IP可能会变。使用firewalld# 假设你的可信IP是 203.0.113.100 sudo firewall-cmd --permanent --remove-servicessh # 先移除默认的ssh服务规则放行22端口 sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address203.0.113.100 port port2222 protocoltcp accept sudo firewall-cmd --reload使用ufwsudo ufw delete allow ssh # 删除之前允许的任何IP访问22端口的规则 sudo ufw allow from 203.0.113.100 to any port 2222 proto tcp sudo ufw reload4.2 进阶加固密钥认证与Fail2ban联动措施三禁用密码认证强制使用密钥对密码可能被暴力破解或撞库而密钥对公钥加密私钥解密在数学上几乎不可破解。在本地机器生成密钥对ssh-keygen -t ed25519 -C your_emailexample.com推荐ed25519算法更快更安全。将公钥上传到服务器ssh-copy-id -p 2222 useryour_server_ip。测试使用密钥登录成功后编辑服务器上的/etc/ssh/sshd_configPasswordAuthentication no PubkeyAuthentication yes重启sshd服务。措施四部署Fail2ban主动防御Fail2ban会监控系统日志如/var/log/auth.log当发现同一个IP在短时间内多次SSH登录失败后会自动调用防火墙iptables/firewalld将该IP临时封禁一段时间。安装Fail2bansudo apt install fail2ban(Ubuntu) /sudo yum install fail2ban(CentOS)。复制默认配置文件sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local。编辑jail.local找到[sshd]段落进行关键配置[sshd] enabled true port 2222 # 改为你的SSH端口 filter sshd logpath /var/log/auth.log # Ubuntu路径CentOS通常是 /var/log/secure maxretry 5 # 最大尝试次数 bantime 3600 # 封禁时间秒这里是一小时 findtime 600 # 在10分钟内达到maxretry则封禁启动并启用Fail2bansudo systemctl enable --now fail2ban。避坑指南配置SSH安全策略时最危险的莫过于把自己锁在外面。我的标准操作流程是1) 通过控制台或确保有一个永不退出的screen/tmux会话。2) 先配置防火墙放行新端口和可信IP。3) 修改sshd_config但先不重启服务。4) 新开一个终端窗口用新端口和密钥或密码尝试登录确保成功。5) 回到第一个会话重启sshd。6) 再次用新会话测试登录。7) 一切正常后再回来关闭密码认证。这个“测试-确认-再应用”的循环至关重要。5. 高级策略与生产环境常见问题排查当Web和SSH服务运行一段时间后你可能会遇到一些复杂场景和问题。5.1 多网卡与区域绑定firewalld高级应用服务器有两张网卡eth0内网IP192.168.1.10用于内部管理eth1公网IP203.0.113.10用于对外服务。我们希望内网可以任意访问所有服务包括SSH而公网只开放Web端口。为网卡分配不同区域sudo firewall-cmd --permanent --zoneinternal --change-interfaceeth0 sudo firewall-cmd --permanent --zonepublic --change-interfaceeth1配置内部区域策略internal区域默认可能没有信任所有流量。我们可以将其源设为信任或者直接添加所有服务。# 方法一将internal区域设置为信任级别类似trusted zone的行为 sudo firewall-cmd --permanent --zoneinternal --set-targetACCEPT # 方法二显式地为internal区域添加服务 sudo firewall-cmd --permanent --zoneinternal --add-servicessh sudo firewall-cmd --permanent --zoneinternal --add-servicehttp sudo firewall-cmd --permanent --zoneinternal --add-servicehttps配置公共区域策略如前所述只放行Web服务。sudo firewall-cmd --permanent --zonepublic --add-servicehttp sudo firewall-cmd --permanent --zonepublic --add-servicehttps # 确保public区域没有ssh服务 sudo firewall-cmd --permanent --zonepublic --remove-servicessh重载配置sudo firewall-cmd --reload。验证分别查看两个区域的配置sudo firewall-cmd --zoneinternal --list-all和sudo firewall-cmd --zonepublic --list-all。5.2 常见问题排查实录即使配置正确网络问题也千奇百怪。下面是一个快速排查清单。问题一本地能访问但外网无法访问Web服务80/443端口。检查点1防火墙规则是否生效firewalld:sudo firewall-cmd --list-all --zonepublic确认http/https服务在列。ufw:sudo ufw status verbose确认规则为ALLOW IN。检查点2服务是否在监听且绑定正确地址sudo ss -tlnp | grep :80和sudo ss -tlnp | grep :443。查看Local Address列。如果显示的是127.0.0.1:80说明服务只监听本地回环需修改Web服务器配置如Nginx的listen指令为0.0.0.0:80或具体公网IP。检查点3云服务商安全组/网络ACL这是最容易被忽略的一点在阿里云、AWS、腾讯云等平台上除了操作系统防火墙还有一层虚拟网络层面的安全组。你必须在那里也放行对应的端口如80/tcp, 443/tcp, 2222/tcp。这个配置在云控制台进行。检查点4上游网络设备检查公司或IDC的出口路由器、硬件防火墙是否有端口限制。问题二SSH使用新端口无法连接。检查点1防火墙是否放行了新端口使用sudo firewall-cmd --list-ports或sudo ufw status仔细核对端口号。检查点2SELinux是否阻止了新端口在RHEL/CentOS上SELinux可能会阻止非标准端口的服务。临时放行sudo semanage port -a -t ssh_port_t -p tcp 2222。安装semanage工具sudo yum install policycoreutils-python-utils。检查点3ssh服务配置是否正确确认/etc/ssh/sshd_config中的Port指令已正确设置且未被注释。重启服务后用sudo systemctl status sshd查看是否有错误。检查点4本地客户端命令是否正确连接时指定端口ssh -p 2222 userserver_ip。问题三添加了IP限制后自己也被挡在外面。原因你的出口公网IP地址可能发生了变化家庭宽带动态IP、移动网络等。应急方案通过云平台的控制台VNC/串口登录服务器暂时将防火墙规则放宽或者添加你当前的新IP。根治方案考虑使用VPN接入服务器所在的内网然后通过内网IP进行SSH管理这样就不需要将SSH暴露在公网也无需频繁更新IP白名单。或者使用零信任网络访问解决方案。问题四firewalld规则混乱想恢复默认状态。警告此操作会清除所有自定义规则可能导致服务中断。务必在业务低峰期或通过控制台操作。# 重置所有配置到安装时的状态 sudo firewall-cmd --reset-to-defaults sudo firewall-cmd --reload对于ufw可以禁用后重新配置sudo ufw disable然后从头开始sudo ufw enable并一条条添加规则。防火墙配置是一个“安全”与“便利”不断权衡的过程。没有一劳永逸的策略需要根据业务变化和安全态势持续调整。我的习惯是任何防火墙规则的变更都记录在运维文档或配置管理系统中并且先在测试环境验证再在业务低峰期应用于生产环境。每次修改后用nmap等工具从外部扫描一下确认开放的端口符合预期没有意外的“后门”被打开。记住防火墙是你的第一道也是最重要的一道防线值得你花时间把它配置得恰到好处。