本指南将带您了解并配置 Linux 中最常用的防火墙工具:UFW 和 iptables,同时涵盖 Fail2ban 自动防御、ipset 地区封锁、Docker 防火墙陷阱及 DDoS 基础防护脚本。通过学习本教程,您可以为 VPS 建立坚实的网络安全防线。
🛡️ 防火墙工作原理
Linux 内核内置了 Netfilter 框架,所有网络数据包在进入/离开系统时都经过它处理。iptables 和 nftables 是操作 Netfilter 规则的用户态工具;UFW 则是 iptables 的简化封装,两者底层相同。防火墙就像忠诚的门卫,根据您设定的规则决定哪些流量可以进出服务器。
数据包流向示意图
← 在此过滤
阻止未授权访问
只开放必要的服务端口,阻止对其他所有端口的访问尝试。
防止端口扫描
使服务器在网络扫描中"隐身",减少成为攻击目标的几率。
限制恶意软件
如果服务器不幸被感染,防火墙可以阻止恶意软件向外连接或传播。
缓解 DDoS 攻击
通过速率限制和连接数控制,在一定程度上缓解小规模攻击。
UFW vs. iptables vs. nftables
- UFW 意为"简单的防火墙",是 Debian/Ubuntu 默认工具。命令接近自然语言,适合 95% 的用户,从这里开始。
- iptables 功能极其强大,直接操作内核 netfilter。语法复杂,学习曲线陡峭,但提供无与伦比的精细控制力。
- nftables iptables 的现代继任者,Debian 10+/Ubuntu 20.04+ 内置。语法更一致,性能更好,新项目推荐使用。
🔥 UFW 简易防火墙
UFW 的设计初衷就是简单易用。下面我们来看如何快速配置它。
第一步:安装并设置默认策略
安装 UFW(如已预装可跳过):
sudo apt update && sudo apt install ufw -y 设置"默认拒绝入站,允许出站"策略:
第二步:放行必要端口并启用
先放行 SSH 端口再启用!在执行 ufw enable 之前务必先 ufw allow SSH端口/tcp,否则开启后会立即断开连接。
UFW 完整命令速查表
| 命令 | 描述 |
|---|---|
| sudo ufw status | 查看 UFW 状态 |
| sudo ufw enable | 启用 UFW |
| sudo ufw disable | 禁用 UFW |
| sudo ufw default deny incoming | 设置默认入站策略为拒绝 |
| sudo ufw default allow outgoing | 设置默认出站策略为允许 |
| sudo ufw allow ssh | 允许 SSH 连接(基于服务名) |
| sudo ufw allow 22/tcp | 同上,按端口号允许 |
| sudo ufw allow http | 允许 HTTP 连接(端口 80) |
| sudo ufw allow 8080/tcp | 允许 TCP 协议的 8080 端口 |
| sudo ufw allow from 1.2.3.4 | 允许特定 IP 的所有连接 |
| sudo ufw allow from 192.168.1.0/24 to any port 3306 | 允许特定子网访问 MySQL |
| sudo ufw limit 22/tcp | 速率限制:30 秒内 >6 次连接则封禁(防爆破) |
| sudo ufw deny 12345/tcp | 拒绝 TCP 协议的 12345 端口 |
| sudo ufw status numbered | 显示带编号的规则列表 |
| sudo ufw delete 1 | 删除编号为 1 的规则 |
| sudo ufw reset | 重置所有规则到初始状态 |
🔗 高级防火墙 iptables
iptables 是 Linux 内核 Netfilter 框架的传统接口,功能极其强大,可以实现 UFW 无法做到的精细控制。
iptables 四表速查
| 表 | 作用 | 常用链 | 典型用途 |
|---|---|---|---|
| filter | 数据包过滤(默认) | INPUT OUTPUT FORWARD | 允许/拒绝端口访问 |
| nat | 网络地址转换 | PREROUTING POSTROUTING | 端口转发、Docker 网络 |
| mangle | 修改数据包头 | 全部5条链 | QoS 流量标记 |
| raw | 跳过连接追踪 | PREROUTING OUTPUT | 高性能抗 DDoS |
基础配置规则集
# 1. 允许本地回环 (重要!)
iptables -A INPUT -i lo -j ACCEPT
# 2. 允许已建立的连接(必须!否则断连)
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# 3. 允许 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
# 4. 允许 ICMP ping
iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT
# 5. 默认拒绝所有其他入站(放在最末尾!)
iptables -P INPUT DROP ⚠️ 顺序极其重要!ESTABLISHED,RELATED 规则必须放在 -P INPUT DROP 之前,否则已建立的 SSH 连接也会被切断。
iptables 完整命令速查表
| 命令 | 描述 |
|---|---|
| iptables -L -v -n --line-numbers | 查看所有链的规则(详细、含行号) |
| iptables -t nat -L -n -v | 查看 NAT 表规则(Docker 端口映射在此) |
| iptables -A INPUT -p tcp --dport 22 -j ACCEPT | 允许 TCP SSH 端口(22)入站 |
| iptables -A INPUT -p tcp --dport 80 -j ACCEPT | 允许 HTTP(80)入站 |
| iptables -A INPUT -s 1.2.3.4 -j DROP | 丢弃来自特定 IP 的包 |
| iptables -P INPUT DROP | 设置 INPUT 链默认策略为丢弃 |
| iptables -D INPUT 3 | 删除 INPUT 链中的第 3 条规则 |
| iptables -F | 清空 filter 表所有规则 |
| apt install iptables-persistent -y | 安装规则持久化工具 |
| netfilter-persistent save | 保存当前规则(重启后生效) |
🐳 重要:Docker 绕过 UFW 的陷阱
Docker 用户必须了解的安全大坑!
Docker 启动时会直接向 iptables 的 nat 表插入规则,将容器端口映射绕过 UFW 直接暴露到公网。例如执行 docker run -p 3306:3306 mysql,即使 UFW 中没有放行 3306,外网也能访问到数据库!原因:UFW 管理 filter 表,Docker 操作 nat 表,两者互不干涉。
# 方案一(推荐):容器绑定本地而非 0.0.0.0
docker run -p 127.0.0.1:3306:3306 mysql
# 或在 docker-compose.yml 中:
# ports:
# - "127.0.0.1:3306:3306"
# 方案二:禁止 Docker 直接操作 iptables
# 编辑 /etc/docker/daemon.json:
# { "iptables": false }
# 重启 Docker:systemctl restart docker
# 验证 Docker 暴露了哪些端口(NAT 表)
iptables -t nat -L DOCKER -n ✅ 方案一:绑定本地(推荐)
- 只需修改容器启动命令,改动最小
- 不影响 Docker 其他网络功能
- 通过 Nginx 反向代理对外暴露服务
- 适合绝大多数个人 VPS 场景
⚠️ 方案二:禁用 iptables 模式
- 完全由 UFW 统一管理所有端口
- 容器间网络通信可能受影响
- 需要手动为每个容器添加 UFW 规则
- 适合对安全要求极高的生产环境
🌍 进阶:ipset 封锁特定国家
如果您发现大量攻击来自特定国家,可以使用 ipset 批量封禁该国所有 IP 段。ipset 使用哈希表存储,无论集合多大查询速度均为 O(1),效率远高于逐条 iptables 规则。
# 1. 安装 ipset
apt install ipset -y
# 2. 创建名为 blocklist 的集合(hash:net 支持 CIDR 段)
ipset create blocklist hash:net
# 3. 下载国家 IP 段(以俄罗斯 RU 为例,可替换为 cn / us / ir 等)
wget -O ru.zone http://www.ipdeny.com/ipblocks/data/countries/ru.zone
# 4. 批量导入
for i in $(cat ru.zone); do ipset add blocklist $i; done
# 5. 关联 iptables(插入到链头,优先执行)
iptables -I INPUT -m set --match-set blocklist src -j DROP
# 6. 持久化 ipset(开机恢复)
ipset save > /etc/ipset.rules
# 在 /etc/rc.local 中添加:ipset restore < /etc/ipset.rules 💡 国家代码参考:cn(中国)、us(美国)、ru(俄罗斯)、ir(伊朗)、kp(朝鲜)。可在 ipdeny.com 下载任意国家的 IP 段文件。注意:地区封锁是双向的,封锁后该地区用户也无法访问您的服务。
👮 进阶:Fail2ban 自动防御
即使改了 SSH 端口,服务器仍会被不停扫描。Fail2ban 监控登录日志,自动将多次尝试失败的恶意 IP 加入 iptables 封禁列表。
# 1. 安装 Fail2ban
apt install fail2ban -y
# 2. 创建本地配置文件(避免更新时覆盖)
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# 3. 自定义 SSH 防护参数(编辑 jail.local)
# [sshd]
# enabled = true
# port = YOUR_SSH_PORT ← 改成你的 SSH 端口
# bantime = 86400 ← 封禁 24 小时
# findtime = 600 ← 10 分钟内
# maxretry = 3 ← 失败 3 次即封
# 4. 启动并设置开机自启
systemctl enable fail2ban && systemctl start fail2ban
# 5. 查看封禁状态
fail2ban-client status sshd /var/log/auth.log。配置 bantime = -1 可实现永久封禁;还可以通过 action 配置与 Cloudflare API 联动,在 CDN 层自动封禁恶意 IP,完全不消耗服务器资源。
🌊 DDoS 基础防护
主机防火墙无法抵御大规模带宽型 DDoS,但可以使用 iptables 速率限制缓解小规模的连接耗尽攻击(CC 攻击)。
连接速率限制脚本
# 限制单个 IP 地址的并发连接数(防 CC 攻击)
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 -j DROP
# 限制 SSH 新连接速率(防暴力破解)
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP SYN Flood 内核级防护
编辑 /etc/sysctl.conf,添加以下参数后执行 sysctl -p 生效:
# 编辑 /etc/sysctl.conf,添加以下参数后执行 sysctl -p 生效
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.conf.all.rp_filter = 1 ⚠️ 对于大规模 DDoS,最有效的方案是将域名接入 Cloudflare(免费版即可),利用其全球 Anycast 网络吸收和过滤攻击流量,完全不需要修改服务器配置。详见服务器安全进阶。
🔮 nftables:现代化替代方案
nftables 是 iptables 的官方继任者,Debian 10+、Ubuntu 20.04+ 已内置。语法更一致,性能更好,且可以在一条规则中同时处理 IPv4 和 IPv6。
# 查看当前 nftables 规则
nft list ruleset
# 基础规则集(等同于 UFW 默认配置)
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input iif lo accept
nft add rule inet filter input tcp dport 22 accept
# 持久化
nft list ruleset > /etc/nftables.conf && systemctl enable nftables 💡 如果是全新部署,建议直接使用 nftables。UFW 目前仍基于 iptables,与 nftables 同时使用可能有冲突,建议二选一。
🚪 通用端口管理
有效管理端口的核心原则:最小化开放端口——只开放您当前需要的服务端口,定期检查并关闭不再使用的端口。
常见服务端口速查
| 端口 | 服务 | 描述 |
|---|---|---|
| 21 | FTP | 文件传输协议(不安全,建议用 SFTP) |
| 22 | SSH | 安全远程登录和文件传输 |
| 25 | SMTP | 邮件发送协议 |
| 53 | DNS | 域名解析服务 |
| 80 | HTTP | Web 服务(未加密) |
| 443 | HTTPS | Web 服务(加密) |
| 3306 | MySQL | MySQL 数据库(建议绑定 127.0.0.1) |
| 5432 | PostgreSQL | PostgreSQL 数据库 |
| 6379 | Redis | Redis 缓存数据库(建议绑定 127.0.0.1) |
| 8080 | HTTP Alt | 备用 HTTP 端口,常用于开发/反代 |
检查当前开放端口
# 查看所有监听端口(推荐)
sudo ss -tuln
# 查看端口及对应进程
sudo ss -tulnp 参数:-t(TCP)-u(UDP)-l(监听)-n(数字格式)-p(显示进程)
📝 日志审计与监控
配置了防火墙不代表万事大吉,定期查看日志能让你了解谁在攻击你、封禁了哪些 IP。
🪵 开启 UFW 日志并实时查看
sudo ufw logging on tail -f /var/log/ufw.log 每条记录包含:时间、动作(BLOCK/ALLOW)、来源 IP、目标端口。
👮 Fail2ban 封禁记录
fail2ban-client status sshd fail2ban-client status 显示当前封禁的 IP 列表、已封禁总数、监控的日志文件。
🔍 查看 SSH 登录失败记录
grep "Failed password" /var/log/auth.log | tail -20 lastb | head -20 ✨ 安全实践和技巧
🛡️ 默认拒绝策略
始终采用"默认拒绝所有,按需允许少数"的策略。这是最核心的防火墙思想,宁可漏配一个端口(功能失效)也不要多开一个端口(安全隐患)。
🚪 最小化开放端口
只开放您当前需要的服务端口。数据库(3306/5432/6379)绑定到 127.0.0.1,不对外暴露。定期用 ss -tulnp 检查监听端口。
🔢 更改默认 SSH 端口
将 SSH 端口从 22 改为 10000-65535 之间的随机端口,可消除 99% 的自动化扫描攻击。修改后先测试新端口可用,再断开旧连接。
🔒 限制 IP 访问敏感端口
管理类端口(数据库、后台面板)只允许特定 IP 访问:ufw allow from 你的IP to any port 3306,完全隔绝外部攻击面。
❓ 常见问题解答
UFW 和 iptables 可以同时使用吗?会冲突吗?
可以同时存在,但建议只用一套工具管理规则。UFW 底层调用 iptables,启用 UFW 时会在 iptables 中插入自己的规则链(ufw-before-input 等)。如果同时直接用 iptables -A 添加规则,规则会并存,执行顺序由插入位置决定,容易产生意外效果。最佳实践:初学者用 UFW;需要精细控制时,ufw disable 后迁移到纯 iptables 或 nftables,选一套坚持使用。
防火墙规则设置错误把自己锁在门外了,怎么办?
标准救援流程:① 登录 VPS 商家控制面板,找到 VNC / Console 带外访问功能;② 通过 VNC 直接操作(不依赖 SSH);③ 关闭防火墙:ufw disable 或 iptables -F;④ 修复配置后重新启用。预防方法:测试新规则时先执行 echo "ufw disable" | at now + 5 minutes,5 分钟后自动关闭,给自己留退路。
DENY 和 REJECT 有什么区别?分别在什么时候用?
DENY(DROP):静默丢弃,不发任何响应。攻击者发包石沉大海,扫描工具需等超时,速度慢——对外部攻击者使用。REJECT:主动返回"Connection refused",连接失败立即可知——对内网或已知 IP 的合法请求使用,更友好。建议:对公网来的恶意扫描用 DROP(UFW deny),对内网服务误配置用 REJECT,减少调试时间。
iptables 规则越来越多,性能会变差吗?如何优化?
iptables 是线性匹配,规则达到数千条时才有明显影响。个人 VPS 通常不超过 50 条,性能完全不是问题。如需管理大量 IP(封禁列表),使用 ipset——哈希表结构,O(1) 查找,万条 IP 也瞬间匹配。另外,将命中率高的规则(如 ESTABLISHED,RELATED)放在链头,大多数包在第一条就匹配,减少后续检查。大规则集场景建议迁移到 nftables,内置集合(set)性能更优。
配置了防火墙后服务器仍被 DDoS 打垮,防火墙有没有用?
防火墙对大规模 DDoS 效果有限。DDoS 的核心是带宽/连接耗尽,即使防火墙在系统层 DROP 了数据包,流量已进入网卡,带宽仍被占满。防火墙只能防止包消耗 CPU/内存,阻挡不了网络层的带宽饱和。真正有效的方案:① Cloudflare(免费):接入后利用其全球 Anycast 网络吸收过滤流量;② 商家 Anti-DDoS:选择有上游防护的 VPS 商家(OVH、Voxility 等);③ 黑洞路由:受攻击时商家临时封禁 IP,保护机房整体。
Fail2ban 误封了我自己的 IP,如何解封?
通过 VNC 控制台登录后执行:fail2ban-client set sshd unbanip 你的IP。预防误封:在 /etc/fail2ban/jail.local 中设置白名单 ignoreip = 127.0.0.1/8 你的IP,白名单内的 IP 永远不会被封禁。如果 IP 是动态的,可以适当提高 maxretry 值(如改为 10),或缩短 findtime(如改为 120 秒)来降低误封概率。
Tailscale / ZeroTier 异地组网后,防火墙规则需要怎么调整?
Tailscale 会创建 tailscale0 虚拟网卡,ZeroTier 创建 ztXXXXXXXX。UFW 默认对所有网卡应用同样规则,需要显式放行:ufw allow in on tailscale0(允许来自组网的所有流量)。更精细控制:只放行 Tailscale 网段的特定端口,例如 ufw allow from 100.64.0.0/10 to any port 3306(Tailscale 默认使用 100.64.0.0/10)。
如何只允许特定国家/地区的 IP 访问服务器?
使用 ipset 白名单模式:创建允许访问的国家 IP 集合,将默认策略设为 DROP,只 ACCEPT 集合内的 IP。比黑名单模式更安全,但维护成本更高。更简单的替代方案是使用 Cloudflare 防火墙规则:在 Cloudflare 的"防火墙规则"中按 IP Geolocation 过滤,在 CDN 层拦截,完全不消耗服务器资源,且地理位置数据库更准确(每天更新)。对于 SSH 端口,可以直接 ufw allow from 你的家庭IP to any port SSH端口,只允许特定 IP 访问,最简单有效。
怎么验证防火墙规则真的生效了?
多种方法组合验证:① 外部 TCP 测试:访问 port.ping.pe,从全球多节点测试目标端口连通性;② Nmap 扫描:从另一台机器执行 nmap -p 1-65535 服务器IP,确认只有预期端口 open;③ 规则命中统计:iptables -L INPUT -v -n,pkts(数据包数)随访问增加说明规则被命中;④ UFW 日志:开启 ufw logging on 后查看 /var/log/ufw.log,确认 BLOCK 记录正常产生。