Linux 防火墙实战:iptables 规则配置与 Fail2ban 防暴力破解

为什么系统防火墙值得认真配

不少个人站长买了云服务器之后,只在云厂商控制台配了安全组,系统自带的防火墙从来没动过。实际上安全组和系统防火墙是两道防线:安全组在云平台网络层过滤,管理哪个端口对外放行;iptables 在服务器内核里过滤,能做更细的规则,比如只允许某个 IP 访问某个端口、限制 ICMP 探测、配合 Fail2ban 动态封禁暴力破解的 IP。SSH 端口天天被脚本扫描爆破是服务器上的常态,光靠改端口和强密码还不够,这篇文章把 iptables 的核心用法和 Fail2ban 防爆破配置完整过一遍。

一、iptables 的基本概念

iptables 基于内核的 netfilter 框架,规则组织成"表"和"链"。常用的有四个表:filter 表做包过滤,是日常用的最多的;nat 表做地址转换,端口转发、内网共享上网靠它;mangle 表修改包内容;raw 表处理连接跟踪。每个表里有预定义的链,filter 表最常用的是 INPUT(进入本机的包)、OUTPUT(本机发出的包)、FORWARD(转发的包)。规则的匹配顺序是从上到下,第一条匹配的规则生效,后面相同的规则不会再处理,所以顺序很重要:先放行,最后兜底拒绝。

二、常用查看命令

配置之前先学会查看当前规则:

iptables -L -n -v          # 查看 filter 表所有规则,-n 不做 DNS 反解显示更快
iptables -t nat -L -n -v   # 查看 nat 表
iptables -S                # 以命令形式输出规则,方便复制复用

三、基础规则配置实战

下面是一套适合个人服务器的入门配置,逐个解释。先清空已有规则并设置默认策略:

iptables -F                # 清空规则

iptables -X # 删除自定义链
iptables -P INPUT DROP # 默认拒绝所有进入的包
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT # 出站默认放行

把默认策略设为 DROP 之后,必须先把该放行的放行,否则 SSH 会立刻断开。放行本地回环、已建立的连接和常用端口:

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH,建议改成自己的端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # HTTP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # HTTPS

再限制一下 ICMP,防止别人拿 ping 探测你的服务器存活状态,允许每秒最多一个回显请求:

iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT

如果你的 SSH 只从家里或者办公室访问,可以更进一步,只对固定 IP 放行 22 端口,其他地址一律拒绝,从源头上杜绝爆破:

iptables -A INPUT -p tcp --dport 22 -s 你的固定IP -j ACCEPT

这条规则配合默认 DROP 策略,等于 SSH 端口对公网完全不可见,比改端口、上 Fail2ban 都彻底,缺点是你换了网络环境(比如手机热点)就连不上,适合 IP 固定的站长。

封禁某个恶意 IP,比如 1.2.3.4:

iptables -A INPUT -s 1.2.3.4 -j DROP
iptables -A INPUT -s 1.2.3.0/24 -j DROP # 封整个网段

还想知道到底是谁在被拒绝,可以在规则链最后加一条日志规则,把被丢弃的包记到系统日志里:

iptables -A INPUT -j LOG --log-prefix "iptables-drop: " --log-level 4

这条规则要放在所有放行规则之后,它不拒绝任何包(目标是 LOG),只是把没被前面规则放行的包记录下来,然后在 /var/log/kern.log 里就能看到类似 iptables-drop: IN=eth0 OUT= SRC=1.2.3.4 的记录,配合分析脚本能看出扫描来自哪些网段。注意日志规则会带来一点性能开销,生产环境建议只记录命中率最高的几条规则,不要全局开。

四、规则持久化

iptables 的规则存在内存里,重启服务器就没了,必须做持久化。Debian/Ubuntu 装 iptables-persistent 并保存:

apt install -y iptables-persistent
netfilter-persistent save # 保存当前规则
netfilter-persistent reload # 重新加载

CentOS 7 以上默认用 firewalld 封装了 iptables,CentOS 8 和 Debian 12 则默认用 nftables 作为后端,命令行还叫 iptables 但实际是兼容层,规则同样可以这样保存。另外提醒一句:云服务器如果重启后网络异常,优先检查安全组和 iptables 持久化是否生效。

五、端口转发与 nat 表实战

nat 表最常用的场景是端口转发。想在服务器上把 8080 端口的流量转到本机 80 端口:

iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80

想把公网进来的流量转发给内网另一台机器,比如把 3306 端口转发到内网数据库 192.168.1.10:

iptables -t nat -A PREROUTING -d 公网IP -p tcp --dport 3306 \
-j DNAT --to-destination 192.168.1.10:3306
iptables -A FORWARD -p tcp -d 192.168.1.10 --dport 3306 -j ACCEPT
iptables -t nat -A POSTROUTING -d 192.168.1.10 -p tcp --dport 3306 -j MASQUERADE

第一行把目标地址改写成内网机器,第二行在 FORWARD 链放行转发流量,第三行做源地址伪装让回包能正确回来。这个组合是内网穿透和跳板机的常见玩法,注意开了转发后 FORWARD 链的默认策略如果是 DROP,一定要把对应规则加在拒绝之前。

六、认识一下 nftables

