跳转到内容
严选跨境网络服务与流媒体推荐
实机测速保障 · 专属折扣
声明:以上服务由影迷漫游评测实验室进行晚高峰抽测与流媒体解锁验证。专属链接包含推广支持,不增加您的购买成本。

Linux 防火墙端口开放完全指南 | iptables、firewalld 与 UFW 配置教程 ​

Linux Firewall Port Configuration

防火墙端口到底管什么 ​

一台服务器对外提供的服务,最终都落在一扇扇端口上。SSH 监听二十二号端口,网站走八十和四百四十三号端口,数据库、缓存、面板各有自己的端口。端口本身只是门牌号,防火墙做的事情,是站在门口决定谁可以敲门、敲哪扇门、从哪个方向来。

理解防火墙,先分清两个方向。入方向是指从外面进入本机的连接,比如有人从自己的电脑连你的 SSH,或者浏览器请求你的网站。出方向是指从本机主动发出的连接,比如服务器去拉取软件包、请求第三方接口、给自己发告警邮件。大多数服务器的默认姿态是:入方向能关就关,只给确实需要对外提供的服务留门;出方向基本放行,因为服务器自己发起的连接通常是业务需要的。把这两个方向混在一起,是新手最常见的困惑来源——明明只想让别人访问网站,却把出方向也收紧,结果服务器连软件源都连不上。

另一个关键概念是默认拒绝。默认拒绝的意思是:没有明确放行的,一律不让进。这和“默认放行、只封已知的坏东西”正好相反。默认拒绝的好处是,新装了一个服务、忘了关端口,防火墙会先替你挡住;代价是,每上一个新服务都要记得来防火墙补一条规则。刚接触时会觉得麻烦,但这正是防火墙的价值所在:它把“暴露面”变成一份需要主动维护的清单,而不是一堆不知不觉敞开的门。

还有一条容易被忽略的规则:已经建立的连接要放行。SSH 连上之后,后续的数据包属于同一条连接,不能再按“入方向新连接”的标准去卡。iptables 里这条规则通常写在最前面,UFW 和 firewalld 则在内部替你处理好了。你不需要每次都操心它,但要知道它的存在——否则排障时会困惑,为什么规则明明没放行某个端口,已经连上的会话却还能继续传数据。

端口号本身只是约定,不是铁律。网站默认走八十和四百四十三,数据库默认走三千三百零六,但服务完全可以监听在任何端口上,改个配置就能换。因此防火墙规则不应该跟着“常见端口表”背,而应该跟着本机实际在监听的服务走。动手之前先看一眼监听列表,哪些端口真的在对外服务,哪些是只给本机用的,哪些是装软件时顺手带起来却早已没人用的,清单先对齐,再写规则。反过来,规则写完也要回头核对:每一个放行项都能对应到一个真实存在的服务,每一个监听中的服务都有对应的规则或者被明确拒绝的理由。端口表背得再熟,也替代不了这一次核对——背出来的规则管的是“一般服务器”,核对出来的规则管的才是你这台服务器。

三个工具的思路差异 ​

Linux 上最常见的三个防火墙工具,表面上是命令不同,实际上是抽象层次不同。选哪个工具,与其说看功能强弱,不如说看你愿意在哪个层次上思考问题。

UFW 的思路是“把规则写成人话”。它的命令贴近日常语言:允许某个端口、拒绝某个来源、查看带编号的规则列表。UFW 本身并不直接处理数据包,它只是把你的规则翻译成底层的 iptables 规则,再交给系统执行。这种设计让它特别适合单机场景:规则不多、变化不频繁、管理员就是写规则的人。它的短板也来自这种简单:规则一多、需要按网段和服务做精细组合时,人话式的命令会显得笨拙,而且它对动态调整的支持有限,改规则基本就是改一次生效一次。

