news 2026/10/20 7:32:00

Linux服务器防火墙实战:Web端口放行与SSH加固指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux服务器防火墙实战:Web端口放行与SSH加固指南

做运维这些年,几乎每次部署一台新的Linux服务器,头一件事就是确认防火墙规则是否已经到位。尤其是在服务器既要对外提供Web服务、又要保留SSH远程管理入口的场景下,防火墙到底怎么配、规则先后顺序怎么排、改了端口之后还要联动哪些配置,任何一个环节没想清楚,轻则网站访问不了,重则远程连接直接断开,只能跑机房。这篇文章把Web服务器和SSH远程服务这两类最典型的防火墙实战配置拆开讲,涵盖规则设计思路、具体命令、持久化方式和故障排查思路。适合刚接手Linux服务器的新手运维,也适合那些每次配防火墙都小心翼翼的“半个老手”。

1. 动手配置前:3种防火墙方案怎么选,数据包处理顺序为什么重要

1.1 按发行版选方案,别混用就行

很多人一上来就纠结“用iptables还是firewalld”,这个问题的答案其实很简单:看你系统的默认方案。CentOS/RHEL系列主流是firewalld,它构建在iptables(新版是nftables)之上,提供zone、service这些更高级的抽象;Debian/Ubuntu系统一般用ufw,它是iptables的封装,命令更短,适合快速配置;而最小化安装的服务器上,最常见的还是直接用iptables命令本身,因为内核里就是它,不依赖额外的服务。

方案适用系统特点适合场景
iptables几乎所有Linux发行版最底层、最灵活,命令直观最小化系统、脚本批量管理
firewalldRHEL/CentOS/Fedora系列zone抽象,支持动态加载,--permanent持久化企业生产环境、复杂规则管理
ufwDebian/Ubuntu系列命令简短,默认策略友好个人服务器、测试环境

这里要提醒一个很容易踩的坑:同一台机器上不要让firewalld和iptables-services同时开启。两个服务同时运行的时候,配置会互相覆盖,规则一会儿生效一会儿不生效,排查起来非常头疼。我见过不少历史遗留服务器就是这么个状态,最后只能二选一,把另一套服务停掉并禁用开机自启,才消停。选好一套方案之后,思路就顺着这套工具走,不要混着用。

1.2 数据包进出的顺序,决定了你的规则写法

可以把防火墙的INPUT链想象成小区门口的保安:所有想进入本机的数据包,都要在INPUT链这里接受检查,检查规则从上往下一条一条过,一旦某条规则命中,就不再往后看了。

对iptables来说,进入本机的数据包完整路径是PREROUTING→INPUT→ 本地进程,所以日常配置防火墙主要操作的就是INPUT链。理解了“自上而下匹配、命中即停”这个原则,就能解释很多规则为什么没生效。比如你在前面写了iptables -A INPUT -p tcp --dport 22 -j DROP,后面再写允许某个IP访问22端口的规则就没有意义了,因为包到DROP那条就已经被丢弃,根本走不到后面的放行规则。

同理,如果要实现“只允许某个IP段访问SSH,其余全部拒绝”,就必须把“允许”的规则写在前面,“拒绝”的规则写在后面。这个顺序问题,是我见过最多的配置错误来源之一,改规则之前一定先看一遍现有规则的顺序。

1.3 写规则前必须摸清的3个底细

配置前先确认三件事,能省下大量返工时间。

第一,当前防火墙状态和默认策略。执行iptables -L -n -v看现有规则和计数器,注意-P INPUT DROP意味着默认拒绝所有入站流量。第二,要放行的服务端口。ss -tlnp能告诉你Nginx、sshd到底在监听哪个端口,很多情况是配置里写的是8080,实际服务却只监听了80,白配一场。第三,客户端来源IP段。需要明确要不要做白名单限制,办公网、云跳板机的IP分别是什么,这样才能决定是否用-s参数限定来源。

