Linux 防火墙实战:iptables 与 firewalld 从入门到加固网站服务器

很多个人站长买了云服务器之后,第一件事就是装 Nginx、MySQL、PHP,网站跑起来了就觉得万事大吉。直到有一天发现服务器被暴力破解、被扫描器扫出奇怪的端口,或者 SSH 登录日志里全是陌生 IP,才想起还有防火墙这回事。说实话,云厂商的安全组只是云平台层面的第一道过滤,服务器系统自带的防火墙才是真正贴身的那道防线。这篇文章用实际操作把 iptables 和 firewalld 讲清楚,从基本概念到网站服务器的加固配置,全部命令都是我在自己的 VPS 上验证过的。

一、先搞清楚 iptables 的基本概念

iptables 是 Linux 内核 netfilter 框架的命令行管理工具,本质上就是在内核层面维护一组规则,决定数据包是放行、拒绝还是丢弃。理解 iptables 只需要抓住三个关键词:表、链、规则。

表(table)按功能划分,最常见的是 filter 表(负责过滤)、nat 表(负责地址转换)和 mangle 表(负责修改数据包)。站长日常用的 95% 都是 filter 表。

链(chain)是规则的集合,filter 表里有三条内置链:INPUT 链处理进入本机的数据包,OUTPUT 链处理本机发出的数据包,FORWARD 链处理经过本机转发的数据包。个人网站服务器主要关心 INPUT 链,也就是"谁想访问我这台机器"。

规则(rule)就是一条条的条件判断,从上往下匹配,命中之后执行动作(ACCEPT 放行、DROP 丢弃、REJECT 拒绝),然后停止继续匹配。记住这个顺序很重要,因为写防火墙规则其实就是把规则按优先级排好队。

查看当前规则用这个命令:

iptables -L -n --line-numbers

-L 表示列出规则,-n 表示不解析域名直接显示 IP,--line-numbers 显示行号,方便后面按行号删除规则。刚装好的 CentOS 或者 Debian 系统上,默认规则可能是一条空的链,也就是什么都不限制,所有端口对外开放。

二、iptables 常用命令实战

先看一个最典型的小站加固方案:只允许 SSH(22 端口)、HTTP(80)、HTTPS(443)进入,其他入站请求全部拒绝。逐条执行:

# 先清空默认规则,从干净状态开始
iptables -F
iptables -X

# 设置默认策略:入站拒绝,出站放行
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 允许回环接口(本机内部通信必须放行)
iptables -A INPUT -i lo -j ACCEPT

# 允许已建立的连接和关联连接继续通信
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 放行 SSH、HTTP、HTTPS
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 允许 ICMP(ping 用于排障,可以视情况去掉)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

执行完之后可以再运行 iptables -L -n 查看,三条放行规则加上默认拒绝,网站的 80/443 端口正常,其余端口全部进不来。这里特别提醒一句:默认策略改成 DROP 之前,一定要先把 22 端口的放行规则加上,否则 SSH 一断,你连服务器都进不去了,只能去云控制台用 VNC 救。

如果你只想针对某个 IP 封禁,比如日志里发现某个 IP 在疯狂扫描:

iptables -A INPUT -s 1.2.3.4 -j DROP

想封禁一个网段就写 1.2.3.0/24。想限制某个 IP 的并发连接数,防止被单点拖垮:

iptables -A INPUT -p tcp --dport 80 -s 1.2.3.4 -m connlimit --connlimit-above 20 -j REJECT

删除规则用 -D 加上完整规则,或者用 -L -n --line-numbers 查到行号后 iptables -D INPUT 5 这种按行号删的方式,新手更不容易出错。

三、规则保存:不保存等于白配

iptables 最大的坑就在这里:命令行里加的规则都是临时的,重启服务器或者重启 iptables 服务之后全部消失。我见过不止一个站长配了半天防火墙,重启一次全没了,还以为是系统问题。

Debian/Ubuntu 系统用 iptables-persistent 保存:

apt install -y iptables-persistent
netfilter-persistent save

CentOS 7 及以上的传统做法是:

yum install -y iptables-services
service iptables save

保存之后规则会写入 /etc/iptables/rules.v4 或者 /etc/sysconfig/iptables,开机自动加载。验证保存是否生效,可以重启后直接 iptables -L -n 看规则还在不在。

四、firewalld 入门:CentOS 上的默认防火墙