firewalld 的思路是“按场景分组”。它引入了区域的概念:同一台机器面对公共网络、内部网络、可信网络时,可以套用不同的规则集合;它还引入了服务的概念,一条“允许网站服务”的规则背后其实是一组端口,改服务定义就等于同时改了这组端口。更重要的是,firewalld 区分运行时规则和永久规则:不加永久标记的改动只在内存里生效,重启就消失,适合先试后定;确认无误再写成永久规则。这个两层设计对生产环境很友好——你可以先临时放行一个端口做测试,验证通过再固化,不用担心一次手滑就把规则永久写坏。它的代价是概念多一些,刚上手要花点时间理解区域、服务、运行时与永久这几层关系。

iptables 的思路是“直接操作数据包的旅程”。它不提供高层抽象,而是让你面对表和链:数据包进入本机走 INPUT 链,离开本机走 OUTPUT 链,经过本机转发走 FORWARD 链,每条链上按顺序匹配规则,第一条命中的规则决定命运。这种底层视角的好处是无所不能,转发、地址转换、按连接状态放行、按数据包特征丢弃,都能表达;坏处是规则写起来长,顺序错了就全错,而且默认不持久化,重启后规则就没了,需要额外工具保存和恢复。iptables 适合两种人:需要实现 UFW 和 firewalld 表达不了的复杂策略的人,以及想真正理解 Linux 网络栈的人。对于日常的“开几个端口”需求,用它属于杀鸡用牛刀。

选型上有一个务实的原则:跟着发行版的默认走。Ubuntu 和 Debian 默认带 UFW,RHEL 系默认带 firewalld,用默认工具意味着文档、社区经验和系统集成都是现成的。除非你有明确的理由——比如要写一套跨发行版的自动化脚本,或者要实现转发和地址转换这类底层策略——否则没必要在三个工具之间来回横跳。工具换来换去,规则的理解成本才是真正的开销。

开放与关闭端口的操作 ​

动手之前,先定一条铁律:改默认策略之前,先放行 SSH。把入方向默认改成拒绝的那一刻,所有没明确放行的连接都会被挡住,包括你正在用的这条 SSH 会话。正确的顺序永远是:先加一条放行 SSH 的规则,确认它生效,再去改默认策略。更稳妥的做法是保留一条控制台通道,比如云厂商提供的网页控制台,这样即使规则写错,也能从带外登录进去修复,而不是只能等服务商救援。

用 UFW 时,操作围绕几条命令展开。先看状态,确认防火墙当前是否启用;启用之前,先把默认策略定下来:入方向拒绝、出方向允许。然后按需放行端口,放行时尽量写明协议,TCP 和 UDP 是两回事,只写端口号会同时放行两种协议,未必是你想要的。放行来源受限的服务时,写清楚允许哪个地址或网段访问哪个端口,比如数据库只接受内网网段的连接。删除规则有两种方式:按编号删适合规则已经乱了的时候,按内容删适合你还记得当初写了什么。UFW 的规则改动即时生效,不需要额外重载,但这也意味着手滑的代价是即时的,改之前看一眼规则列表是个好习惯。

bash
# 查看状态
sudo ufw status

# 设置默认策略:入方向拒绝,出方向允许
sudo ufw default deny incoming
sudo ufw default allow outgoing

# 先放行 SSH,再启用防火墙
sudo ufw allow 22/tcp
sudo ufw enable

# 开放 Web 服务
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# 只允许内网网段访问数据库(地址为示例,请按实际网段改)
sudo ufw allow from 192.168.1.0/24 to any port 3306

# 查看带编号的规则,按编号删除
sudo ufw status numbered
sudo ufw delete 3

# 按内容删除
sudo ufw delete allow 80/tcp

用 firewalld 时,要时刻记得运行时与永久的区别。不加永久标记的改动只影响当前运行状态,适合测试;确认要保留的规则,必须带上永久标记,再重载一次让它生效。漏掉重载是 firewalld 新手最常见的失误:规则写进去了,测试却不通,原因往往是还没重载。firewalld 更推荐用服务名而不是端口号来放行,网站服务对应八十和四百四十三两个端口,用服务名写一条规则,比写两条端口规则更易读,日后服务端口有调整,改服务定义即可。需要精细控制来源时,firewalld 提供了富规则,可以在一条规则里同时写明来源地址、端口或服务和放行动作,写起来长,但表达力完整。