这里顺便说一个很重要的操作顺序:如果打算把默认策略从ACCEPT改成DROP,一定要先把需要的放行规则全部加好,再改默认策略。因为一旦改成DROP,现有的SSH连接也会立刻断掉,如果规则没准备齐全,你连补救的机会都没有。这也是为什么后面我会强调用脚本一次性执行,而不是一条条敲命令。

2. Web服务器端口放行:用到的核心指令与常见变体

2.1 最基础的80和443放行,5条命令解决

如果你的系统用的是firewalld,最省事的方法是用内置的服务定义来放行HTTP和HTTPS:

systemctl start firewalld firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --reload

这里用--add-service=http而不是--add-port=80/tcp,好处是防火墙知道这是HTTP服务,配置文件里语义清晰,而且以后看zone的列表时一眼就能明白放行了什么。如果你用的是一台最小化的CentOS,里面只有iptables,那对应的写法是:

iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -j ACCEPT

如果防火墙的默认策略是ACCEPT,其实不放行也能访问Web端口;但默认策略改成DROP后就必须显式打开。这也是很多加固文档上来就建议把默认策略设置为DROP的原因——配合显式放行,让服务器只暴露必要的端口,其他一律进不来。另外注意,如果你的Web服务监听的是非标准端口,比如Nginx配置里写了listen 8080,那就要把80替换成对应的实际端口。

2.2 多域名、CDN回源和自定义端口的扩展写法

实际生产环境里,一个服务器上往往不止80/443这两个口。比如前面挂了负载均衡器或CDN时,回源可能走自定义端口;又比如同一个IP上跑了多个Web站点,用不同端口区分服务。firewalld的写法是:

firewall-cmd --permanent --add-port=8080-8090/tcp firewall-cmd --permanent --add-port=8443/tcp

iptables的对应写法:

iptables -A INPUT -p tcp --dport 8080:8090 -j ACCEPT iptables -A INPUT -p tcp --dport 8443 -j ACCEPT

把端口范围写到规则里,就能一次覆盖一批服务,比一条条加清晰得多。这里还要特别提一下SELinux:如果你启用了SELinux并且处于enforcing模式,那么仅仅在防火墙里放行端口可能还不够。Nginx绑定8443这类非标准端口时会被SELinux拦下来,现象就是防火墙规则明明加了,外部还是连不上,系统日志里出现SELinux is preventing nginx from binding之类的信息。这种情况需要额外放行SELinux的端口类型:

semanage port -a -t http_port_t -p tcp 8443

这个问题不算防火墙本身的责任,但在“网站打不开”的排查现场,很容易把时间浪费在防火墙上,所以放在Web服务器这一节提醒一句。

2.3 容易被忽略的回环地址与本地访问放行

默认策略是DROP的时候,很多人只放行了物理网卡上的端口,忘了本机内部的回环通信。比如Nginx和PHP-FPM之间的通信走127.0.0.1:9000,Redis、数据库客户端也都经常走本地回环。如果回环接口被默认策略挡住,会出现服务之间互相访问不了的奇怪问题,而外部访问却是通的,特别让人迷惑。

所以无论你用哪种方案,落地规则时都建议在第一行放行lo接口:

iptables -A INPUT -i lo -j ACCEPT

firewalld在默认的public zone里其实会放行lo和已建立的连接,但iptables直管模式下不会。这条规则写成第一个很重要,因为防火墙是从上到下匹配的,放在最前面能确保所有回环流量都放行,不会再被后面的拒绝规则拦掉。我见过不止一次,默认策略DROP之后本地MySQL连不上,查了半天外部端口,最后发现是回环被挡,加完这条立刻恢复。

3. SSH远程服务的防火墙加固:来源限制、端口变更和防暴力破解

3.1 只放行可信来源IP,规则顺序别记反

SSH是一个长期监听22端口的管理入口,不管怎么加固,最理想的防火墙策略是“除了我信任的来源,其他一律不要想连进来”。iptables下可以这样写:

iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 22 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j DROP

