ARTICLE DETAIL

资讯详情

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

阿里云服务器ping不通但SSH能连?安全组与ICMP排查指南

阿里云服务器ping不通但SSH能连?安全组与ICMP排查指南 我在帮朋友排查一台阿里云服务器的时候遇到一个看着特别拧巴的问题系统防火墙明明已经关了可本地ping服务器IP还是满屏的请求超时但他用 Xshell 连服务器却一点问题没有。拧巴在哪呢按常理说防火墙关了等于大门敞开为什么偏偏ping的数据包就像被人悄悄截住一样这个现象在云服务器上其实相当典型。Xshell 能连上说明服务器在线、SSH服务正常、整个公网链路也是通的而ping不通说明 ICMP 报文在某个环节被丢了。两个结果放一起非但不矛盾反而是一份非常有效的诊断线索。这篇文章就从这个矛盾入手把阿里云服务器从安全组到系统防火墙、再到链路层的排查思路完整捋一遍顺便把我这些年踩过的坑也一并交代清楚。不管你是刚买服务器的小白还是被这个问题折腾过几次的运维新手照着下文一步步查基本都能定位到问题。1. 一个反直觉的现象SSH畅通但 ping 不通先别急着怪防火墙1.1 Xshell 和 ping 走的是完全不同的两条路先说一个最容易被忽略的点Xshell 连服务器用的是 SSH 协议底层跑在 TCP 22 端口上是一个典型的面向连接的可靠传输协议。而ping指令走的是 ICMP 协议它既不基于 TCP、也不基于 UDP更像是一个网络层探针发送方丢出一个 Echo Request回显请求接收方如果有回应就返回一个 Echo Reply回显应答。打个比方SSH 连接像是你打电话要先拨号、对方接听、双方确认身份然后才开始聊天而 ICMP 里的 ping 像是你在楼下朝楼上喊一句喂你在吗楼上听见了回一句在呢。这两种沟通方式使用的消息通道、被检查的环节完全不一样。所以SSH 通只能证明电话线路通、有人接听不能证明喊话也能被听见并回应。在云服务器场景下一次公网 ping 请求的完整路径是本地网络出口 - 运营商链路 - 云厂商边缘网关 - 安全组虚拟防火墙 - 云内路由 - 虚拟网卡 - 操作系统网络栈 - 内核 ICMP 处理逻辑每一层都有可能丢掉 ICMP 报文。而 SSH 连接走的是另一条应用层链路虽然物理路径大体相似但它在安全组、系统防火墙层面依赖的是 TCP 22 端口放行规则和 ICMP 的放行规则可以完全不同。1.2 为什么服务器在线不能靠 ping 来证明很多人习惯用 ping 判断一台服务器是否在线这个习惯在物理服务器时代大体没问题但到了云上就未必可靠了。我记得有一次在客户现场他们一口咬定服务器挂了理由是 ping 不通可我打开控制台一看CPU 占用率才 5%SSH 也连得上去。后来查下来是安全组里压根没有放行 ICMP。这不是个例。阿里云的安全组默认规则通常是默认拒绝”加显式放行买完 ECS 实例控制台会自动放行 22、3389 这类常用远程管理端口一般不会主动放行 ICMP。也就是说从你拿到一台新服务器开始ping 不通其实是符合默认策略的反倒是 Xshell 能连上才是正常放行后的结果。所以遇到SSH通但 ping 不通的情况我的第一反应不是怀疑防火墙没关干净而是先确认云平台安全组有没有放行 ICMP。这一步基本能解决掉八成的问题。接下来要做的就是把安全组和系统防火墙这两个概念彻底分清否则后面越查越乱。2. 阿里云安全组最容易忽略的隐形防火墙2.1 安全组是什么和 CentOS 的 firewalld 有什么区别很多初次接触云服务器的朋友会混淆两件事服务器内部跑的 firewalld、iptables和云控制台里的安全组。虽然名字都带防火墙三个字但它们工作的位置完全不同。安全组是云平台层面的一组虚拟防火墙规则在流量进入虚拟机网卡之前先做一次过滤。它就像一个小区大门的门卫负责检查谁可以进小区。而系统防火墙例如 firewalld 或 iptables是你家门上的锁只管进你家之后的事。即便你把家门锁拆了关闭系统防火墙小区门卫不认识你一样不会放行。这就解释了标题里那个诡异的场景系统防火墙关了只是把家门锁拆了但安全组作为社区门卫默认没有给 ICMP 释放通行证于是 ping 报文在小区门口就被拦下来了。Xshell 之所以能进去是因为门卫手里有 22 号端口的放行名单看到是 SSH 流量就抬手放行。2.2 实战在阿里云控制台放行 ICMP 入方向配置过程不复杂但每一步都有讲究。我以阿里云 ECS 控制台为例轻量应用服务器也在类似位置登录阿里云控制台进入云服务器 ECS页面找到目标实例。在实例详情页点击安全组页签进入该实例绑定的安全组。点击管理规则 - 入方向 - 手动添加。规则设置里协议类型选择ICMP(IPv4)源地址写0.0.0.0/0允许所有 IPv4 地址 ping描述可以写allow icmp ping。点击保存。保存后一般秒级生效。回到本地再ping一次正常情况下就能看到稳定的应答了。如果还需要支持 IPv6 的 ping额外添加一条ICMP(IPv6)规则即可。这里有一个小细节有人会把源地址写成0.0.0.0这种形式严格来说应该使用 CIDR 格式也就是0.0.0.0/0否则部分控制台会提示格式不合法。出于安全考虑如果你不想对所有公网开放 ping可以把源地址限定为公司的固定出口 IP例如123.45.67.89/32。这样只有该 IP 发起的 ping 才能到达服务器其它来源依旧是拒绝状态。运维上既保留了探测手段又不至于把服务器完全暴露在扫描器之下。2.3 配置安全组最容易踩的几个坑第一不要图省事把安全组出方向和入方向全部改成放行所有端口。有些教程让你先把安全组全部放开排查问题这种操作在测试环境我还能理解生产环境千万别这么干。全部放开之后服务器等于直接裸奔在公网上扫描端口、暴力破解、挖矿木马都会找上门。第二注意你修改的是入方向还是出方向。ICMP 的 ping 请求是外部发起的入站流量对应的回包虽然从服务器发回但安全组的状态机制会自动允许该连接的回程流量所以一般只需在入方向放行 ICMP 就行。如果你发现服务器内能 ping 通外网但外网 ping 不进来大概率就是入方向没有放行。第三安全组规则有优先级字段数字越小优先级越高。如果你之前添加过一条拒绝 ICMP的高优先级规则那么后面再加允许 ICMP也是白搭必须先删掉或调低那条拒绝规则。我自己就犯过这个错在测试安全策略的时候加过一条 Deny ICMP两周后排查 ping 不通的问题翻了好一会儿才想起这条陈年老规则。3. 系统防火墙层确认关闭之后还要查这些残留3.1 把 firewalld 和 iptables 的状态彻底查一遍如果安全组已经放行了 ICMP服务器仍然 ping 不通这时候才轮到系统层排查。先说一个很多人都会掉进去的坑只在防火墙服务层面执行了systemctl stop firewalld就觉得万事大吉但实际上 iptables 规则可能仍然残留在内核里。我见过太多次这种情况用户明明执行过关闭命令但一查iptables -L -nINPUT 链还是有一堆 DROP 规则。原因很简单可能是 CentOS 6 时代遗留的 iptables-services 也在运行或者某个初始化脚本在开机时重新加载了规则。所以完整的检查命令应该是# 查看 firewalld 运行状态 systemctl status firewalld firewall-cmd --state # 直接查看内核当前的 iptables 规则 iptables -L -n --line-numbers iptables -L INPUT -n --line-numbers # 查看持久化规则 iptables-save如果iptables-save里能看到类似下面的规则那问题就出在这里-A INPUT -p icmp --icmp-type echo-request -j DROP解决办法很直接要么把 DROP 改成 ACCEPT要么直接删除这条规则iptables -D INPUT -p icmp --icmp-type echo-request -j DROP千万别忘了用iptables命令修改的规则是临时的重启后可能会恢复。如果要永久生效要么用service iptables save针对 iptables-services要么把规则写进/etc/sysconfig/iptables。另外Ubuntu 系统默认用的是 ufw检查命令是ufw status有些云镜像还预置了其他安全加固脚本建议一并查一下/etc/systemd/system里有没有奇怪的网络策略服务。3.2 一个很多人没听过的内核参数icmp_echo_ignore_all系统防火墙关干净了安全组也放行了服务器还是 ping 不通那就要怀疑 Linux 内核是不是开启了忽略所有 ping的开关。有一个内核参数叫net.ipv4.icmp_echo_ignore_all当它的值为 1 时内核会直接丢弃所有 ICMP Echo Request连应答都不生成表现就是完全 ping 不通而且服务器上不会有任何日志——因为它根本没到应用层。检查命令很简单sysctl net.ipv4.icmp_echo_ignore_all如果输出结果是net.ipv4.icmp_echo_ignore_all 1把它临时改回 0sysctl -w net.ipv4.icmp_echo_ignore_all0这里我建议额外看一看/etc/sysctl.conf和/etc/sysctl.d/目录下的配置文件。有些安全基线扫描工具会在加固服务器时顺手把这个参数设成 1结果导致防火墙关了也 ping 不通这种状况。如果配置里有这一项要把它改成 0 或注释掉再执行sysctl -p重新加载。这个参数的存在也能解释一个问题为什么明明 Xshell 能连上、SSH 完全正常echo 报文却像石沉大海。因为 TCP 连接走的是内核里的另一套处理逻辑和 ICMP 的回显响应完全是两码事。3.3 SELinux 和自定义策略的干扰排查再往下走还有一个概率不高但确实存在过的干扰源SELinux。按常规经验SELinux 默认配置不会拦截 ping但如果服务器上有一些人手动改过的策略模块、或者跑到强制模式里加了些奇怪的自定义规则不排除 ICMP 被拦截。排查时可以临时把 SELinux 切到 permissive 模式试试setenforce 0 getenforce如果切换之后 ping 通了说明确实和 SELinux 策略有关。但注意setenforce 0只是临时修改重启后又会恢复 enforcing要永久关闭需要修改/etc/selinux/config里的SELINUXdisabled。生产环境我不建议为了一个 ping 就把 SELinux 整个关掉更稳妥的方式是在 SELinux 的布尔配置里放行对应协议或者仔细排查是哪条策略产生了拦截。还有一类情况服务器上装了 fail2ban、安全狗、云锁之类的安全加固软件它们会在 netfilter 层面插入自己的规则。查的时候光看 iptables 还不够要把这些软件自带的防护状态也一起检查一遍。4. 链路级排查从本地到服务器一步步定位断点4.1 自下而上的验证顺序本地网关、公网路由、服务器回程如果安全组、系统防火墙、内核参数都排查过ping 依然不通那就不能只盯着服务器本身了要把范围扩大到整个链路。我的习惯是自下而上、从近到远地验证。先在本地确认自己的网络是否正常ping 114.114.114.114 ping 223.5.5.5如果这两条都不通说明本地出口网络就有问题和服务器没半毛钱关系。如果能通再拿本地到目标服务器 IP 的整条路径做诊断。这里有一个容易被混淆的点Xshell 能连上并不代表链路上每一个节点都放行 ICMP。公网上很多路由节点会主动丢弃 ICMP 报文但它们并不影响 TCP 连接所以才会出现端口通、ping 不通的局面。4.2 用 mtr 和 traceroute 看清楚数据包卡在哪一跳判断 ICMP 到底丢在哪一跳最有效的工具是mtr。它相当于 traceroute 和 ping 的合体可以持续追踪每一跳的丢包率。在 Linux 上安装后运行mtr -rwz 服务器公网IP如果发现前面几跳都好好的到达目标 IP 的那一跳显示 100% 丢包但 SSH 依然能连那基本可以断定是目标服务器侧的安全策略把 ICMP 给拦了而不是中间链路故障。Windows 上对应的命令是tracert不过它默认也是基于 ICMP 实现的如果某个云平台把 ICMP 禁掉tracert 也看不到完整信息。这时候可以配合端口探测工具来交叉验证例如tcping工具注意不是ping是专门用来测试 TCP 端口通的:tcping 服务器IP 22只要 TCP 22 端口能通就再次证明 TCP 链路是通的问题集中在 ICMP 协议本身。4.3 从云端反向测试在服务器里 ping 出去能说明什么如果本地链路查不出问题那就换一个方向从服务器内部往外 ping看是不是出方向也异常。最快捷的方式是不依赖 SSH直接通过阿里云控制台的 VNC 或 Workbench 远程连接进入系统进入方式可以参考控制台的远程连接入口因为这时候 SSH 可能不是你首要的信任通道。登录服务器后先验证本机协议栈ping 127.0.0.1再验证云内网络ping 内网网关IP # 通常可以在控制台看到或者 ip route 输出里的 default 网关然后验证出网方向ping 223.5.5.5 curl -I https://www.baidu.com这里我会把 curl 也做一遍因为 curl 走的是 TCP 80/443 端口能独立于 ICMP 链路验证出方向是否通。如果服务器内 ping 外网也不通、但 curl 百度通那问题多半又是安全组或运营商在 ICMP 层面做了限制。如果 ping 外网也不通、curl 也不通那可能是安全组出方向规则、EIP 绑定、路由表等配置问题。继续检查ip addr ip route show重点看公网 IP 是否正确绑定在网卡上、默认路由是否存在。之前我在排查一台 ECS 时遇到过一种情况系统里有多个网卡默认路由指向了一个错误的网关导致回程报文发不出去。从外网看服务器仿佛消失了但实际上系统运行正常。4.4 借助第三方超级 ping交叉验证运营商和地域因素还有一种概率不高但确实存在的场景本地网络尤其是公司网络、校园网禁止 ICMP 出站。判断方法很简单在用超级 ping 工具从全国各地多个节点同时测试目标 IP例如 17ce 网站、站长工具的 ping 测试等。如果全国大部分节点都能 ping 通只有你自己的网络不通那问题几乎可以锁定在本地出口策略而不是服务器。反向思考同样成立如果第三方显示几乎所有节点都 ping 不通但你本地 Xshell 连得很顺畅那基本就是服务器侧安全策略把 ICMP 整体拦掉了。这种全网都不通、只有 TCP 通的特征指向性非常强基本不用再怀疑运营商或中间路由。另外阿里云控制台本身也有一些网络诊断能力比如 ECS 实例页面的自助排查、监控图表里的公网流量趋势可以辅助判断是否出现了丢包。如果是突发性的 ping 不通记得顺手看一眼云监控里的公网流入流出带宽有时候是带宽跑满导致 ICMP 报文被丢弃。5. 整理一份可以直接照抄的排障清单5.1 快速定位表现象-原因-验证-操作排查到最后我把常用的定位思路整理成一张表遇到类似问题可以直接对着查现象首选排查方向关键验证命令/操作解决动作外网 ping 不通但 SSH 能连安全组没放行 ICMP控制台查看入方向规则添加 ICMP(IPv4) 入方向放行安全组已放行还是 ping 不通系统防火墙/iptables 残留规则iptables -L -n查看 DROP 规则删除或修改对应 DROP 规则防火墙已关闭仍无响应内核参数icmp_echo_ignore_allsysctl net.ipv4.icmp_echo_ignore_all改为 0 并持久化服务器内 ping 外网不通安全组出方向、路由、EIP服务器内ping 223.5.5.5、curl baidu.com检查出方向规则和路由表只有本地 ping 不通别处正常本地网络禁止 ICMP 出站超级 ping 全国节点测试联系本地网络管理员或更换网络某一段路由丢包严重中间运营商节点丢弃 ICMPmtr -rwz查看每一跳丢包率换时间段再测或联系运营商这张表是我做云服务器排障时最常用的首页索引。多数情况下走到第一行就能解决问题后面几行是给那些第一反应正确但依然无效的情况准备的。5.2 我自己的运维习惯和几个小技巧最后说几个从实战里沉淀下来的习惯算不上什么高深理论但确实能省不少时间。第一把安全组和系统防火墙的分工明确下来。安全组负责对外边界管控只放行业务必需的端口和协议系统防火墙负责主机内部防线即使安全组被误配成全放行系统防火墙也能兜底。不要为了省事永久关闭系统防火墙尤其是暴露在公网的服务器。第二每次改动安全组规则都在备注里写清楚谁改的、为什么改、改了哪条。听起来很啰嗦但等你需要翻两个月前的记录时就知道这一行备注有多值钱了。云上莫名其妙的网络问题最后多半能找到一条当时随手加、后来忘删的旧规则。第三ICMP 放行建议单独建一条规则源地址尽量限制在自己的办公网 IP 或跳板机 IP 范围而不是无脑对所有公网开放。虽然 ping 本身不提供太多数据给攻击者但少暴露一种探测途径总归是好的。第四当你已经排查到mtr 显示到达目标后丢包这一步时不妨顺手把系统防火墙的服务状态重新确认一遍而不是只看应该关了。有些云镜像自带定时任务或初始化脚本会在业务启动时把防火墙重新拉起来。这种关了又自动开的情况我也遇到过不止一次。回到最初那个问题——Xshell 能连、ping 不通——用一句话概括就是SSH 证明的是 TCP 链路ping 验证的是 ICMP 链路两条链路的放行规则在云平台上彼此独立。排查时按安全组 - 系统防火墙 - 内核参数 - 链路路由 - 本地网络的顺序逐步缩小范围基本不会走偏。这个过程里最忌讳的是凭直觉反复重启服务器或者盲目重装系统——因为问题根本不在服务器状态上而在谁放行、谁拒绝的规则链里。
返回列表