一、ufw 和 iptables 到底什么关系

先说结论:ufw 不是和 iptables 平级的另一种防火墙,它是 iptables 之上的一个规则管理前端。你用 ufw 写的每一条规则,最终都变成 iptables 规则;你用 iptables 直接写的规则,ufw 不一定管得到,因为 ufw 只管理它自己那个链和规则表里的空间。
这个关系的实际后果有三个,知道了就不容易乱。
第一,你可以混用。用 ufw 管理日常规则(放行 22、80、443,deny 其余入站),用 iptables 处理 ufw 表达不了的需求(限制某个 IP 的连接速率、做字符串匹配、限制 syn 包速率)。两者可以共存,但要注意规则顺序。
第二,ufw 有自己的规则表和链。ufw 把规则写在 filter 表的 ufw-user-input 链里,通过一个跳转规则从 INPUT 链跳进去。而 INPUT 链的遍历顺序是「先走完 ufw-user-input 链,再回到 INPUT 链继续」。所以你用 iptables 直接 iptables -I INPUT 1 插入的规则,排在 ufw 规则前面,优先生效。这解释了新手最常见的困惑:「我明明在 ufw 里 deny 了,为什么那条 iptables 规则还能通」。
第三,ufw 的 deny 默认会连 established,related 的连接一起放行(回包必须能出去),所以 ufw 不是「完全封锁」语义。
用一条命令看清全部关系:
sudo iptables -L -n -v --line-numbers | head -30
sudo iptables -t filter -S | head -30
-S 输出的是规则的实际语法形式,比 -L 更直观。
底层结构是这样的:
INPUT → ufw-before-input → ufw-user-input → ufw-after-input → ufw-after-forward → ufw-logging-deny → ufw-reject-input
INPUT → ufw-after-input → ...
如果你的 iptables 规则被 ufw 的 before 链拦住了,要用 ufw before 子命令插入,而不是直接 -I INPUT。
二、什么时候用 ufw,什么时候用 iptables

