---
url: https://eoht.net/vps/settings/firewall-port.md
description: >-
  先识别 VPS 当前使用的防火墙，再用 iptables 或 firewalld 仅放行所需 TCP 端口，保留 SSH
  和现有规则，并检查服务监听、云安全组、IPv6 与规则持久化。
---

# VPS 开放防火墙端口：iptables 与 firewalld 命令 {#open-vps-firewall-ports}

下面以开放 Web 服务的 TCP `80`、`443` 端口为例。先确认应用确实需要这些端口，再选择当前正在管理规则的工具；Debian、Ubuntu、CentOS 等发行版名称不能直接决定应该运行哪组命令。

## 先检查现有规则和 SSH

保留当前 SSH 会话，确认云控制台或串行控制台可用。记录实际 SSH 端口及其允许的来源地址，不要默认一定是 `22`。先查看服务监听和可用工具：

```sh
sudo ss -lntp
command -v firewall-cmd ufw nft iptables
```

按已安装的工具查看状态：

| 工具 | 只读检查 | 后续操作 |
| --- | --- | --- |
| firewalld | `sudo firewall-cmd --state`、`sudo firewall-cmd --get-active-zones` | 服务正在运行时使用下方 firewalld 示例 |
| UFW | `sudo ufw status verbose` | 若显示 active，继续用 UFW 管理，不混用本页示例 |
| nftables | `sudo nft list ruleset` | 若由原生 nftables 配置管理，在原配置中添加规则 |
| iptables | `sudo iptables -S`、`sudo iptables -L INPUT -n -v --line-numbers` | 确认没有其他前端接管后，使用下方 iptables 示例 |

`iptables` 也可能使用 nftables 后端，因此能看到规则并不代表两套独立防火墙。若规则由容器平台、配置管理程序或云镜像脚本维护，应修改相应的来源配置，避免手工规则随后被覆盖。

## 使用 iptables 放行指定端口

这一组仅适用于直接维护 iptables 规则的主机。先备份 IPv4 规则，文件保存在当前登录用户的主目录：

```sh
rules_backup="$HOME/iptables-before-$(date +%Y%m%d-%H%M%S).rules"
sudo iptables-save > "$rules_backup"
```

确认备份命令成功且文件非空后，添加 TCP 端口规则。`-C` 检查相同规则是否存在，避免重复添加；`-I INPUT 1` 将允许规则插入 INPUT 链开头。

```sh
sudo iptables -C INPUT -p tcp --dport 80 -j ACCEPT ||
  sudo iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
sudo iptables -C INPUT -p tcp --dport 443 -j ACCEPT ||
  sudo iptables -I INPUT 1 -p tcp --dport 443 -j ACCEPT
sudo iptables -L INPUT -n -v --line-numbers
```

以上示例允许任意来源访问这两个端口。如需限制来源，应在检查和添加两条命令中都加上同一个 `-s 来源CIDR`。不要用清空规则或把全部默认策略改为 ACCEPT 来代替开放端口。

这里修改的是 IPv4。提供 IPv6 服务时，还要检查 `ip6tables` 或实际管理 IPv6 的规则，并保留 IPv6 所需的 ICMPv6 流量。

从另一台机器验证服务及新的 SSH 会话都正常后，再保存规则。只有已经安装并配置 `netfilter-persistent` / `iptables-persistent` 管理启动规则的主机，才使用：

```sh
sudo netfilter-persistent save
```

该命令保存当前规则集；先确认其中没有需要撤回的临时规则。其他发行版或管理方式应使用其已有的持久化机制，不能仅凭一次添加成功就认定重启后仍有效。

## 使用 firewalld 放行指定端口

适用于 firewalld 已运行并接管规则的主机。通过 `--get-active-zones` 找到外网接口或来源地址实际归属的 zone，再查看其规则。下面的 `public` 只是示例，必须按实际结果修改：

```sh
firewall_zone='public'
sudo firewall-cmd --zone="$firewall_zone" --list-all
sudo firewall-cmd --permanent --zone="$firewall_zone" --list-all
```

确认现有 SSH 放行规则正确后，先添加运行时规则：

```sh
sudo firewall-cmd --zone="$firewall_zone" --add-port=80/tcp
sudo firewall-cmd --zone="$firewall_zone" --add-port=443/tcp
sudo firewall-cmd --zone="$firewall_zone" --query-port=80/tcp
sudo firewall-cmd --zone="$firewall_zone" --query-port=443/tcp
```

外部访问和新的 SSH 会话验证通过后，再添加对应的永久规则：

```sh
sudo firewall-cmd --permanent --zone="$firewall_zone" --add-port=80/tcp
sudo firewall-cmd --permanent --zone="$firewall_zone" --add-port=443/tcp
sudo firewall-cmd --permanent --zone="$firewall_zone" --list-ports
```

运行时和永久配置已经分别添加，不必为这一步额外 reload。如果 firewalld 原本未运行，应先完成现有防火墙的迁移规划；不要直接启动它再尝试远程排错。

## 最后验证

* `ss -lntp` 能看到应用监听预期端口和地址。只监听 `127.0.0.1` 的服务不会因开放防火墙而对外提供服务。
* 云安全组、安全列表或网络 ACL 也允许同一协议、端口和来源；系统防火墙与云平台规则需要分别满足。
* 从外部网络访问实际服务，并新建一次 SSH 连接；已有 SSH 会话仍在线不足以验证新连接规则。
* 若要撤回，只删除本次新增的端口规则，并同步永久配置；不要删除执行前已经存在的规则。
