一台刚开机的 VPS,往往默认开放了大量端口。对代理服务器来说,暴露不必要的端口等于给攻击者留门。防火墙的核心思路很简单:默认拒绝所有入站,只放行你明确需要的端口。
这篇文章覆盖三套主流方案:经典的 iptables、现代的 nftables、以及 Ubuntu 推荐的简化工具 ufw。不需要全部掌握——根据你的系统和习惯选一套即可。
一、核心概念:入站、出站与默认策略
防火墙工作在网络包的转发路径上,对每个数据包执行匹配规则。理解以下三个概念是配置的前提:
- 入站(INPUT):外部发往你 VPS 的数据包。这是防火墙重点防护的方向——决定哪些端口对外可见。
- 出站(OUTPUT):你的 VPS 向外发送的数据包。通常不做限制,除非你需要控制出站流量。
- 转发(FORWARD):经过 VPS 中转的数据包。除非你做路由器或网关,一般用不到。
默认策略决定当数据包不匹配任何规则时的行为:
| 策略 | 行为 | 适用场景 |
|---|---|---|
| DROP(丢弃) | 静默丢弃,不返回任何响应 | 推荐。攻击者无法判断端口是否存活 |
| REJECT(拒绝) | 返回"连接被拒绝"错误 | 调试时使用,正式环境不推荐 |
| ACCEPT(放行) | 允许通过 | 仅用于你明确需要的端口 |
二、iptables:经典但依然主流
iptables 是 Linux 上最广泛使用的防火墙工具,基于 Netfilter 内核模块。虽然语法略显陈旧,但几乎所有 Linux 发行版都默认支持。
2.1 基本操作
# 查看当前规则
iptables -L -n -v
# 清空所有规则(危险!先确保有带外访问)
iptables -F
iptables -X
# 设置默认策略:入站丢弃,出站放行
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
2.2 放行必要端口
在设置默认 DROP 之前,务必先放行 SSH 和你的代理端口,否则你会立刻断开连接:
# 放行 SSH(先放行再设 DROP 策略)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 放行代理端口(以 Reality 443 为例)
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 放行已建立的连接和关联流量(关键!)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 放行本地回环
iptables -A INPUT -i lo -j ACCEPT
# 设置默认丢弃
iptables -P INPUT DROP
-m state --state ESTABLISHED,RELATED 这条规则允许已建立的连接回包通过。没有它,你发出的请求能出去,但回应进不来——等于网络断了。2.3 UDP 端口放行
如果你使用 Hysteria2 或 TUIC 等基于 UDP 的协议,需要额外放行 UDP 端口:
# 放行 Hysteria2 UDP 端口
iptables -A INPUT -p udp --dport 8443 -j ACCEPT
# 放行 DNS 查询(如果 VPS 需要对外提供 DNS)
iptables -A INPUT -p udp --dport 53 -j ACCEPT
2.4 防暴力破解限速
对 SSH 端口添加连接限速,防止暴力破解:
# SSH 端口限速:每分钟最多 6 个新连接
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 6 --name SSH -j DROP
2.5 持久化规则
iptables 规则重启后会丢失,需要持久化:
# Debian / Ubuntu
apt install iptables-persistent -y
netfilter-persistent save
# CentOS / RHEL
service iptables save
2.6 代理服务器完整规则示例
#!/bin/bash
# VPS 防火墙初始化脚本 — Reality + SSH 场景
# 清空规则
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(建议改为非标准端口)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 放行 Reality(443/TCP)
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 放行 Hysteria2(8443/UDP,如需要)
# iptables -A INPUT -p udp --dport 8443 -j ACCEPT
# SSH 限速
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 6 --name SSH -j DROP
# 保存
netfilter-persistent save
三、nftables:iptables 的现代替代
nftables 是 iptables 的官方继任者,自 Linux 内核 3.13 起引入。语法更简洁、性能更好、支持原子规则替换(不会在更新规则时出现短暂的无规则状态)。Debian 12、Ubuntu 22.04+ 默认使用 nftables 后端。
3.1 检查系统是否使用 nftables
# 查看 nftables 版本
nft --version
# 查看当前规则集
nft list ruleset
3.2 基本操作
# 清空所有规则
nft flush ruleset
# 创建表和链
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }
nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }
3.3 放行必要端口
# 放行本地回环
nft add rule inet filter input iif lo accept
# 放行已建立连接
nft add rule inet filter input ct state established,related accept
# 放行 SSH
nft add rule inet filter input tcp dport 22 accept
# 放行代理端口(Reality 443)
nft add rule inet filter input tcp dport 443 accept
# 放行 UDP 端口(Hysteria2)
nft add rule inet filter input udp dport 8443 accept
3.4 一条命令搞定
把上面的规则合并成一条命令,方便一键部署:
nft add rule inet filter input iif lo accept \
\; ct state established,related accept \
\; tcp dport 22 accept \
\; tcp dport 443 accept \
\; udp dport 8443 accept
3.5 持久化 nftables 规则
# 导出当前规则
nft list ruleset > /etc/nftables.conf
# 启用 nftables 服务(重启自动加载)
systemctl enable nftables
systemctl start nftables
3.6 iptables 与 nftables 的关系
| 对比项 | iptables | nftables |
|---|---|---|
| 语法 | 命令式,规则分散管理 | 声明式,规则集整体管理 |
| 原子更新 | 不支持(逐条更新) | 支持(flush + 一次性加载) |
| 性能 | 线性匹配 | 集合匹配,大规模规则更快 |
| IPv4/IPv6 | 需分别用 iptables/ip6tables | 统一用 nft(inet 族) |
| 兼容性 | 所有发行版 | 内核 3.13+,新发行版默认 |
四、ufw:Ubuntu 的简化方案
ufw(Uncomplicated Firewall)是 Ubuntu 官方推荐的防火墙前端,底层调用 iptables 或 nftables,但大幅简化了操作。如果你用 Ubuntu,这是最省心的选择。
4.1 安装与启用
# 安装 ufw
apt install ufw -y
# 查看状态
ufw status verbose
4.2 配置规则
ufw 的规则语法非常直白:ufw allow [端口/协议]。
# 先放行 SSH(否则启用后会锁死自己)
ufw allow 22/tcp
# 放行代理端口
ufw allow 443/tcp
# 放行 UDP 端口(Hysteria2)
ufw allow 8443/udp
# 启用防火墙
ufw enable
# 查看最终状态
ufw status numbered
ufw delete 3 — 删除第 3 条规则ufw allow from 1.2.3.4 — 只允许特定 IP 访问ufw deny 3306/tcp — 显式拒绝某端口ufw reset — 重置所有规则(慎用)
4.3 代理服务器推荐 ufw 配置
#!/bin/bash
# Ubuntu VPS 防火墙初始化 — ufw 方案
# 重置(首次配置时)
ufw --force reset
# 默认策略
ufw default deny incoming
ufw default allow outgoing
# 放行必要端口
ufw allow 22/tcp comment 'SSH'
ufw allow 443/tcp comment 'Reality/VLESS'
# 如需 Hysteria2
# ufw allow 8443/udp comment 'Hysteria2'
# 启用
ufw --force enable
# 验证
ufw status verbose
4.4 ufw 日志
ufw 默认记录被拒绝的连接尝试,方便排查问题:
# 查看 ufw 日志
tail -f /var/log/ufw.log
# 或查看最近被拒绝的连接
grep "BLOCK" /var/log/ufw.log | tail -20
五、代理场景专用:端口规划建议
不同代理协议对端口的需求不同。以下是常见场景的端口规划:
| 协议 | 端口 | 协议类型 | 说明 |
|---|---|---|---|
| VLESS-Reality | 443 | TCP | 伪装成 HTTPS,必须用 443 |
| Trojan | 443 | TCP | 标准 TLS 伪装,通常用 443 |
| Hysteria2 | 自定义 | UDP | 推荐 8443 或 10086 等非标准端口 |
| TUIC v5 | 自定义 | UDP | 推荐 443 或自定义端口 |
| VLESS+WS+CDN | 443 | TCP | 走 Cloudflare CDN,443 |
| SSH | 22(建议改) | TCP | 改为非标准端口降低扫描风险 |
5.1 SSH 端口更换
将 SSH 端口从默认的 22 改为非标准端口(如 2222),可以大幅减少自动化扫描器的骚扰:
# 编辑 SSH 配置
vi /etc/ssh/sshd_config
# 找到 Port 22,改为
Port 2222
# 重启 SSH(先确认防火墙放行了新端口!)
systemctl restart sshd
5.2 多协议共存的端口规划
如果你同时运行 Reality 和 Hysteria2,端口规划可以这样:
# Reality: 443/TCP
# Hysteria2: 8443/UDP
# SSH: 2222/TCP
# iptables 规则
iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p udp --dport 8443 -j ACCEPT
# 或 ufw 规则
ufw allow 2222/tcp
ufw allow 443/tcp
ufw allow 8443/udp
六、出站控制:可选但有用
默认情况下出站流量不做限制。但在某些场景下,控制出站可以增强安全:
- 防止 VPS 被当作跳板:限制 VPS 只能访问特定目标,防止被入侵后用于攻击他人。
- 减少流量消耗:按量计费的 VPS 可以限制不必要的出站流量。
# 出站默认丢弃(先放行必要目标)
iptables -P OUTPUT DROP
# 放行 DNS 查询
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
# 放行 HTTPS(代理回源)
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
# 放行本地回环
iptables -A OUTPUT -o lo -j ACCEPT
# 放行已建立连接
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
七、常见问题排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 设置 DROP 后 SSH 断开 | 未先放行 SSH 端口 | 通过 VPS 控制台登录,添加 SSH 放行规则 |
| 代理能连但速度很慢 | UDP 端口未放行 | 检查 Hysteria2/TUIC 的 UDP 端口是否在防火墙中放行 |
| 重启后规则丢失 | 未持久化规则 | iptables: netfilter-persistent save;nftables: 保存到 /etc/nftables.conf |
| ufw 启用后无法连接 | 未放行 SSH | 通过控制台执行 ufw allow 22/tcp |
| 规则看似正确但不生效 | 规则顺序问题 / 网卡接口不匹配 | 检查 -i 参数指定的网卡名,调整规则顺序 |
| iptables 和 nftables 冲突 | 两者同时使用 | 选一个工具,不要混用。nft list ruleset 和 iptables -L 查看各自规则 |
7.1 排查被拒绝的连接
# iptables — 查看被丢弃的包计数
iptables -L -v -n | grep DROP
# ufw — 查看被拒绝的日志
grep "BLOCK" /var/log/ufw.log | tail -20
# nftables — 查看规则匹配计数
nft list ruleset -a
7.2 紧急恢复:通过控制台重置防火墙
如果被防火墙锁死,通过 VPS 控制台的 VNC/Serial 终端登录后:
# iptables — 清空所有规则
iptables -F
iptables -P INPUT ACCEPT
# nftables — 清空所有规则
nft flush ruleset
# ufw — 重置
ufw --force reset
八、三套方案选型建议
| 方案 | 适合谁 | 优点 | 缺点 |
|---|---|---|---|
| iptables | 老用户、CentOS/RHEL | 兼容性最好,资料最多 | 语法冗长,IPv4/IPv6 分开管理 |
| nftables | Debian 12+、追求现代语法 | 原子更新,统一 IPv4/IPv6,性能好 | 学习成本略高,旧发行版支持不完整 |
| ufw | Ubuntu 用户、追求简单 | 命令最简,一条搞定一个端口 | 高级功能受限,不适合复杂规则 |
对大多数代理用户来说:Ubuntu 用 ufw,Debian 用 nftables,CentOS 用 iptables。选你系统默认推荐的那个,不会错。