ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux防火墙封禁高危端口实战:445/3389/6379与远程保命

Linux防火墙封禁高危端口实战:445/3389/6379与远程保命 一台刚交付的云主机从拿到公网 IP 到被第一波扫描撞上门中间通常撑不过几个小时。日志里刷得最多的往往是 445、3389、6379 这几个熟面孔——有人拿它们跑漏洞利用有人拿它们试空口令也有人只是批量扫一遍留着以后用。很多同行把Linux 防火墙封禁高危端口命令当成一条条记不住的语法去背结果真到线上操作时要么是规则写了没生效要么是重载那一刻把自己踢出 SSH要么是发现容器里的端口压根绕过了主机的规则链。这篇就把我在物理机、云主机、容器宿主机上反复用过的那套做法完整摊开从为什么要封讲到封完怎么验证怎么保证不把自己关在门外命令都能直接抄但更重要的是每一步背后的判断依据。1. 445、3389、6379 为什么总在第一波扫描名单里1.1 端口数量与攻击面的关系并不是线性增长一台默认安装完的 Linux监听端口通常不超过二十个但真正对公网开放的往往只有那么三四个。麻烦在于开放的那几个端口背后挂着的服务性质差别极大22 端口是远程管理入口封了你就上不去443 端口是业务入口封了业务就死而 445、111、2375 这类端口很多情况下是安装某个软件时被顺手带起来的管理员自己都不一定知道它在听。扫描器不关心你的业务逻辑它只做一件事把 1 到 65535 挨个敲一遍把回应的端口记下来然后拿去比对漏洞库。所以攻击面的大小本质等于对外可达的端口数量 × 每个端口背后服务的脆弱程度。封禁高危端口的价值就是把第二个乘数直接砍掉——这个端口根本不回应再多的漏洞库条目也无从下手。这里有个容易被忽略的细节风险不只来自你主动开放还来自默认监听。Redis 默认配置在某些版本里监听 0.0.0.0MongoDB 早期版本默认不开认证Docker 的远程 API 一旦以-H tcp://0.0.0.0:2375启动就等于把整台机器交出去。这些都不是管理员决定的是软件默认行为决定的而防火墙恰好是唯一能在不改动软件配置的前提下兜住底的那一层。这也是为什么我一直建议能在服务配置里改监听地址的优先改配置改不动的、来不及改的先用防火墙挡上两者叠加才踏实。1.2 常见高危端口清单与它们各自的危险来源把高危端口简单理解成别人常扫的端口是不够的每个端口背后都有一条具体的风险链路。我按实际遇到过的频率整理了一张表方便你对照自查。端口协议对应服务风险来源21TCPFTP明文传输凭据、匿名登录、历史溢出漏洞23TCPTelnet全明文凭据可被直接嗅探135/137/139TCP/UDPNetBIOS / RPC内网信息泄露、横向移动的跳板445TCPSMB无需认证即可触发历史漏洞影响面极大111TCP/UDPrpcbind暴露 NFS 挂载关系配合 2049 使用2375TCPDocker Remote API未授权即可创建特权容器接管宿主机3306/5432/1433TCPMySQL / PostgreSQL / SQL Server弱口令爆破、公网直接拖库6379TCPRedis默认无认证可写文件、可反弹执行11211UDPMemcached放大反射也会被拿来做数据泄露9200TCPElasticsearch早期版本无认证索引数据全裸27017TCPMongoDB早期默认无认证批量被清库3389TCPRDP爆破强度最高的入口之一5900TCPVNC弱口令、无认证模式445 端口被反复点名原因值得单独说清楚SMB 是文件共享协议设计上服务于内网可信环境认证流程复杂且历史实现中出过大量问题一旦被触发攻击者拿到的往往不只是文件读取权限还可能直接执行代码。更关键的是它的传播特性——一台机器中招后会自动向同网段其他 445 端口发起连接这让它成为大规模蠕虫式传播的首选通道。所以哪怕你的服务器根本不提供文件共享只要 445 在监听就应该当成零容忍项处理。1.3 封端口是止损不是修复需要说清楚的是态度问题。封禁端口解决的是外部够不着但服务本身的漏洞、弱口令、错误配置一点没变。如果有台内网机器已经被控制攻击者从内网发起连接你的公网防火墙规则完全拦不住。所以正确的心态是封端口属于收缩暴露面的第一步是给后续修复争取时间的止损动作绝不能替代打补丁、改口令、收紧服务配置这些根本工作。我自己的处理顺序通常是先摸清监听、再封高危端口、同时排期修配置最后复查是否还有必要保留该端口的对外可达性。三步里防火墙是最快能落地的一步也是唯一能在凌晨两点不重启业务的前提下完成的一步。2. 动手封之前先把本机的监听底账摸清楚2.1 ss 与 netstat 到底该用哪个老教程里清一色是netstat -tulnp但 net-tools 包在新版发行版里已经默认不装了ss是 iproute2 套件的一部分几乎必然存在速度也快得多。看监听端口的常用写法是ss -lntup逐个参数解释一下-l只看监听状态-n不做域名和服务名解析直接显示数字端口避免看到一堆mysqlssh之类的别名反而对不上规则-t看 TCP-u看 UDP-p显示占用端口的进程。加上-p需要有 root 权限普通用户跑出来进程那一列是空的这点很多人会误以为是命令有问题。如果只想看某个具体端口可以用过滤表达式ss -lntp sport :445UDP 端口千万别漏掉。Memcached 走 11211/UDP、SNMP 走 161/UDP、有些 DNS 相关服务走 53/UDP只查 TCP 会让你以为一切干净。2.2 0.0.0.0 和 127.0.0.1 的区别决定了要不要封ss输出里最左边那一列是本地地址这一列是判断暴露面的核心依据127.0.0.1:6379只接受本机回环连接外部根本连不上防火墙封不封它意义不大。0.0.0.0:6379监听所有网卡的 IPv4 地址只要主机有公网 IP 且网络可达外部就能连。[::]:6379IPv6 的等价写法同样意味着全监听。192.168.1.10:6379只监听指定网卡地址暴露范围限于该网段。很多我明明封了 445 怎么还在被扫的情况最后查出来是服务监听在 IPv6 上而防火墙只写了 IPv4 规则。所以摸底账这一步看到[::]开头的监听一定要单独记一笔。顺便给一条查暴露项的快捷命令ss -lntup | grep -v -E 127\.0\.0\.1|\[::1\]它会过滤掉只监听回环的行剩下的就是需要你逐个确认是否该对外开放的端口。2.3 从外部视角做一次真实探活本机看到的监听只是我认为的状态真正的可达性要从外部验证。最轻量的方式是ncnc -zv -w 3 目标IP 445-z表示只探测不发送数据-v输出详细信息-w 3是超时 3 秒。返回succeeded说明通了Connection refused说明端口没监听或被 REJECT一直卡到超时说明被 DROP 了。这三种结果的差异后面验证章节还会用到。telnet也能用虽然它本意不是干这个的telnet 目标IP 445连上后按Ctrl]再输入quit退出。它的好处是几乎所有系统都有坏处是连不通时的提示信息不如nc明确。要做批量扫描就用nmapnmap -Pn -p 21,23,135,139,445,3389,6379 目标网段/24-Pn是跳过主机存活探测直接扫端口避免因为对方不回 ICMP 而漏报。这里必须提醒扫描只对自己有权限的资产做扫别人的地址段在很多地方是要担责的。2.4 把底账整理成一份可复查的清单摸完一轮之后我习惯把结果整理成三列端口、监听地址、是否有必要对外开放。这份清单的价值在半年后体现——那时候你已经忘了当初为什么开这个端口而清单上写着临时调试用7 月 3 日应关闭一眼就能判断该不该留。具体做法很简单把ss的输出重定向留档即可ss -lntup /root/port-audit-$(date %F).txt有条件的话把这份文件纳入配置管理每次变更前后各存一份对比两次输出的差异就能看出哪个操作引入了新的监听端口。这比事后翻操作记录快得多。3. firewalld、iptables、ufw 别在不该纠结的地方浪费时间3.1 三者的关系是分层而不是并列替代一个常见误解是firewalld 和 iptables 二选一。实际情况是内核里的包过滤由 netfilter 框架完成iptables 和 nftables 是操作 netfilter 的用户态工具firewalld 则是运行在 iptables新版走 nftables 后端之上的一层管理服务。firewalld 的 zone、service、rich rule 最终都会被翻译成规则链。所以我装了 firewalld 还能不能直接敲 iptables——能敲但非常不明智因为 firewalld 重载时会把自己管理的链刷掉你手写的规则跟着一起消失而且不会给你任何提示。ufw 的位置类似它是 Ubuntu 系上对 iptables 的简化封装规则最终也落到同一套链上。所以在同一台机器上同时启用 firewalld 和 ufw基本等于自己给自己挖坑。3.2 按发行版和场景选工具的判断表纠结用哪个的时候我一般按这张表决定基本不犹豫场景推荐工具理由CentOS 7 / RHEL / Rocky / Almafirewalld系统默认与 systemd 集成好重载不中断连接Ubuntu / Debian 桌面或轻量服务器ufw语法最短适合单人维护的少量机器需要精细控制链、做 NAT、做复杂转发iptables 或 nftables表达能力最强规则顺序完全可控容器宿主机iptables配 DOCKER-USER 链Docker 直接操作 iptables用高层工具容易被绕过已有成熟的 iptables 脚本体系继续用 iptables迁移成本高于收益没必要为了新而新判断的核心不是哪个更先进而是哪一层能覆盖住你实际需要控制的流量。容器场景特别典型ufw 写了 deny容器发布的端口照样能从外面访问因为流量走的是 FORWARD 链和 DNAT压根不经过 ufw 管理的 INPUT 链。3.3 先确认当前到底是谁在管事在敲任何规则之前花十秒确认一下当前状态能省掉后面半小时的困惑systemctl status firewalld systemctl status ufw iptables -L -n | head -20如果firewalld是 active就别动 iptables如果两个都是 inactive说明当前没有任何系统级过滤云主机上可能还有云安全组兜着但不能假设。还有一种情况是iptables -L能看到 Docker 相关链说明 Docker 在管一部分规则这时候修改要格外小心改错了可能导致所有容器网络不通。4. firewalld 封禁高危端口zone 和 rich rule 的正确姿势4.1 zone 决定了规则挂在哪个网络接口上firewalld 里最容易让人绕晕的概念是 zone。简单理解zone 是一组信任级别 绑定的网卡规则写在 zone 里只对绑到该 zone 的网卡生效。默认情况下大多数发行版把主网卡放在publiczone。先确认当前状态firewall-cmd --get-active-zones firewall-cmd --get-default-zone第一条会告诉你哪个 zone 绑了哪些网卡第二条告诉你默认 zone。如果--get-active-zones显示的是public那后面所有命令都可以省略--zonepublic如果显示的是别的名字有些云镜像会自定义 zone就必须显式指定否则规则写到默认 zone 上跟实际绑定的 zone 对不上规则就不生效。看某个 zone 当前放了什么firewall-cmd --zonepublic --list-all输出里的ports:和services:两行是关键。services是预定义的服务集合比如ssh服务对应 22/tcpsamba服务对应 137/138/139/445 等一串端口。这意味着如果你的 zone 里赫然写着services: ssh dhcpv6-client samba那 445 是被 samba 这个服务条目带开放的直接--remove-port445/tcp不会有效果因为它不是通过--add-port加的。4.2 端口、端口段、服务的三种写法差异封禁单个端口和端口段语法不一样# 封单个端口不持久重启失效 firewall-cmd --zonepublic --remove-port445/tcp # 封一段端口 firewall-cmd --zonepublic --remove-port8000-8010/tcp # 移除某个服务带来的所有端口 firewall-cmd --zonepublic --remove-servicesamba注意--remove-port和--remove-service都只能移除曾经被 add 过的内容。如果端口是被某个服务间接带开的移除端口无效必须移除服务。判断方法就是看--list-all里它出现在ports还是services那一行。如果端口压根没被显式开放但你依然想确保它被丢弃比如担心后续有人误操作放开了更稳的做法是用 rich rule 主动 drop它优先级高于 zone 的通用规则firewall-cmd --permanent --zonepublic --add-rich-rulerule familyipv4 port port445 protocoltcp drop4.3 permanent 与 reload 这个坑几乎人人踩过firewall-cmd 有个设计不加--permanent的修改立刻生效但重启后丢失加了--permanent的修改写入配置文件但不会立刻生效必须--reload才应用。这个设计本身合理但实际用起来经常出问题典型的是三条第一先加了--permanent又忘了 reload验证时发现没生效以为命令写错了反复试。第二reload 会重新加载所有规则理论上 firewalld 的 reload 不断开已建立的连接这是它相比 iptables restart 的优势但如果规则里有明显错误依然可能导致新连接被拒。第三有些人为了省事把--permanent和--reload串在一条命令里用测试阶段这么做没问题生产环境上建议分两步执行中间留出验证窗口。标准的两步写法firewall-cmd --permanent --zonepublic --add-rich-rulerule familyipv4 port port445 protocoltcp drop firewall-cmd --reloadreload 之后必须重新--list-all确认规则真的在里面别信命令的回显success——它只表示命令语法通过不表示规则生效。4.4 用 rich rule 做源地址级的精细控制真正体现 firewalld 能力的场景是端口不能全封但要限定来源。比如 3306 需要给办公网段访问其他一律拒绝# 先允许指定网段 firewall-cmd --permanent --zonepublic --add-rich-rulerule familyipv4 source address203.0.113.0/24 port port3306 protocoltcp accept # 再全局丢弃 firewall-cmd --permanent --zonepublic --add-rich-rulerule familyipv4 port port3306 protocoltcp drop firewall-cmd --reloadrich rule 里的 accept 和 drop 是有顺序优先级的同一 zone 内更具体的规则优先匹配但为了避免依赖这套隐式优先级我习惯把 accept 写在前面、drop 写在后面并且接受规则里尽量带上 source 限制这样逻辑上一目了然。再加上日志记录就得到了一个可观测的封禁规则firewall-cmd --permanent --zonepublic --add-rich-rulerule familyipv4 port port445 protocoltcp log prefixDROP445 levelnotice limit value5/m droplimit value5/m是限速每分钟最多记 5 条防止被扫描时把日志写爆——这是吃过亏的经验曾经有台机器一夜之间写满了 4G 日志分区导致服务起不来。5. iptables 手写规则链DROP 还是 REJECT 值得想清楚5.1 规则顺序决定一条包走哪条路iptables 是逐条匹配、匹配到就执行动作、不再往下走的模型所以规则顺序比规则内容更重要。用-A是追加到链尾用-I是插入到链首-I INPUT 1表示插到第一条。封禁场景下基本都该用-I因为系统里可能已经有若干 ACCEPT 规则追加到链尾的 DROP 永远轮不到执行。先看现有规则iptables -L INPUT -n -v --line-numbers--line-numbers会显示每条规则的序号后面删除规则时要用到-v显示每条规则匹配的包数和字节数这是排查规则到底有没有被命中的关键——如果一个 DROP 规则跑了三天packets 计数还是 0要么是没人扫要么是前面有规则把它截胡了。5.2 一次封一批端口的写法逐个端口写规则既啰嗦又慢用 multiport 扩展可以一条搞定iptables -I INPUT 1 -p tcp -m multiport --dports 21,23,135,139,445,2375,3389,5900 -j DROP注意 multiport 的端口数量上限是 15 个超过要拆成多条。端口段也可以用--dports 8000:8010这种冒号写法。UDP 高危端口单独再来一条iptables -I INPUT 2 -p udp -m multiport --dports 111,137,161,11211 -j DROP如果只想限制来源加上 source 条件iptables -I INPUT 1 -p tcp --dport 3306 ! -s 203.0.113.0/24 -j DROP!是取反意思是来源不在这个网段就丢弃。这种写法的可读性其实一般容易看反我更喜欢写成两条先 ACCEPT 再 DROP。规则多了以后可读性比省一行的价值大得多。还有一点如果链的默认策略是 ACCEPT你需要显式写 DROP 规则如果默认策略是 DROP则要显式写 ACCEPT 规则。改默认策略风险很高尤其是远程操作时把 INPUT 策略改成 DROP 而没放行 22等于当场断线。5.3 DROP 与 REJECT 的行为差异和选择依据这是最常被问的问题。两者的区别在于DROP包被静默丢弃不回任何响应。发起方会一直等到超时通常是几秒到几十秒。REJECT返回一个错误响应默认是 ICMP port unreachable也可以指定--reject-with tcp-reset发起方立刻知道连接被拒。安全视角上DROP 更沉默不向扫描者透露端口状态扫描全端口时会慢很多REJECT 则更礼貌能立刻告诉对方这个端口不通。实际选择时要考虑业务侧影响。如果这个端口有内部程序会去连DROP 会让程序卡在超时上可能拖慢页面响应甚至耗尽连接池REJECT 会让程序立刻拿到错误尽快走失败分支。对外部暴露的端口我一般对外网来源用 DROP对已知内部网段用 REJECT写法是# 内网来源直接拒绝让程序快速失败 iptables -I INPUT 1 -s 10.0.0.0/8 -p tcp --dport 445 -j REJECT --reject-with tcp-reset # 其余来源静默丢弃 iptables -I INPUT 2 -p tcp --dport 445 -j DROP5.4 保存与开机生效不同发行版差得挺多iptables 规则默认只存在于内存重启就没了。持久化方式各发行版不一样系统持久化方式RHEL / CentOS 7 及之前service iptables save文件在/etc/sysconfig/iptablesDebian / Ubuntu装iptables-persistent用netfilter-persistent save通用做法iptables-save /etc/iptables/rules.v4配 systemd 单元开机恢复nftables 后端nft list ruleset /etc/nftables.conf启用nftables.service这里有个细节CentOS 7 之后默认用 firewalld/etc/sysconfig/iptables可能不存在也不会被加载。如果你在 CentOS 7 上手工写 iptables 规则并保存结果重启后失效八成是这个原因——要么停掉 firewalld 改用纯 iptables要么老老实实用 firewalld 的 rich rule。6. Ubuntu 上的 ufw 三行就能搞定但默认策略要看清6.1 默认 deny 与规则顺序之间的陷阱ufw 的核心理念是默认拒绝入站正确启用顺序是这样的ufw default deny incoming ufw default allow outgoing ufw allow 22/tcp ufw enable顺序不能反。如果先ufw enable再ufw allow 22/tcp中间那几秒你的 SSH 连接会直接被切断只能去控制台救场。这是我带过的实习生踩过的第一个坑现在我把这条写进了团队的检查清单。ufw enable会提示是否继续因为操作可能中断现有 SSH 连接。看到这个提示时先别急着按 y确认 22 端口已经放行。6.2 封端口、封网段、加限速的写法封禁单个或一批端口ufw deny 445/tcp ufw deny 21,23,135,139/tcp ufw deny 11211/udpufw deny底层用的是 DROP如果想要 REJECT 的行为直接写ufw reject 445/tcp。批量封禁的逗号写法其实不是 ufw 原生支持的稳妥写法是分多条或者用 application profile。为避免语法不支持我更建议一条一条写反正也不多。封指定来源网段ufw deny from 198.51.100.0/24 to any port 3306 proto tcp限速防爆破对 SSH 很实用ufw limit 22/tcplimit默认是 30 秒内超过 6 次连接就临时拒绝能显著降低爆破效率。查看和删除规则ufw status numbered ufw delete 3加了numbered才能按序号删除这个设计比 iptables 友好。6.3 ufw 和 Docker 的冲突必须提前知道这是 Ubuntu 服务器上最隐蔽的问题之一装了 Docker 之后容器发布的端口会绕过 ufw 规则。原因在于 Docker 把转发规则插到了 nat 表的 PREROUTING 和 FORWARD 链上外部流量做 DNAT 直接进容器根本不经过 ufw 管理的 INPUT 链。表现就是ufw status显示 6379 是 deny但外部nc -zv依然能连上容器里的 Redis。解决办法有几种按推荐顺序最优解发布端口时绑定到回环地址-p 127.0.0.1:6379:6379从源头限制可达性。次优解在DOCKER-USER链里加规则这条链是 Docker 预留给你自定义的不会被容器操作覆盖iptables -I DOCKER-USER -p tcp --dport 6379 -j DROP下策在daemon.json里设置iptables: false并自己管理全部规则工作量陡增容易出错。7. 封完之后怎么验证规则、连接、日志三条线对账7.1 规则层面确认规则真的加载了不同工具的命令不一样我把常用的几条列在一起备用firewall-cmd --zonepublic --list-all firewall-cmd --zonepublic --list-rich-rules iptables -L INPUT -n -v --line-numbers nft list ruleset ufw status verbosefirewall-cmd --list-rich-rules值得单独用因为--list-all输出较长rich rule 容易看漏。iptables 那边重点看-v的包计数确认规则位置在前面而不是被别的规则挡住。7.2 连接层面验证三种结果的含义前面提过nc -zv -w 3 IP 端口的三种结果这里把它们的对应关系说清楚这是排查时最重要的判断依据返回结果含义对应规则succeeded端口可达无拦截或命中 ACCEPTConnection refused被明确拒绝命中 REJECT或服务未监听卡住直到超时无任何响应命中 DROPNo route to host网络层不通路由或云安全组拦截有个容易混淆的点Connection refused既可能是 REJECT 造成的也可能是服务根本没监听。区分方法是本地跑ss -lntp如果本地有监听而远端是 refused那就是 REJECT 生效了如果本地也没监听那和服务无关是端口没起。7.3 日志层面把被丢弃的连接留下证据规则生效但没日志等于没法审计。firewalld 的 rich rule 加 log 参数前面演示过iptables 的写法是iptables -I INPUT 1 -p tcp --dport 445 -j LOG --log-prefix DROP-445: --log-level 4 iptables -I INPUT 2 -p tcp --dport 445 -j DROPLOG 是记录后继续匹配所以必须紧跟一条真正的 DROP 规则顺序不能反。日志会写到内核日志用dmesg | tail或journalctl -k -f查看。这里必须提醒限速问题。日志规则不限速的话一次全端口扫描就能产生上万条记录日志分区写满会导致整个系统出问题。iptables 可以用-m limit --limit 5/m --limit-burst 10来限速iptables -I INPUT 1 -p tcp --dport 445 -m limit --limit 5/m -j LOG --log-prefix DROP-445: 7.4 把验证结果和预期做成对照表我习惯在变更结束后填一张这样的表一是给自己确认二是留给后面接手的人端口预期状态本机验证结果外网验证结果结论22放行可达可达正常445封禁本地仍监听超时符合预期6379封禁本地仍监听超时符合预期3306限指定网段本地仍监听办公网可达、其他超时符合预期注意本地仍监听是正常的——防火墙只拦外部流量不会让服务停止监听。如果本地都连不上那不是防火墙的问题是服务自己挂了。8. 最怕把自己关在门外远程改防火墙的保命流程8.1 先放行后封禁的顺序不能颠倒这条规矩听起来像废话但每年都有人栽在上面。核心操作原则就一条在远程会话里修改防火墙任何时刻都必须保证当前会话所需的端口是放行的。具体到操作上就是所有封禁类命令都在放行规则之后执行。而且封禁时不要用清空规则再重写的思路iptables -F在远程场景下是极度危险的操作因为它会瞬间清掉所有规则如果默认策略是 DROP你的会话当场断开且重启也救不回来。真需要重建规则正确做法是先写一份完整的新规则文件然后一次性应用。8.2 定时回滚脚本几十秒换一条命的保险这个技巧我推荐给每一个需要远程操作防火墙的人成本几乎为零# 写法一用 at 在 5 分钟后执行回滚 echo iptables -P INPUT ACCEPT; iptables -F | at now 5 minutes # 写法二systemd-run 定时任务适合所有 systemd 系统 systemd-run --on-active300 /usr/local/bin/firewall-rollback.sh # 写法三后台 sleep 加回滚最简陋但随处可用 nohup bash -c sleep 300; iptables -P INPUT ACCEPT; iptables -F /dev/null 21 思路很简单在动手改规则之前先挂一个5 分钟后自动恢复的任务。改完规则后立刻开一个新终端验证 SSH 还能连确认没问题再手动取消这个定时任务。如果改崩了等 5 分钟自动恢复你还能连回去。这 5 分钟比任何应急预案都实用。取消方法at用atq查任务号、atrm 编号删除systemd-run用systemctl list-timers找到对应单元后systemctl stop掉。回滚脚本的内容要写清楚比如 firewalld 场景可以是#!/bin/bash firewall-cmd --permanent --remove-rich-rulerule familyipv4 port port445 protocoltcp drop firewall-cmd --reload8.3 云安全组和系统防火墙是两层别只改一层公网云主机上安全组有的平台叫网络 ACL、有的叫防火墙规则通常作用在虚拟网络层先于主机防火墙生效。这意味着安全组没放开主机防火墙放行了也没用安全组放开了主机防火墙没配好端口依然可达。两层得都看。这也是排查端口到底通不通时最容易绕圈的地方。我的排查顺序是先确认云控制台安全组入方向规则里该端口是否放行再确认主机ss -lntp有监听再确认主机防火墙规则最后从外部探活。按这个顺序走基本不会出现查了两小时最后发现是安全组的问题这种尴尬。8.4 容器和转发链会绕过你写的规则前面提过 Docker 的情况这里补充几个同类问题。开启了 IP 转发net.ipv4.ip_forward1的机器上经过本机转发的流量走的是 FORWARD 链而不是 INPUT 链只在 INPUT 上封端口对这类流量无效。判断方法是看iptables -L FORWARD -n -v是否有大量匹配。另外如果主机跑着 Kuberneteskube-proxy 会往 nat 和 filter 表里塞大量规则手工维护 iptables 基本不可行这时候应该通过 CNI 的网络策略或者在节点外侧做网络层限制而不是在节点上敲 iptables。9. 把一次性封禁做成能长期维护的端口治理9.1 用白名单思路替代到处加黑名单加黑名单是最直观的做法——想到一个端口封一个。但维护久了会发现两个问题一是规则越加越多半年后自己也看不懂哪条还需要二是总有想不到的端口被新装的软件带进来。更省心的思路是反过来做默认拒绝所有入站只放行确实需要对外的那几个端口。这样新装的软件即使默认监听 0.0.0.0也不会自动暴露。firewalld 里可以这样设置firewall-cmd --permanent --zonepublic --set-targetDROP firewall-cmd --permanent --zonepublic --add-servicessh firewall-cmd --reloadiptables 里则是把 INPUT 链默认策略设为 DROP然后按需 ACCEPT。注意改默认策略前务必确认放行规则已经生效并且配合 8.2 节的定时回滚否则极易断线。9.2 变更记录比规则本身更值钱我维护过的机器里出问题最多的不是规则写错而是没人知道某条规则为什么存在。所以每次改动我都会在配置目录里留一行注释或一条记录说清楚时间、原因、影响范围。firewalld 的 rich rule 支持在规则里带描述通过--add-rich-rule配合 zone 配置文件的注释行iptables 则可以直接在规则上挂 commentiptables -I INPUT 1 -p tcp --dport 445 -m comment --comment 2024-06-15 封SMB审计要求 -j DROP-m comment --comment的内容在iptables -L -n加--line-numbers时不一定显示需要用iptables -L INPUT -n --line-numbers -v配合iptables-save查看iptables-save的输出里注释是完整保留的。养成这个习惯一年后接手的人会感谢你。9.3 防火墙挡掉的东西比你想的多最后说一个常被问到的问题防火墙关掉有什么影响吗。从技术上说关掉之后所有入站连接不再被过滤原本被丢弃的扫描、爆破、漏洞利用尝试会全部打到服务上。如果你的服务本身有认证、有 WAF、有入侵检测也许还能撑住但绝大多数情况下端口一旦暴露日志量和异常请求量会在几分钟内明显上升。反过来讲防火墙也不是万能的。它挡得住从外部发起的连接挡不住已经进入内网的横向移动也挡不住应用层的攻击——比如你的 Web 服务本身有漏洞443 端口放行了攻击照样能打进来。所以我在实际维护中一直把它当成多层防护里成本最低、见效最快的那一层先在防火墙把不该露的端口露不出去再去处理服务配置、补丁、口令这些更花时间的事情。这套命令我用过很多次最深的体会是那句老话——真正容易出错的不是语法而是顺序和验证。记住先放行后封禁、改前挂回滚、改后必验证这三条剩下的语法查手册就够了。
返回列表