选择标准很简单:规则是「按端口放行/拒绝」这种粗粒度的,用 ufw;规则涉及 IP 集合、速率限制、协议匹配、标记(mark)这些的,用 iptables。
ufw 的典型适用场景:
# 允许 SSH(务必第一条)
22/tcp
# 允许 HTTP 与 HTTPS
80/tcp
443/tcp
# 允许某个游戏服端口
25565/tcp
# 拒绝其他所有入站
默认 deny incoming
iptables 的典型适用场景有四种。第一种是按来源 IP 精确控制:
# 只允许 203.0.113.5 访问 SSH,其他一律拒绝
sudo iptables -A INPUT -p tcp --dport 22 -s 203.0.113.5 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j DROP
第二种是限制连接速率,防扫描和暴力破解:
# 对 SSH 限制:15 秒内最多 4 个新连接,超过就丢弃
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --set --name ssh
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --update --seconds 15 --hitcount 4 --name ssh -j DROP
第三种是限制 syn 包速率:
# 限制每秒 30 个新的 syn 包,抑制半开连接耗尽
sudo iptables -A INPUT -p tcp --syn -m limit --limit 30/s --limit-burst 60 -j ACCEPT
sudo iptables -A INPUT -p tcp --syn -j DROP
第四种是丢弃无效包,这是防火墙的基本卫生:
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
如果你的需求里出现了「限速」「按 IP 段」「标记流量」「转发」这些词,ufw 就吃力了。
一个现实因素是持久化。ufw 的规则写在 /etc/ufw/*.rules 里,重启自动恢复;iptables 直接写的规则重启就丢,必须用 iptables-persistent 或 netfilter-persistent 存到 /etc/iptables/rules.v4,或者自己写 systemd 服务。
# Debian/Ubuntu
sudo apt install iptables-persistent
sudo netfilter-persistent save
# CentOS
sudo yum install iptables-services
sudo systemctl enable iptables
ufw 也需要 sudo ufw enable 之后规则才真正生效,只 ufw allow 是不上线的。
还有第三个选项值得知道:nftables。它是 Linux 内核 4.18 之后自带的新一代包过滤框架,是 iptables 的后继。发行版上常见的 iptables 命令在较新的内核上其实已经是 nftables 的兼容层。nftables 的优势是用一套语法统一管理 IPv4、IPv6、桥接和 arp 表,规则集是表、链、集合的树状结构,匹配效率更高,而且天然支持集合操作——一次能处理上千个 IP,不需要为每个 IP 生成一条规则。
# 查看当前的 nftables 规则集
sudo nft list ruleset
如果你的机器内核在 4.18 以上并且你打算从头设计一套规则,nftables 是更现代的选择。但如果你的目标是最快解决问题,ufw 加 iptables 的组合仍然是绝大多数运维场景里最省时的路径,因为网上能找到的教程和现成脚本绝大多数是这两个。
三、ufw 常用规则怎么写

ufw 的命令语法是「动作 + 端口/服务 + 来源」。写规则时最常见的三个坑:不带 tcp/udp 后缀、用 allow 忘了 enable、以及 deny 之后 allow 的顺序。
先看完整的一套:
# 1. 默认策略:入站拒绝,出站允许,转发拒绝
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw default deny routed
# 2. 允许 SSH(第一条,永远不要跳过)
sudo ufw allow 22/tcp
# 3. 允许 Web
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# 4. 允许指定来源访问指定端口
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp
# 5. 允许 UDP 的 DNS 出站(出站默认已允许,写出来是为了明确意图)
sudo ufw allow out to 8.8.8.8 port 53 proto udp
# 6. 拒绝某个 IP 访问所有端口
sudo ufw deny from 198.51.100.7
# 7. 限制子网段
sudo ufw allow from 192.168.1.0/24 to any port 3306 proto tcp
# 8. 启用
sudo ufw enable
注意第 6 条:deny from 一个 IP 在 ufw 里不是绝对的,因为它排在 ufw-user-input 链里,而你之前写的 allow from 203.0.113.0/24 to any port 22 这类规则在同一链里,ufw 的规则是按添加顺序匹配,先匹配到的先生效。所以「deny 某个 IP」要放在相关 allow 规则之后才有效。这个顺序问题在 ufw 里没有显式提示,是最容易踩的一个坑。
查状态和规则:
sudo ufw status verbose # 带默认策略和规则编号
sudo ufw status numbered # 带编号,便于删除
sudo ufw show raw # 看生成的 iptables 规则
sudo ufw show raw 这条特别有用,它能让你确认 ufw 到底把你的规则翻译成了什么。如果 show raw 里没有你预期的规则,说明命令写错了。
ufw 的规则编号还有一个实用技巧——用编号插入而不是追加,可以把新规则放到指定位置:
# 在第 3 条规则之前插入一条新的 SSH 放行
sudo ufw insert 3 allow from 203.0.113.5 to any port 22 proto tcp
这解决了前面提到的顺序问题:想 deny 某个 IP 但已经有相关的 allow 规则时,不需要先删再加,直接 insert 到 allow 之前就行。
常见报错与含义:
| 报错 | 原因 | 处理 |
|---|---|---|
ERROR: Invalid syntax |
动作或参数写错 | 对照 ufw --help 逐项检查 |
ERROR: You must enable before... |
加了规则但没启用 | sudo ufw enable |
Skipping adding existing rule |
规则已存在 | 正常提示,不是错误 |
ERROR: Unable to contact firewall |
ufw 服务没起来 | systemctl status ufw |
ERROR: Running in faked mode |
没有真实防火墙支持 | 检查内核模块是否加载 |
最后一条 Running in faked mode 通常出现在容器里或者内核没有 iptables 支持的环境。此时 ufw 的规则不会真正生效,你必须用云厂商的安全组来控制访问。
还有一类报错发生在 IPv6 环境。ufw 的 IPV6=yes 默认开启,但如果你编辑 /etc/default/ufw 把它关掉了,而系统实际有 IPv6 地址,就会出现「IPv4 规则生效但 IPv6 连不上」的情况。检查方法:
ip -6 addr show scope global
grep IPV6 /etc/default/ufw
如果机器有公网 IPv6 地址,/etc/default/ufw 里的 IPV6=yes 应该保留,同时要在云厂商安全组里也放行对应的 IPv6 规则。
四、出站规则:最容易被忽略的一层防护

大多数教程只讲入站规则,因为入站是「别人来打我」。但出站规则同样重要,而且它防的是另一类事故:服务器被入侵后,攻击者往外发数据、挖矿、连回控制服务器。
先说清楚默认策略。ufw 的默认出站策略是 allow,也就是不限制。这对大多数个人用户是合理的——你需要机器能装软件、访问 API、更新源。但如果你跑的是一台有敏感数据的机器,出站白名单是值得加的。
# 默认出站拒绝
sudo ufw default deny outgoing
# 然后按需放行:DNS、DNS 解析、HTTP、HTTPS、SSH 出去
sudo ufw allow out to 8.8.8.8 port 53 proto udp
sudo ufw allow out to 8.8.4.4 port 53 proto udp
sudo ufw allow out to any port 80 proto tcp
sudo ufw allow out to any port 443 proto tcp
sudo ufw allow out to any port 22 proto tcp
注意 DNS 要放行到具体的解析器 IP 而不是 53 端口全放,否则「允许所有 DNS 出站」等于把数据外泄的口子留着。
如果你的系统用 systemd-resolved,DNS 走的是本地 127.0.0.53,那出站规则要放行到真正的上游。查看上游:
resolvectl status | grep "DNS Servers"
放行之后要确认没有把自己锁死——出站拒绝状态下,apt 更新、pip 安装、curl 访问外网都会失败。测试方法:
curl -sI https://deb.debian.org | head -1
sudo apt update
这两条都正常,说明出站规则配对了。
另一个出站场景是「只允许特定目标」的严格模式。用 ipset 管理一组 IP,iptables 规则只引用这个集合:
# 创建集合
sudo ipset create allowed_ips hash:net
sudo ipset add allowed_ips 203.0.113.0/24
sudo ipset add allowed_ips 198.51.100.0/24
# 只允许出站到这些 IP 的 TCP 流量
sudo iptables -A OUTPUT -p tcp -m set --match-set allowed_ips src,dst -j ACCEPT
sudo iptables -A OUTPUT -p tcp -j REJECT
集合的好处是加 IP 时只改一行,不用动防火墙规则本身。维护 ipset 的持久化用 ipset-persistent 包。
还要提醒一个安全细节:出站规则能防的是「被控制后往外发数据」,防不了「被用来打别人」。后者需要限制出站目的端口:
# 禁止出站连接常见的邮件中继端口 25,防止机器被当成垃圾邮件跳板
sudo ufw deny out to any port 25 proto tcp
云厂商一般已经在安全组层面默认封了 25 端口,但独立服务器需要自己处理。
五、误封自己 SSH 怎么办:三种救援办法

这是每个新手都会遇到一次的问题。改了防火墙规则,SSH 连不上了,机器还在跑,但你在外面。
先说预防,这是最有效的手段。在改动防火墙之前,保持当前 SSH 会话不要关,另开一个终端测试新规则:
# 在新会话里测试(不关闭当前会话)
ssh -p 22 root@你的IP
确认能连上再关旧会话。如果你的服务商提供 VNC / 控制台 / IPMI / 串口控制台,一定要先找到它——这是唯一的物理后门。
说清楚原理:iptables 的规则是立即生效的,它不关心你的 SSH 会话是已建立的还是新建的。你已经建立的 SSH 连接靠的是 ESTABLISHED,RELATED 状态跟踪,所以旧会话通常不会断;但你新开的连接会按新规则走,于是被拒。
三种救援办法,按可靠性排序。
第一种,用服务商提供的 VNC 或网页控制台登录。这是最干净的,因为完全绕过了网络。多数 VPS 提供商都有这个功能,登录后直接:
sudo ufw disable # 先恢复
sudo ufw status # 确认规则
# 修好规则后再 enable
第二种,用 provider 提供的急救模式或者重新加载防火墙配置。有些服务商提供「重置防火墙」按钮,效果等同于 ufw disable。
第三种,如果你的服务商有 ipmi 或者 IPKVM 且服务商支持「防火墙关闭」,用这个。
三种都不可用时的最后手段:找服务商客服,说明情况,请求临时解除网络限制。这个流程会慢,但在紧急情况下是唯一的路。
预防措施,现在就做:
# 1. 改规则前先加一条定时自动解除的规则
sudo at now + 10 minutes <<< "sudo ufw disable"
# 如果系统没有 at,用 cron 一次性任务
echo "10 0 * * * root /usr/sbin/ufw disable" | sudo tee /etc/cron.d/ufw-reset
# 确认能连上后删除它
sudo rm /etc/cron.d/ufw-reset
这个「定时解禁」的技巧值得记住,它把「改防火墙」从一个有风险的动作变成了可逆的动作。
还有一个必备习惯:加一条针对自己来源 IP 的白名单规则,放在所有规则最前面:
sudo ufw allow from 你的公网IP to any port 22 proto tcp
你的公网 IP 可以这样查:
curl -s https://api.ipify.org
如果你的公网 IP 是动态的(家庭宽带、移动网络),更稳妥的做法是按网段放行,比如整个 /24 段:
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp
再进一步的做法是干脆不用密码登录,改用密钥加二次验证。这从根上消除了「被扫描到 SSH 端口」这个风险面:
# 生成密钥对(在本地机器上执行,私钥永远不要传到服务器)
ssh-keygen -t ed25519 -C "vps-2026"
# 把公钥传到服务器
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@你的IP
# 验证密钥登录可用后,关闭密码登录
sudo sed -i 's/#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl reload sshd
sshd -t 是配置语法检查,加 && 保证检查通过才重载服务。PermitRootLogin prohibit-password 允许 root 用密钥登录但禁止用密码,比完全禁止 root 更方便,同时保留了密钥这一条路径。
改完之后用新开一个终端测试:
ssh root@你的IP
能连上再关掉旧会话。这样即使之后防火墙规则改错了,你也不会彻底失联——因为密钥登录不受影响,而 ufw 只需要放行 22 端口就够了。
六、云厂商安全组与本机防火墙怎么叠加

大部分 VPS 场景里,你的机器前面有两层控制:云厂商的网络安全组(Security Group)和机器本机的 ufw/iptables。它们是串联关系,任何一层拒绝,请求就到不了服务。
请求路径是这样:
外部请求 → 云厂商安全组(虚拟交换机层) → 虚拟网卡 → 本机 netfilter/iptables/ufw → 应用
关键规则:两层是「与」的关系,不是「或」。安全组放行但本机拒绝 → 不通;本机放行但安全组拒绝 → 也不通。所以排查连通性问题时,必须从外往里逐层测。
逐层测试的方法:
# 第一层:从外部测试端口是否通(用别人机器或在线工具)
nc -zv 你的IP 443
# 第二层:看安全组规则里有没有这个端口
# 第三层:在机器本机看是否监听
sudo ss -tlnp | grep :443
# 第四层:在机器本机测试(绕过安全组,只测本机防火墙)
curl -k https://127.0.0.1 -H "Host: 你的域名"
第四步是分界点。本机测试通、外部测试不通 → 问题在安全组或云防火墙;本机测试也不通 → 问题在本机防火墙或应用。
安全组常见的默认行为:
- 入站默认拒绝,出站默认允许。
- 部分服务商会给「默认放行所有」或「默认拒绝所有」两种模板,创建时要看清。
- 安全组规则有优先级,数字小的先匹配,和 ufw 的「后添加先生效」正好相反。
- 很多服务商的安全组不支持「只放行某 IP」,或者每条规则有数量上限。
具体的开放端口清单,取决于你跑什么。常见服务对应的端口:
| 服务 | 端口 | 协议 |
|---|---|---|
| SSH | 22 | TCP |
| HTTP | 80 | TCP |
| HTTPS | 443 | TCP |
| DNS 解析 | 53 | TCP/UDP |
| 邮件 | 25、465、587 | TCP |
| FTP | 21 | TCP |
| RDP | 3389 | TCP |
| 数据库(外网访问时) | 3306、5432 | TCP |
数据库端口原则上不要对公网开放。如果确实需要远程连,走 SSH 隧道:
ssh -N -L 3307:127.0.0.1:3306 user@你的VPS
# 然后本地客户端连 127.0.0.1:3307
这样数据库端口在安全组和本机防火墙里都可以完全关闭。
顺带一提「云厂商防火墙」和「安全组」的区别:有些服务商提供的是流量级别的规则(比如按访问源 IP 的 CIDR 放行),有些是主机级别的(比如只作用于某台机器)。两层都有的话,最外层是主机防火墙,最外层优先。
七、端口扫描防护:正确的配法与常见误区

端口扫描本身不等于攻击,但暴露了一台开着很多端口的机器会招来自动化扫描,进而招来暴力破解。防护的目标不是「让扫描器扫不到」——这做不到,因为只要机器对公网开放一个端口,扫描就能发现主机存活——目标是「让扫描之后的攻击尝试难以成功,并且留下日志」。
第一步是最基础的:只开必要端口,关闭一切不需要的。
# 看当前实际监听的端口
sudo ss -tulnp
输出里 0.0.0.0:22 表示所有网卡都监听,127.0.0.1:3306 表示只有本地能访问。数据库和缓存应该只监听回环地址或内网地址。
改 MySQL 绑定地址,在 /etc/mysql/mysql.conf.d/mysqld.cnf:
[mysqld]
bind-address = 127.0.0.1
改 Redis,在 redis.conf:
bind 127.0.0.1
protected-mode yes
第二步是针对暴力破解加限速。用 fail2ban 是最省事的方案,它扫描认证失败日志然后封禁来源 IP:
sudo apt install fail2ban
sudo systemctl enable --now fail2ban
# 查看当前被封禁的 IP 和服务状态
sudo fail2ban-client status sshd
fail2ban 默认对 sshd 的策略是:5 分钟内失败 5 次就封 10 分钟。可以自定义 /etc/fail2ban/jail.local:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 3
[sshd]
enabled = true
bantime = 24h
findtime = 10m
maxretry = 3
这个配置的含义是:10 分钟内失败 3 次,封 24 小时。对有真实用户在使用 SSH 的机器,bantime 别设太长,否则你可能把自己锁在外面。
第三步是内核层的 SYN 洪水防护:
# 开启 syncookies,应对 SYN flood
sudo sysctl -w net.ipv4.tcp_syncookies=1
echo "net.ipv4.tcp_syncookies = 1" | sudo tee -a /etc/sysctl.conf
syncookies 在 SYN 队列溢出时启用半连接 cookie,让服务器不保存半连接状态就能正确验证,代价是客户端首次连接会稍慢。
第四步是连接数限制,防止单 IP 耗尽连接数:
# 每个源 IP 最多 20 个并发连接
sudo iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW \
-m recent --set --name connlimit
sudo iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW \
-m recent --update --seconds 60 --hitcount 20 --name connlimit -j REJECT --reject-with tcp-reset
第五步是限速,这是 ufw 也能做的一层:
# 限制 SSH 速率:每秒 6 个包,突发 10
sudo ufw limit 22/tcp
ufw limit 是 ufw allow 的速率限制版本,内部生成的是 iptables 的 limit 规则,比 fail2ban 轻量,但不会自动解封。
关于常见误区,有几个需要澄清。
误区一:「装个防火墙扫描就扫不到了」。不成立。只要 80 或 443 开着,扫描器就能确认主机存活并识别服务,隐藏端口不能改变这一点。真正有效的是减少可利用面——关闭无用端口、禁用密码登录、密钥登录。
误区二:「fail2ban 装上就万事大吉」。fail2ban 只处理认证失败日志。如果你的 SSH 允许 root 密码登录,暴力破解本身就能在成功之前耗尽资源。正确做法是禁用密码登录:
sudo sed -i 's/#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl reload sshd
sshd -t 是语法检查,加 && 保证检查通过才重载,否则你可能把自己锁在外面。
误区三:「限速规则越多越安全」。限速规则本身要消耗 CPU 处理每一个包。规则链上堆几十条无用的规则,只增加延迟不增加安全。
误区四:「云厂商安全组配好了就不用管机器里的防火墙」。两层是串联的,缺一不可,而且要定期核对两边的规则是否一致——很多事故的成因是「安全组后来被改动了,机器里的规则没同步」。
八、日志、监控与规则的日常维护

防火墙配好之后有两件事必须持续做:知道谁在扫你,以及定期复查规则。
审计日志要先打开。ufw 默认把日志记到 /var/log/ufw.log,但级别可能不够。用:
sudo ufw logging medium
级别从低到高是 off、low、medium、high。medium 会记录被拒绝的连接。
ufw 的日志位置可以改,在 /etc/ufw/ufw.conf 里:
LOGGING=file
改成 file 之后日志进 /var/log/ufw.log;默认是 syslog,进 journald。可以直接看:
sudo tail -f /var/log/ufw.log
# 或者
sudo journalctl -k -f | grep -i ufw
统计一下最近的扫描来源:
# 最近被拒绝的连接最多的来源 IP 前 10
sudo grep "UFW BLOCK" /var/log/ufw.log | awk '{print $NF}' | sort | uniq -c | sort -rn | head -10
这些 IP 就是正在扫你的。数量多不代表危险,规律性的大量扫描是常态。
用 iptables 的日志做同样的分析:
# 给 INPUT 链加日志规则(放在最前面)
sudo iptables -I INPUT 1 -j LOG --log-prefix "FW-DROP: " --log-level 4
# 然后看
sudo dmesg | grep "FW-DROP" | tail -50
注意 LOG 链只是记录不会阻断,真正的拒绝要靠后面的 DROP 规则。
日常维护有一个固定清单,建议每月跑一次:
# 1. 当前实际监听的端口
sudo ss -tulnp
# 2. ufw 规则与默认策略
sudo ufw status verbose
# 3. iptables 完整规则
sudo iptables -S
# 4. 安全组规则(去控制台核对)
# 5. 确认 SSH 配置
sudo sshd -T | grep -E "permitrootlogin|passwordauthentication|pubkeyauthentication"
# 6. 确认规则已持久化
sudo netfilter-persistent save 2>/dev/null || echo "检查持久化方式"
第 5 条的输出里,permitrootlogin no、passwordauthentication no、pubkeyauthentication yes 是期望值。
规则清理也有固定做法。先看每条规则的命中次数:
sudo iptables -L -n -v --line-numbers
pkts 列长期为 0 的规则通常可以删掉。删除前先备份:
sudo iptables-save > ~/iptables-backup-$(date +%F).rules
sudo iptables-restore < ~/iptables-backup-2026-11-05.rules
ufw 规则的删除用编号:
sudo ufw status numbered
# 6/tcp ALLOW IN 22
sudo ufw delete 6
也可以按规则原文删:
sudo ufw delete allow 22/tcp
还有一个容易忽略的检查:ufw 的规则文件和实际生效的规则可能不一致。sudo ufw show raw 显示的是当前生效的,/etc/ufw/user.rules 显示的是落盘的。如果两者对不上,说明有人手动改过 iptables 而没有同步到 ufw 的配置里。
Docker 与 ufw 的冲突也要在这一步检查。Docker 会在启动时把它的规则插到 DOCKER 链,而 ufw 的 before 规则可能在 DOCKER-USER 链之前生效或被绕过,表现就是「ufw deny 了某个端口,但容器端口照样能访问」。解决办法是把限制规则放到 DOCKER-USER 链:
sudo iptables -I DOCKER-USER -p tcp --dport 3306 -j DROP
这条规则会在 Docker 的转发逻辑之前拦下流量。
九、防火墙配置对机型选择的影响:为什么配置要匹配带宽

防火墙不是纯软件话题,它和机器的规格有直接关系。这一节讲清楚这个关系,因为很多人是在机器已经买好之后才想起防火墙,而那时候可能发现配置空间不够用。
第一个关系是规则集大小与内存。iptables 的规则在内存里,每个连接都要走一遍规则链。规则链上有几百条规则时,每包的处理时间会增加,但这个开销通常在微秒级,对绝大多数应用可以忽略。真正会出问题的场景是「用 ipset 拉黑名单」——如果名单有十万条 IP,虽然 set 查询是 O(1) 的,但 set 本身占用的内存可观。做法是给 set 设上限:
sudo ipset create blacklist hash:ip maxelem 200000
第二个关系是带宽与限速规则的匹配。这一条很实际:如果你在链路上加了 SYN 限速规则,限速阈值必须和你的实际带宽匹配。
# 限速 30 个 syn/秒,突发 60
sudo iptables -A INPUT -p tcp --syn -m limit --limit 30/s --limit-burst 60 -j ACCEPT
这个规则的意思是「每秒最多处理 30 个新连接,超过的直接 DROP」。如果你机器的带宽是 10000 Mbps(10000/8 = 1250 MB/s),而你的业务需要支撑每秒数百个新连接,那么 30/s 的限速就会成为瓶颈——正常业务的连接也会被丢。限速阈值应该按「正常业务峰值新连接数 × 2」来设,而不是照抄网上的例子。
第三个关系是流量成本。端口扫描防护里的封禁规则会让被封 IP 的连接直接 RST 或 DROP,这些流量通常不计入你的月流量额度(因为没进你的带宽管道),但如果服务商对「入站流量」也计费,就要看具体条款了。
第四个关系是防护能力与内存规格的匹配。防护方案通常需要额外进程常驻:fail2ban 大约占用 30MB 到 60MB 内存,Suricata 这样的全流量检测引擎则是 GB 级。所以一台 1GB 内存的机器跑 fail2ban 没问题,跑 Suricata 就直接见底。
这一节的实用结论是:按负载配机型时,把防护组件的常驻内存算进去。渠道库里能查到的真实机型里,1GB 内存那档(RosCloud-01,19.99 美元/月,2 核 1GB 20GB 盘 500 Mbps 1024GB 流量)跑基础服务加 fail2ban 是够的;4GB 内存那档(RosCloud-03,39.99 美元/月,4 核 4GB 80GB 盘 3072GB 流量)就能加上审计、监控 agent 这类常驻进程了。
最后还要说一句关于安全的常识:防火墙是纵深防御的一层,不是一层顶所有。真正的安全底线是——不用 root 密码登录、保持系统更新、限制监听端口、给管理面板加访问控制。防火墙规则能挡住已知端口的扫描,但挡不住针对已开放端口的应用层攻击。这两件事要一起做。
按你的情况,下一步该看哪家
上面讲的是判断标准,但多数人最后还是想问一句「那我该买谁」。按你的实际情况对照下面几条,直接去看对应的机型页比继续比价更快:
- 主要访客在国内、在意打开速度:先确认回程线路,再谈配置。看 iwebfusion 当前机型与价格
- 只是开发测试、临时用:按小时或月付,用完就删,别买年付。看 racknerd 当前机型与价格
价格与库存以商家页面当日显示为准,下单前建议先确认退款窗口与是否支持按月付费。
十、常见问题

ufw和iptables应该用哪个? 看规则的精细程度。按端口放行拒绝用 ufw,涉及 IP 段、速率限制、协议匹配、Docker 转发这些用 iptables。两者可以共存,注意 iptables 里用 -I INPUT 1 插入的规则会排在 ufw 规则前面。
为什么我在ufw里deny了某个IP,它还能访问? ufw 的规则按添加顺序匹配,先匹配到的先生效。要 deny 的规则必须加在相关 allow 规则之后。另外 ufw 默认放行 established,related 的连接。
改了防火墙规则SSH连不上了怎么办? 首选服务商的 VNC 或网页控制台,进去执行 sudo ufw disable 再修规则。以后改规则前先跑 sudo at now + 10 minutes <<< "sudo ufw disable" 做保险,或者先加一条自己公网 IP 的放行规则。
提示"Running in faked mode"是什么意思? 表示系统没有真正的防火墙支持(常见于容器环境或内核未加载相关模块),ufw 规则不会生效。此时必须用云厂商的安全组控制访问。
为什么安全组放行了端口但外网还是连不上? 安全组和本机防火墙是串联的,任何一层拒绝都不通。从外往里逐层测:先 nc -zv IP 端口 测外网,再在机器上 ss -tlnp | grep 端口 看是否监听,最后 curl 连 127.0.0.1 测本机防火墙。本机通外网不通,问题在安全组。
ufw的规则重启后会丢失吗? 不会,ufw 规则写在 /etc/ufw/user.rules 等文件里,启用后自动恢复。但直接用 iptables 命令写的规则会丢,需要 netfilter-persistent save 或配 systemd 服务持久化。
怎么查看服务器上到底开着哪些端口? sudo ss -tulnp 最直观,能同时看到端口、协议、进程名和监听地址。netstat -tulnp 是老写法,需要装 net-tools。nmap 是从外部扫描自己的机器,能看到对外呈现的端口视图。
fail2ban封禁的IP怎么解封? sudo fail2ban-client set sshd unbanip 1.2.3.4。查看全部被封 IP 用 sudo fail2ban-client status sshd。误封自己时也可以直接清空:sudo fail2ban-client unban --all。
云服务器的安全组和独立服务器的iptables,先配哪个? 独立服务器只有 iptables 这一层。云服务器优先配安全组(改错了还能通过控制台回滚),本机防火墙作为第二层防护。顺序上先安全组后本机,两层规则都要覆盖实际需要的端口。
Docker容器的端口为什么ufw拦不住? Docker 把规则放在 DOCKER 链并在转发路径上优先生效,可能绕过 ufw 的 INPUT 链。解决办法是把限制规则插到 DOCKER-USER 链,它在 Docker 转发逻辑之前生效。
iptables规则太多导致响应变慢,怎么排查? 用 sudo iptables -L -n -v --line-numbers 看每个规则的命中数(pkts 列)。命中数为 0 的规则通常是没用的,可以删掉。规则链条过长时,把高频匹配放在前面。
VPS被扫了需要换IP吗? 一般不需要。扫描是自动化的,互联网上每台公网机器都在被扫。真正要处理的是:关闭无用端口、禁用 SSH 密码登录、装 fail2ban、保持系统更新。有业务依赖特定 IP 的场景才考虑换 IP。

喜欢
高兴
鬼脸
呵呵
无聊
伤心