第一条放行整个192.168.1.0/24网段访问22端口,第二条拒绝其他所有来源访问22端口。重点是两条的顺序不能反,如果把DROP写前面,所有SSH连接都会在第一条被丢弃,后面的放行规则形同虚设。

firewalld的表达方式没那么直接,用rich rule来实现来源限制:

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="22" protocol="tcp" accept' firewall-cmd --permanent --add-rich-rule='rule family="ipv4" port port="22" protocol="tcp" drop'

为什么不直接--add-service=ssh再加来源限制?因为--add-service=ssh是对所有人开放的,它不包含“允许某个网段”这种条件,所以这种带来源地址的规则必须用rich rule。如果你对rich rule语法不熟,可以先用firewall-cmd --add-rich-rule='...' --timeout=60试跑一下,验证无误后再加--permanent,避免写错语法把自己锁在外面。

3.2 修改SSH端口的完整联动流程

不少人对SSH默认22端口被全网扫描感到头疼,选择把端口改成高位。改端口能挡住相当一部分自动化扫描脚本,但重点是别把防火墙配置漏了。我的习惯顺序是:

先放行新端口,再改sshd配置。比如准备改成2222:

firewall-cmd --permanent --add-port=2222/tcp firewall-cmd --reload

然后修改/etc/ssh/sshd_config,把Port 22改成Port 2222,最后systemctl restart sshd。重启完立刻开一个新终端,用新端口去连,确认能连上之后,再把旧的22端口从防火墙上移除。

这里强调一个原则:必须先放行新端口,再改sshd配置。否则SSH服务重启之后监听的是新端口,但防火墙里没有放行记录,当前这个连接虽然还活着,但只要一断就再也进不来了。另外,SELinux对SSH端口同样有控制,enforcing模式下改端口需要同步放行:

semanage port -a -t ssh_port_t -p tcp 2222

如果你不确定SELinux是否拦截,可以临时用setenforce 0验证一下,确认是无碍后再恢复enforcing。不过这只是排查手段,不要长期关掉SELinux。

3.3 fail2ban与防火墙规则的配合姿势

除了防火墙本身的静态规则,强烈建议给SSH加上fail2ban这类动态封禁工具。它的工作方式并不神秘:监控sshd日志,某个来源IP在短时间内反复认证失败,就往防火墙里插入一条临时拒绝规则,过期自动删。这在防火墙层面是一个很好的补充,尤其适合无法用白名单限制来源的场景。

在iptables环境下,fail2ban通常会创建一个独立的规则链,比如f2b-sshd,再把它插入INPUT链的最前面。这时候要注意:如果自己在INPUT链里显式写了-A INPUT -p tcp --dport 22 -j ACCEPT,fail2ban插在最前面的链依然会优先被匹配,所以不用担心自己的允许规则把封禁规则“顶掉”。

在firewalld环境下,fail2ban的默认action会调用firewall-cmd --add-rich-rule动态加规则。我实测下来两者配合都比较顺畅,前提是不要手动停掉系统自带的firewalld服务,否则动态加规则会失败。配置完fail2ban之后,可以用fail2ban-client status sshd查看当前封禁的IP列表,确认规则确实生效了。

4. 规则持久化与线上改动规则的应急处置

4.1 不同方案下的持久化做法

在线敲的iptables规则默认重启后全部丢失,这是新手最容易踩的坑。服务器一重启,辛辛苦苦配的规则全没了,默认策略可能也回到了ACCEPT,等于门户大开。持久化的方法按方案区分。

firewalld在配置时只要带了--permanent,再执行--reload就已经持久化了,规则会写入配置文件。iptables的持久化,Debian/Ubuntu下常用:

iptables-save > /etc/iptables/rules.v4

CentOS/RHEL如果装了iptables-services,可以直接执行service iptables save,这条命令会把当前规则保存到/etc/sysconfig/iptables,下次开机自动加载。ufw则是一边配置一边持久化,不需要额外的保存动作。

这里有个细节要留意:iptables-save > 文件只是把规则写到了文件里,如果后期又增删了规则,记得重新执行保存,否则下次重启恢复的是旧规则。你以为自己在控制线上配置,实际重启之后又是另一套,很容易造成安全隐患。