CentOS 7 开始系统默认带的是 firewalld,它本身仍然基于 iptables/netfilter,只是提供了一套更友好的 zone(区域)管理方式。firewalld 把不同的信任级别划分成 zone,比如 public 区域表示不可信的外部网络,home 区域表示可信的家庭网络,默认网卡属于 public。

常用命令非常直观:

# 查看默认区域和当前规则
firewall-cmd --get-default-zone
firewall-cmd --list-all

# 永久放行 80、443 端口(--permanent 表示写入配置)
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=443/tcp
firewall-cmd --reload

# 放行服务(firewalld 内置了常见服务的定义)
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload

# 移除端口
firewall-cmd --permanent --remove-port=80/tcp
firewall-cmd --reload

注意 --permanent 参数:不加它只对当前会话生效,加了它才写入永久配置,但不会立即生效,必须执行 firewall-cmd --reload 重新加载。这两个动作配合错了,是新手最常见的困惑来源。

如果网站跑在 Docker 容器里,情况会变得复杂:Docker 默认会往 iptables 的 DOCKER 链里写规则做端口映射,firewalld 的拦截规则有时候管不住容器映射出来的端口。遇到这种情况,建议在 firewalld 的 rich rule 里显式控制,或者直接把容器端口范围管理交给 Docker 自己的网络策略,再配合云安全组做外层限制,双保险。

五、网站服务器加固的完整思路

光有防火墙还不够,个人站长的服务器加固应该是组合拳。我自己常用的顺序是:

第一层:云安全组只放行必要的端口,这是云平台层面的第一道闸门,误操作风险低,还能挡住大部分扫描流量。

第二层:系统防火墙(iptables 或 firewalld)做精细控制,比如只允许某个网段访问 SSH,限制某个端口的并发连接数。

第三层:fail2ban 监控日志,自动封禁反复尝试登录的 IP,配合 SSH 密钥登录,暴力破解基本可以无视。

第四层:应用层加固,比如 Nginx 限制单 IP 请求频率、PHP 禁用危险函数、MySQL 只监听内网地址等。

用 iptables 限制 SSH 只允许公司 IP 段访问,是很多站长会做的高性价比操作:

iptables -A INPUT -p tcp --dport 22 -s 你的办公IP/32 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP

MySQL 只监听内网也是必须的:编辑 /etc/mysql/mysql.conf.d/mysqld.cnf,把 bind-address 改成 127.0.0.1,然后重启 MySQL。这样即使防火墙某天配置丢了,数据库也不会暴露在公网上。

六、常见问题与排错

问题一:配完防火墙网站打不开了。优先检查 80/443 端口的放行规则是否在 DROP 策略之前,规则是顺序匹配的,如果 DROP 写在前面,后面的 ACCEPT 永远不会被命中。用 iptables -L -n --line-numbers 看顺序。

问题二:SSH 连不上了。别慌,去云厂商控制台用 VNC/终端登录,把 22 端口放行规则补上,然后重新保存规则。这也是为什么我强烈建议每配置一步就立即验证一步。

问题三:规则保存了但重启后失效。Debian 系检查 iptables-persistent 是否安装,规则文件是否生成;CentOS 检查 iptables-services 是否安装并 enable 开机自启。

问题四:docker 容器端口外部访问不了。先在宿主机上 iptables -L -n 看 DOCKER 链,确认端口映射规则存在;再确认云安全组放行了对应端口;最后确认 firewalld 没有拦截,三层缺一不可。

问题五:ping 不通但网站正常。多半是 ICMP 被默认策略拒绝了,不影响网站访问,属于正常现象,不用纠结。

问题六:iptables 和 firewalld 到底该用哪个。Debian/Ubuntu 默认不带 firewalld,直接用 iptables 加 iptables-persistent 就很清爽;CentOS 用户建议就用系统自带的 firewalld,命令更直观,管理 zone 和 rich rule 都比手写 iptables 规则省事。两台服务器都装了 Docker 的话,务必意识到容器端口映射会绕过一部分宿主机规则,先在云安全组层面兜底,再逐层排查。

防火墙配置这件事,核心就是"最小开放原则":只开网站真正需要的端口,其他一律拒绝,然后定期检查日志里有没有异常的扫描行为。配好之后,服务器的安全性会有质的提升,半夜被暴力破解的焦虑也能少一大半。另外养成一个好习惯:每次改完规则都顺手把规则导出备份一份,万一服务器出问题重装系统,照着备份把规则还原回来只需要一分钟。

Last modification:August 15th, 2026 at 08:39 am

Leave a Comment