nftables 是 iptables 的下一代替代品,语法更统一,配置是"表-链-规则"的结构。CentOS 8、Rocky Linux、Debian 12 默认就是 nftables。一个最简单的例子:

nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0; policy drop; }
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input tcp dport 22 accept
nft list ruleset

日常维护时如果系统默认是 nftables,直接用 iptables 命令写规则通常也能工作(内核会自动翻译),但混用两套工具容易出混乱,新装的系统建议直接用 nft 语法管理。

七、Fail2ban 防暴力破解实战

iptables 是静态规则,Fail2ban 是动态的:它监控服务的日志文件,发现某个 IP 在短时间内反复认证失败,就自动调用 iptables 把这个 IP 封掉一段时间,到期自动解封。安装和配置:

apt install -y fail2ban
systemctl enable --now fail2ban

不要直接改 jail.conf,升级会被覆盖,在 /etc/fail2ban/jail.local 里写自定义配置。SSH 防爆破是最典型的场景:

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
findtime = 600
bantime = 3600
ignoreip = 127.0.0.1/8 ::1 你的固定IP

含义:10 分钟(findtime=600 秒)内失败 5 次(maxretry=5),封禁 1 小时(bantime=3600 秒)。ignoreip 一定要填上你自己的 IP,否则自己输错几次密码也会被关在门外。注意 logpath 在 CentOS 上是 /var/log/secure,Debian/Ubuntu 是 /var/log/auth.log,写错路径 Fail2ban 不会报错但也不会生效。配完重载并查看状态:

fail2ban-client reload
fail2ban-client status # 列出所有启用的 jail
fail2ban-client status sshd # 查看 sshd 监狱封了哪些 IP

Nginx 也可以防,比如监控访问日志里 404 刷得特别频繁的扫描 IP,在 jail.local 里加一段:

[nginx-scan]
enabled = true
port = http,https
filter = nginx-scan
logpath = /var/log/nginx/access.log
maxretry = 20
bantime = 600

对应的 filter 文件放在 /etc/fail2ban/filter.d/nginx-scan.conf,用正则匹配日志里的状态码和请求频率,Fail2ban 自带的 filter 目录里已经有很多现成模板可以抄。想在被封时收到邮件通知,在 jail.local 的 [DEFAULT] 段加上:

[DEFAULT]
destemail = you@example.com
sender = fail2ban@example.com
mta = sendmail
action = %(action_mwl)s

action_mwl 会发送包含 whois 信息和日志摘要的邮件,方便判断是误封还是真的在被攻击。想自己定义匹配规则,在 /etc/fail2ban/filter.d/ 下新建文件,failregex 用正则匹配日志行, 是 Fail2ban 内置的 IP 提取占位符,比如匹配 Nginx 访问日志里的 404 请求:

[Definition]
failregex = ^<HOST> . "(GET|POST) ." 404
ignoreregex =

写完后在 jail.local 里把 filter 指到新文件,reload 即可生效。日常管理常用的还有几个命令:临时改封禁时长用 fail2ban-client set sshd bantime 86400;批量解封所有 IP 用 fail2ban-client unban --all;查看某个 IP 的封禁记录用 fail2ban-client get sshd banned。误封自己之后别慌,先从 ignoreip 里把 IP 加上,再 unban 解封,然后 reload。

八、验证封禁效果

配置完要真实验证一次:在另一台机器上故意用错误密码连续 SSH 登录 6 次,然后回服务器执行 fail2ban-client status sshd,能看到该 IP 出现在封禁列表里,同时 iptables -L -n 里会出现一条 f2b-sshd 链的 DROP 规则。想手动解封误封的 IP:

fail2ban-client set sshd unbanip 1.2.3.4

九、常见坑汇总

第一,规则顺序:iptables 从上到下匹配,把拒绝规则放在放行规则前面才能生效,比如先 -A INPUT -s 恶意IP -j DROP 再放行 80 端口;第二,Docker 会往 FORWARD 链注入自己的规则,千万别执行 iptables -F 清空规则来"重置",否则所有容器网络直接断掉;第三,IPv6 是另一套规则,用 ip6tables 单独管理,忘了配等于 IPv6 裸奔;第四,改了 iptables 默认策略为 DROP 后,务必先确认 SSH 放行规则已写入再断开当前连接,防止把自己锁在外面;第五,云安全组和系统防火墙是叠加的,端口不通先查安全组,规则没错再查 iptables;第六,firewalld、ufw 这些工具本质是 iptables/nftables 的前端封装,同一台机器不要混用两套工具管理防火墙,否则规则互相覆盖很难排查;第七,不要为了图省事把 3306、6379 这类数据库端口直接暴露公网,数据库端口一旦暴露,爆破脚本几小时内就会找上门,正确做法是安全组只放行自己的 IP,数据库只监听内网地址。

十、总结

iptables 加 Fail2ban 是个人站长性价比最高的安全组合:iptables 负责静态的端口和 IP 管控,Fail2ban 负责动态封禁暴力破解,两者配合能把服务器被扫破的风险降一个量级。配置完成后再加个计划任务每天检查 fail2ban-client status 的封禁数量,异常暴增往往意味着有人在针对你的服务器。

Last modification:September 2nd, 2026 at 07:59 am

Leave a Comment