4.2 改规则前的备份和应急通道

线上的服务器改动防火墙,最怕的就是把管理通道封死。我现在的习惯是:动手之前先做三件小事。

第一,备份当前规则:

iptables-save > ~/iptables-$(date +%F_%H%M).bak

第二,确认自己有没有带外管理通道,比如硬件的远程管理卡、虚拟机的网页控制台。有了它,万一规则把SSH封了,还能从管理界面进去恢复。

第三,改动较大时,给自己留一个“自动撤销”的保险。比如用at命令安排一个两分钟后清空防火墙的任务:

echo "iptables -P INPUT ACCEPT; iptables -F" | at now + 2 minutes

如果两分钟内规则验证没问题,就把这个任务取消掉;如果出了问题,等它自动执行就恢复了。这个技巧在远程操作时特别有价值,相当于给操作加了一个自动回滚的保险丝。

4.3 用脚本管理规则,而不是每次都手敲命令

生产环境我强烈建议把一组规则整理成一个bash脚本,而不是每次手工敲命令。好处有两个:一是规则变更可以被版本管理工具追踪,二是下次新装服务器可以直接复用。

一个基于iptables的基础脚本大概长这样:

#!/bin/bash iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 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 iptables -A INPUT -j DROP

脚本里特意加了-m conntrack --ctstate ESTABLISHED,RELATED,让已经建立的连接和关联连接放行。这样服务器主动发起的出站连接,它的回应包也能顺利回来,不会因为INPUT默认策略是DROP而全部卡死。这个细节非常重要,不加的话,服务器能连出去但收不到应答,表现就是各种“超时”。

对于firewalld环境,类似的思路是写一个包含firewall-cmd --permanent命令的初始化脚本,跑完一遍之后--reload,效果一样。以后换机器,直接改改端口号就能复用。

5. 常见故障排查实录与避坑经验

5.1 端口放行了,网站还是打不开?

防火墙配置完,最常见的问题就是:我明明把80/443放行了,外部还是打不开网页。这时候我建议按顺序查。

首先看服务本身有没有监听。执行ss -tlnp | grep :80,如果输出里监听地址是127.0.0.1:80,那说明服务只在本机回环上监听,外部网卡根本收不到流量,这和防火墙没有关系,需要把服务监听地址改成0.0.0.0:80或者对应的内网IP。

接着看防火墙规则是否真的加载了。执行iptables -L -n -v | grep :80,看计数器是否在增长。如果计数器一直是0,说明规则没有匹配到流量,问题大概率在更前面——比如云平台的安全组或者物理网络。

最后还要检查是不是加到了firewalld的非默认zone里。很多人把规则加到了非默认zone,但网卡还是挂在public zone上,规则等于没加。用firewall-cmd --get-active-zones看一下网卡归属,再对照实际加的zone,这个点很容易忽略。

5.2 SSH连不上,但规则看起来是对的

SSH连接失败分几种情况,不能一概而论。连接超时,大概率是被防火墙DROP了;连接被拒绝(Connection refused),多半是sshd本身没监听或监听端口和你连的不一致;提示认证失败,才轮到密钥、密码和fail2ban封禁的问题。

如果规则里写了来源IP白名单,先确认你的出口IP是否在这个范围内。固定IP办公环境还好说,家庭宽带动态IP很常见,今天能连明天就可能连不上。遇到这种情况,把-s的范围放宽,同时优先配合fail2ban兜底,而不是一味收紧白名单。

另外提醒一下,测试SSH防火墙规则的时候,千万不要在已经建立的连接里直接测试自己这条规则。比如你本来就SSH在上面,然后针对同一路径修改了规则,当前连接不会立刻断开,但新连接已经进不来了,等你反应过来时连接也断了。正确做法是从另一台机器、另一个网络环境发起测试,保证测试的是新建连接路径。

5.3 防火墙排查中容易被忽略的4个细节