bash
# 查看当前区域的规则
sudo firewall-cmd --list-all

# 放行 Web 服务(永久生效,随后重载)
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --reload

# 放行单个端口
sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
sudo firewall-cmd --reload

# 只允许某个地址访问 SSH(地址为示例,请按实际管理地址改)
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="203.0.113.50" service name="ssh" accept'
sudo firewall-cmd --reload

# 删除端口或服务后同样要重载
sudo firewall-cmd --zone=public --remove-port=8080/tcp --permanent
sudo firewall-cmd --reload

用 iptables 时,顺序就是一切。规则按从上到下的顺序匹配,第一条命中的规则决定数据包的命运,后面的规则不再看。因此写规则的顺序通常是:先放行本地回环,再放行已建立和相关的连接,再放行你明确要开放的端口,最后由默认策略兜底拒绝。把“允许已建立连接”这条漏掉,会出现一种诡异现象:新连接能建,建好之后数据却传不回来。把默认拒绝写在放行 SSH 之前,会出现更严重的现象:你直接把自己锁在门外。iptables 的规则默认不保存,配好之后要立刻保存一次,Debian 系可以用持久化工具,RHEL 系可以用系统自带的保存方式,或者手动把规则导出到文件,写进开机恢复流程。只配不保存,等于重启后全部白干。

bash
# 查看当前规则(带行号,方便按号删除)
sudo iptables -L INPUT -n --line-numbers

# 先放行 SSH,再把入方向默认策略改成拒绝
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -P INPUT DROP

# 放行已建立和相关的连接(新连接建好后的后续数据包靠它)
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 放行 Web 服务与本地回环
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -i lo -j ACCEPT

# 只允许内网网段访问数据库(网段为示例,请按实际网段改)
sudo iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 3306 -j ACCEPT

# 按行号删除一条规则
sudo iptables -D INPUT 3

# 保存规则(Debian/Ubuntu 持久化工具,安装后执行一次即可)
sudo apt install iptables-persistent -y
sudo netfilter-persistent save

顺带提一句过时写法的修正。老教程里常见两处现在不推荐的写法:一是 RHEL 系用 yum 安装 firewalld,新版系统已经用 dnf 接管了软件包管理,命令要跟着换;二是 iptables 里用 -m state --state 匹配连接状态,这套写法仍能工作,但新版系统更推荐 -m conntrack --ctstate,语义相同,兼容性更好。照抄老教程之前,先确认发行版和工具链的现状,命令本身没错,但时代变了,写法也该跟着变。

关闭端口和开放端口同样重要,而且往往更能体现管理水平。服务下线了,对应的防火墙规则要同步删掉;临时测试开的端口,测试完要收回;接手别人的服务器,第一件事应该是把规则列表从头读一遍,删掉那些不知道用途的放行项。防火墙规则和代码一样会腐烂:当初为了调试开的口子,半年后没人记得为什么开着,却一直在替你扩大暴露面。定期审计不是洁癖,是防火墙这套机制成立的前提——默认拒绝只有在规则清单真实可信时才有意义。

只放行必要端口的收尾原则 ​

规则写完之后,还有几条收尾原则,决定了这套防火墙是真安全还是只有安全感。

第一条是最小权限:只开放确实需要对外提供的端口。网站需要八十和四百四十三,就只开这两个;管理面板如果只给自己用,就不要对全网开放,改走 SSH 隧道或者只放行自己的管理地址。数据库、缓存这类服务,原则上只接受内网连接,对公网放行数据库端口是最常见的严重失误之一。判断一个端口该不该开,有个简单的标准:这个服务的调用方是谁?如果调用方是公网用户,开;如果调用方是同一台机器或者内网里的另一台机器,就只对那个来源开;如果答不上来,先不开,等有人提出需求再补。

