结论: 服务器防火墙的正确配置是"双层防御 + 默认拒绝":云安全组做外层粗粒度过滤,系统内用 ufw(Ubuntu/Debian)、firewalld(CentOS/RHEL 系)或 iptables 做细粒度控制,策略一律设为默认拒绝入站、按需放行。同时必须给 SSH 加限速或接入 fail2ban,并在启用前先放行 22 端口防止把自己锁在门外。
引言:防火墙不是"开了就行"
很多服务器的防火墙状态是"装了但等于没装"——要么默认策略是 ACCEPT,几百条放行规则里躺着 3306、6379;要么 ufw 和 firewalld 同时运行,规则互相覆盖;还有一类更隐蔽:开了 ufw,但 Docker 映射的端口照样能被公网访问。
配置防火墙的目标不是"阻止所有流量",而是最小化暴露面:只开放业务必需的端口,只对必要的来源 IP 开放,对管理类端口(SSH、数据库)做限速与源限制。本文给出可直接落地的配置模板。示例系统为 Ubuntu 24.04 LTS 与 Rocky Linux 9(截至 2026 年均为主流 LTS 版本)。
防火墙方案怎么选?
先给结论:先选系统自带的默认工具,不要为了"统一"强行混用。
| 工具 | 底层 | 适用系统 | 优点 | 缺点 |
|---|---|---|---|---|
| ufw | iptables/nftables | Ubuntu、Debian | 语法最简,适合单机 | 复杂规则表达能力弱 |
| firewalld | nftables(默认) | RHEL、CentOS、Rocky、AlmaLinux | 支持 zone 与动态重载,无需断连 | 概念偏多 |
| iptables | netfilter | 通用 | 控制最精细,脚本化方便 | 规则顺序敏感,易出错 |
| nftables | nftables | 新发行版 | 语法统一,性能好 | 学习成本较高 |
| 云安全组 | 虚拟化层 | 所有云服务器 | 独立于系统,系统被攻破仍生效 | 粒度较粗,无连接状态跟踪 |
关键原则:只启用其中一种系统防火墙工具。 同时跑 ufw 和 firewalld 会导致规则集互相覆盖,排查起来极其痛苦。检查与清理:
sudo ufw status # Status: inactive 才是关闭
sudo systemctl is-active firewalld
sudo iptables -L -n | head -20 # 看现有规则是否被某个工具接管第一步:先配云安全组(第一道防线)
结论:安全组在虚拟化层过滤,即使系统被攻破、系统防火墙被清空,它依然生效,是最可靠的一道防线。
配置要点:
- 入站默认拒绝,逐条添加放行规则,而不是"默认全放再补黑名单"。
- SSH(22)的授权对象填运维出口 IP 段,不要
0.0.0.0/0。 - Web 端口(80/443)可对全网开放。
- 数据库、缓存、注册中心端口不要出现在安全组里,走内网或 SSH 隧道。
- 出方向一般默认全放,但高安全场景应限制出站,防止被控主机外连 C2 服务器。
第二步:ufw 实战(Ubuntu / Debian)
结论:ufw 的策略是"默认拒绝 + 显式放行",加上自带的 limit 语法可以一行搞定 SSH 防暴力破解。
sudo apt install -y ufw
# 1) 默认策略
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 2) 务必先放行 SSH —— 改过端口就填改后的端口
sudo ufw limit 22/tcp comment 'SSH rate limit' # limit 会在 30 秒内超过 6 次连接时拒绝
# 或者限定来源 IP
sudo ufw allow from 203.0.113.5 to any port 22 proto tcp
# 3) Web 服务
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
# 4) 需要的话放行自定义业务端口
sudo ufw allow 8080/tcp comment 'app'
# 5) 允许内网网段访问数据库(注意只限内网网卡)
sudo ufw allow in on eth1 from 10.0.0.0/8 to any port 3306 proto tcp
# 6) 启用
sudo ufw enable
sudo ufw status verbose日常管理命令:
sudo ufw status numbered # 带编号列出,方便删除
sudo ufw delete 4 # 按编号删除规则
sudo ufw insert 1 allow from 203.0.113.0/24 to any port 22 proto tcp # 插到最前
sudo ufw reload
sudo ufw app list # 查看预定义的应用配置(OpenSSH、Nginx Full 等)ufw 的规则文件在 /etc/ufw/user.rules 与 /etc/ufw/user6.rules,备份时直接复制这两个文件即可。
第三步:firewalld 实战(RHEL 系)
结论:firewalld 的核心是 zone(区域):网卡属于哪个 zone 就应用哪套规则。默认网卡多在 public zone,最安全的做法是把管理类服务单独放到受信任来源里。
sudo systemctl enable --now firewalld
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all
# 把默认 zone 设为 public,并只放行必要服务
sudo firewall-cmd --set-default-zone=public
sudo firewall-cmd --permanent --remove-service=dhcpv6-client
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=8080/tcp
# 端口转发:把 80 的访问转到本机 8080(需开启 masquerade 才能跨机)
sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
sudo firewall-cmd --reload
sudo firewall-cmd --list-all用 rich rule 做精细化控制,这是 firewalld 最强大的部分:
# 只允许指定 IP 访问 SSH
sudo firewall-cmd --permanent --zone=public --add-rich-rule='
rule family="ipv4" source address="203.0.113.5/32"
service name="ssh" log prefix="ssh-accept" level="info" accept'
# 对 SSH 做速率限制:每分钟超过 4 次新连接就拒绝
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4" service name="ssh"
limit value="4/m" accept'
# 直接封禁某个 IP 段
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4" source address="198.51.100.0/24" drop'
sudo firewall-cmd --reload第四步:iptables 实战(通用且最可控)
结论:iptables 的规则按顺序匹配、命中即停,因此放行规则必须写在 DROP 之前。下面是一份可直接使用的生产级脚本,含状态跟踪、SSH 限速、ICMP 限速与丢弃日志。
sudo tee /usr/local/sbin/fw-init.sh <<'EOF'
#!/bin/bash
# 基础防火墙初始化:默认拒绝入站,按需放行
iptables -F
iptables -X
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# 1) 回环与已建立的连接必须放通
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# 2) SSH 限速:60 秒内新连接超过 5 次即丢弃(防暴力破解)
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --set --name SSHPOOL
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --update --seconds 60 --hitcount 5 --rttl --name SSHPOOL -j DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 3) Web 服务
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 4) 允许被 ping,但限速防 ICMP Flood
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/s -j ACCEPT
# 5) SYN Flood 缓解
iptables -A INPUT -p tcp --syn -m limit --limit 20/s --limit-burst 30 -j ACCEPT
# 6) 丢弃前记录日志(务必限速,否则日志会刷爆磁盘)
iptables -A INPUT -m limit --limit 5/min -j LOG \
--log-prefix "IPT-DROP: " --log-level 4
iptables -A INPUT -j DROP
EOF
sudo chmod +x /usr/local/sbin/fw-init.sh
sudo /usr/local/sbin/fw-init.sh
sudo iptables -L -n -v --line-numbers执行前先在云控制台开好 VNC 通道。如果规则有误导致 SSH 断开,可用 VNC 登录后执行 iptables -P INPUT ACCEPT 恢复。
持久化:
# Debian / Ubuntu
sudo apt install -y iptables-persistent
sudo netfilter-persistent save # 写入 /etc/iptables/rules.v4 与 rules.v6
# 通用手工保存与恢复
sudo iptables-save | sudo tee /etc/iptables/rules.v4
sudo iptables-restore < /etc/iptables/rules.v4第五步:用 fail2ban 自动封禁扫描源
结论:防火墙的规则是静态的,fail2ban 是动态的——它通过扫描日志识别失败登录,超过阈值就临时把来源 IP 加入防火墙黑名单,是防暴力破解(Brute Force)的标配。
sudo apt install -y fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local编辑 /etc/fail2ban/jail.local:
[DEFAULT]
bantime = 3600 # 封禁 1 小时
findtime = 600 # 统计窗口 10 分钟
maxretry = 3 # 失败 3 次即封
ignoreip = 127.0.0.1/8 203.0.113.5 # 白名单,务必加上自己的出口 IP
backend = systemd
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400 # SSH 封 24 小时
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.logsudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd # 查看被封 IP 数
sudo fail2ban-client set sshd unbanip 198.51.100.7 # 误封时解封
sudo tail -f /var/log/fail2ban.log
企业QQ咨询