第一个细节是匹配顺序。用iptables -I插入规则时会插到最前面,用-A追加会放到最后。如果你原有DROP规则在前,新放行规则在后,放行规则永远不会被匹配。查规则的时候不要只看有没有,还要看顺序对不对。

第二个细节是默认策略。很多人执行iptables -F清空规则却忘了默认策略还是DROP,清完之后网络可能更不通了。同理,修改默认策略的顺序也很有讲究,一定是先加放行规则,再改默认策略,否则操作到一半就断连了。

第三个细节是firewalld与iptables同时存在的冲突。有些历史遗留服务器,两个服务都在跑,你在firewalld里加了一条规则,实际却被iptables里的旧规则拦住了,两边规则不一致,排查体验非常差。建议选一套并明确停掉另一套,避免这种隐性问题。

第四个细节是重启验证。无论怎么配,配完之后建议主动重启一次系统,然后看规则是否自动恢复、服务是否正常启动。很多问题只有在重启后才会暴露,比如持久化文件没生效、服务依赖顺序不对。这个验证成本很低,但能帮你发现不少隐患。

最后再分享一个小习惯:在我维护的服务器上,防火墙规则文件都会放到固定目录并且用脚本统一管理,每次变更后在变更记录里留一行说明。这不算复杂,但时间长了会发现,排查问题的效率比其他方式高很多。毕竟防火墙这种配置,出问题的时候往往是半夜,少折腾一步就能省下大把时间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 7:31:55

AgentCore架构解析:面向生产环境的确定性智能体设计

1. 这不是又一个“智能体框架”的简单升级最近在某云厂商技术峰会现场听到“AgentCore”这个词时,我下意识摸了出去的U盘——不是为了拷资料,是条件反射想插进笔记本跑个本地验证。这反应背后,是过去两年里被至少七套标榜“全栈Agent开发平台…

作者头像 李华
网站建设 2026/10/20 7:31:54

AgentCore:智能体工程化的四大支柱与生产实践

1. 这不是又一个“智能体框架”,而是Agent工程化的分水岭最近刷技术社区,几乎每条高赞帖都绕不开“AgentCore”三个字。阿里云在QCon上海站正式发布AgentCore后,我第一时间拉了源码、搭了本地环境、跑了三个典型场景——不是为了赶热度&#…

作者头像 李华
网站建设 2026/10/20 7:30:23

基于人工势场法的无人机集群三维避障Matlab仿真实现与调参

做无人机集群仿真,最难的不是让某一架飞机飞起来,而是让一群飞机在同一个三维空间里既不撞障碍物、又不互相撞,还能整体到达目标区域。我最早接触这个课题时,第一反应是找现成的开源方案,结果翻了一圈,工业…

作者头像 李华
网站建设 2026/10/20 7:30:21

SQL窗口函数巧解连续日期状态区间问题

LeetCode 数据库题单做到后面,会发现大量题目其实是在为真实世界的报表需求做“降维”。这道“报告系统状态的连续日期”就是非常典型的一道。题面很短:系统每天运行,成功日期和失败日期分别记在两张表里,要求把某个时间段内所有“…

作者头像 李华
网站建设 2026/10/20 7:28:45

两级式三相光伏逆变并网系统Simulink仿真完整搭建与调试

几个月前我把一套“两极式三相光伏逆变并网系统”的Simulink仿真模型完整跑通了。从最开始的光伏阵列建模,到Boost升压、三相逆变、并网控制,再到最后的说明文档和参考文献整理,整个过程踩了不少坑。这篇记录打算把这套模型的搭建思路、控制链…

作者头像 李华
网站建设 2026/10/20 7:27:52

基于ESP32的鱼缸智能监控系统:GitHub项目dz-1032完整实战

做过物联网或者嵌入式DIY的朋友应该都有这种感觉:真正难的不是写代码,而是把一堆传感器、执行机构、通信协议组合成一个能持续稳定运行的小系统。这个代号为“dz-1032”的鱼缸智能监控系统,恰好就是这样一个足够典型、又足够落地的项目。它把…

作者头像 李华