第二条是来源限制比端口开放更重要。同样是开放 SSH,对全网开放和只对管理地址开放,风险完全不在一个量级。管理类入口——SSH、面板、数据库——都应该加上来源限制,哪怕只是限制到一个网段。来源限制不是万能的,地址可以伪造,网段也可能被渗透,但它把攻击者的门槛从“全网扫描到就能试”抬高到了“先拿到内网立足点”,这一步的价值很大。配合密钥登录和失败封禁,管理入口的安全性会再上一个台阶,这部分可以参考站内的 SSH 密钥与 Fail2ban 教程。

第三条是改端口不等于加安全。把 SSH 从二十二号改到一个冷门端口,能减少扫描器日志里的噪音,但防不住有针对性的扫描——端口扫描本来就是把所有端口扫一遍,冷门端口一样会被发现。改端口可以作为降噪手段,但不能替代来源限制和密钥登录。同样,关掉 ICMP 也不是什么高明的安全措施,它只会让排障变得更困难,真正的安全来自规则本身,而不是让服务器假装不存在。

第四条是审计和备份要形成习惯。每月花几分钟看一次规则列表:哪些规则还在用,哪些服务已经下线,哪些临时放行忘了收回。备份同样重要,规则文件丢了、服务器迁移了、重装系统了,能从备份里恢复规则清单,比凭记忆重写一遍可靠得多。UFW 的规则文件、firewalld 的配置文件、iptables 的导出文件,都值得放进你的备份流程。备份的频率不需要高,规则有变化时顺手存一份就够了。

误封自救 ​

防火墙配错最典型的后果,就是把自己锁在门外。遇到这种情况,先别慌,锁死的原因通常不出以下几种,按顺序排查最省时间。

第一种是 SSH 规则本身的问题:改了默认策略却忘了放行 SSH,或者改了 SSH 端口却忘了同步改防火墙规则。自救的路径是带外通道:云厂商的网页控制台、服务商提供的 VNC、机房的物理终端,都是不走 SSH 的登录方式。登进去之后,先临时禁用防火墙确认是不是防火墙的问题,恢复连接后再一条一条查规则,补上缺失的放行项,重新启用。预防比自救重要:改规则之前先确认控制台通道可用,改完之后不要立刻断开当前会话,开一个新会话测试连通性,确认新会话能进来,再断开旧会话。

第二种是端口明明放行了,服务还是访问不了。这时候问题往往不在防火墙,而在防火墙之外。先确认服务本身有没有在监听这个端口,服务没起来,防火墙放行再多也没用。再确认云服务商的安全组:很多云服务器有两层防火墙,系统里的防火墙放行了,云控制台的安全组没放行,流量到不了机器。还有 SELinux 这类强制访问控制,它会在应用层再卡一道,表现为防火墙全开、服务监听正常、外部依然连不上,临时放宽 SELinux 测试一下,往往就能定位。Docker 用户还要多看一层:容器端口映射走的是另一条链,UFW 和 Docker 的链顺序问题是老生常谈的坑,表现为容器端口时通时不通,重启防火墙之后行为又变了。

第三种是临时测试留下的烂摊子。调试时临时开放了一个端口,问题解决了,规则却忘了删,几个月后这个端口还在对外敞着。避免的方法很简单:临时规则写在纸上或者记在任务清单里,测试完立刻删;firewalld 用户可以用运行时规则做测试,重启即失效,天然带过期机制;UFW 和 iptables 用户则要在测试结束时手动收回。临时放行本身不是问题,临时放行之后没有收回才是问题。

防火墙端口管理说到底是一项清单管理:清单上每一项都要有存在的理由,每一项的来源和用途都要说得清楚。工具选哪个、命令怎么写,都是次要的;真正决定安全水位的,是这份清单是否真实、是否最新、是否有人定期看它。把清单维护好,防火墙才算配完了。

相关教程推荐 ​


延伸阅读 ​

免责声明

本文仅供技术交流和学习参考。涉及第三方服务的链接可能包含 sponsored 标记,请自行核实服务条款、价格和可用性,并遵守当地法律法规。