1. 项目概述为什么我们要亲手抓包看SSH如果你是一名运维工程师、网络安全研究员或者是对网络通信底层有好奇心的开发者那么“SSH连接”对你来说可能就像呼吸一样自然。我们每天敲下ssh userhost输入密码或者更优雅地使用密钥然后就能在远程服务器上畅行无阻。但你是否想过在这看似简单的命令背后你的电脑和服务器之间究竟“聊”了些什么数据是如何在不可信的网络中安全穿行的当连接失败时除了看日志我们还能从哪里找到线索这就是本次“SSH流程与Wireshark抓包分析”项目的核心价值。它不是一个简单的工具使用教程而是一次深入的网络协议“解剖”实践。通过亲手捕获并分析SSH协议的数据包你将能直观理解SSH协议栈从TCP三次握手到密钥交换、身份认证再到加密通道的建立你将亲眼看到每一个阶段对应的网络报文。掌握强大的排错技能当SSH连接出现“Connection refused”、“Permission denied”或卡在某个阶段时抓包分析能提供比系统日志更底层、更精确的故障定位信息。深化网络安全认知你会看到Diffie-Hellman密钥交换如何在不传输密钥的情况下让双方协商出共享密钥理解为什么SSH能够抵御中间人攻击这对构建安全应用有直接的启发。我们将使用网络分析领域的“瑞士军刀”——Wireshark来完成这次探索。整个过程就像给网络通信做一次“X光透视”所有隐藏在命令行背后的复杂交互都将一览无余。无论你是想夯实网络基础还是解决棘手的连接问题亦或是单纯满足技术好奇心这次实践都会让你受益匪浅。2. SSH协议核心流程深度解析在打开Wireshark之前我们必须先在心里搭建起SSH连接的完整蓝图。SSHSecure Shell协议不仅仅是一个简单的登录工具它是一个分层的协议族其连接建立过程是一个精妙、严谨的“握手”仪式。2.1 连接建立的四个关键阶段一次完整的SSH连接可以清晰地划分为四个阶段它们像齿轮一样紧密咬合顺序执行。阶段一传输层协议建立TCP连接这是所有网络应用的基础。你的SSH客户端通常是22端口会向服务器端的22端口发起一个标准的TCP三次握手。这个阶段确保了基础的、可靠的字节流传输通道。没有它后续的一切都无从谈起。在抓包中你会看到熟悉的SYN,SYN-ACK,ACK报文。阶段二协议版本协商与密钥交换TCP连接建立后双方立即开始SSH层面的对话。首先交换的是协议版本字符串例如“SSH-2.0-OpenSSH_8.9”。版本匹配后便进入整个SSH安全性的基石——密钥交换。 这个过程主要基于Diffie-Hellman算法。简单类比双方公开交换一些颜色信息公开参数再各自混入自己的秘密颜色私钥最终通过一系列计算独立得到相同的最终颜色共享密钥而旁观者无法推导出这个最终颜色。在抓包中你会看到SSH_MSG_KEXINIT和SSH_MSG_KEXDH_INIT/REPLY等报文它们承载了算法协商和密钥交换的核心数据。注意密钥交换的目的不是直接生成用于加密会话数据的密钥而是生成一个双方共享的、唯一的“秘密种子”。后续的会话密钥、认证用的HMAC密钥等都是通过这个种子派生出来的。阶段三用户身份认证共享密钥建立后后续的通信就已经可以被加密了但通常在此阶段认证过程本身的报文是受保护的。认证方式有多种密码认证客户端发送加密后的用户名和密码。公钥认证最常用客户端声明自己拥有某个公钥对应的私钥并发送一个用该私钥签名的数据包。服务器用已预存的公钥验证签名。抓包中会看到SSH_MSG_USERAUTH_REQUEST报文。键盘交互认证用于二次验证等场景。阶段四会话通道建立认证成功后客户端会请求打开一个“通道”Channel用于承载实际的Shell会话、文件传输SCP/SFTP或端口转发等。你可以把SSH连接理解为一个加密的隧道而通道就是隧道里面并行的多条逻辑车道。抓包中会看到SSH_MSG_CHANNEL_OPEN和SSH_MSG_CHANNEL_OPEN_CONFIRMATION报文。2.2 核心算法与安全机制理解这些算法能让你看懂抓包数据中那些“神秘”字段的含义。密钥交换算法常见的有diffie-hellman-group14-sha1,ecdh-sha2-nistp256等。group14指使用2048位的模数素数安全性更高。抓包时在SSH_MSG_KEXINIT报文中可以看到客户端和服务端各自支持的算法列表最终协商出一个双方都支持的。加密算法用于加密通道数据。如aes128-ctr,aes256-gcm。GCM模式同时提供加密和完整性校验通常更受青睐。消息认证码算法用于验证数据包的完整性防止被篡改。如hmac-sha2-256。主机密钥服务器在密钥交换开始时会将其主机密钥通常是一对RSA或ECDSA密钥的公钥发送给客户端。客户端用此来验证服务器的身份防止中间人攻击。这就是第一次连接某台服务器时会提示你接受“指纹”的原因。指纹就是这个主机密钥公钥的哈希值。3. Wireshark抓包环境准备与配置工欲善其事必先利其器。直接用Wireshark抓取所有网卡流量你会瞬间被海量无关报文淹没。正确的配置是成功分析的一半。3.1 精准捕获过滤器的艺术我们的目标是只捕获与本次SSH测试相关的流量这就需要使用捕获过滤器。场景设定假设你的本地IP是192.168.1.100你要连接的服务器IP是10.0.0.5。最精准的捕获过滤器host 10.0.0.5 and port 22这个过滤器告诉Wireshark“只抓取发往或来自10.0.0.5的22端口的所有数据包。” 这是最干净、最推荐的方式。备选或扩展过滤器tcp port 22抓取所有进出本机22端口的流量。如果你不确定服务器IP或者本地有多个SSH连接可以用这个但可能会有其他噪音。src host 192.168.1.100 and dst host 10.0.0.5 and tcp port 22更严格地指定源和目的适用于多网卡环境。操作步骤打开Wireshark在首页选择你要使用的网络接口通常是活跃的以太网或Wi-Fi适配器。在选中接口的右侧找到“捕获过滤器”输入框直接输入host 10.0.0.5 and port 22。点击接口名称旁边的蓝色鲨鱼鳍按钮开始捕获。此时打开你的终端执行ssh user10.0.0.5进行连接。连接成功或失败后回到Wireshark点击红色方块按钮停止捕获。3.2 让SSH报文“现形”解码与着色规则捕获到的数据包默认可能只被识别为普通的TCP数据。我们需要让Wireshark识别出SSH协议。强制解码为SSHWireshark通常能自动识别22端口的流量为SSH。如果不能可以右键某个TCP包 - “解码为...” - 在“当前”列中找到该TCP流将其解码为SSH协议。配置Wireshark解析非标准端口的SSH如果你的SSH服务运行在非22端口如2222你需要永久设置。点击菜单分析-启用的协议- 在搜索框输入“ssh”找到“SSH protocol”项在其下方“TCP端口”栏位将默认的“22”改为“22,2222”用逗号分隔多个端口。设置着色规则快速定位阶段TCP握手Wireshark默认会用浅蓝色标记TCP的SYN,ACK包很容易识别。SSH协议你可以创建自定义着色规则来高亮不同阶段的SSH包。点击视图-着色规则-新建。名称可以设为“SSH Key Exchange”。过滤器字符串输入ssh.protocol 20SSH_MSG_KEXINIT的协议代码是20。选择一个醒目的背景色比如浅黄色。同样可以为认证报文ssh.protocol 50设置浅绿色为通道报文设置浅紫色。 这样在密密麻麻的数据包列表中不同功能的SSH报文会以不同颜色突出显示分析效率大增。4. 逐步抓包分析与协议报文解读现在让我们结合一个真实的抓包文件假设我们已成功连接从头到尾“走读”一遍SSH的完整对话。以下分析基于Wireshark的包列表和详情展开。4.1 阶段一TCP三次握手包1-3包1客户端192.168.1.100发送[SYN]到服务器10.0.0.5:22。Seq0。包2服务器回复[SYN, ACK]。Seq0 Ack1。包3客户端回复[ACK]。Seq1 Ack1。 至此TCP连接建立。这之后的所有包[PSH, ACK]标志位会非常常见表示携带应用层数据。4.2 阶段二SSH版本协商与密钥交换包4-10这是最复杂也最精彩的部分。包4客户端发出第一个SSH报文。在Packet Details面板展开Secure Shell Layer你会看到SSH Version: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6这是一个明文协议标识。服务器在下一个包也会回复自己的版本。包5 6SSH_MSG_KEXINIT交换。这是算法协商。展开此报文你会看到两个长长的列表kex_algorithms密钥交换算法列表如curve25519-sha256,ecdh-sha2-nistp256,ecdh-sha2-nistp384,diffie-hellman-group14-sha256,...server_host_key_algorithms服务器主机密钥算法如rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp256,ssh-ed25519...encryption_algorithms_client_to_server/server_to_client加密算法列表。mac_algorithms_client_to_server/server_to_clientMAC算法列表。compression_algorithms压缩算法列表。 客户端和服务器各自发送自己支持的算法列表最终选择双方列表中都存在的、各自偏好顺序靠前的第一个算法。包7 8SSH_MSG_KEXDH_INIT和SSH_MSG_KEXDH_REPLY。这是Diffie-Hellman密钥交换的核心。在INIT包中客户端发送自己的Diffie-Hellman公钥值e。在REPLY包中服务器发送自己的DH公钥值f以及用其主机私钥签名的数据包含交换的哈希值。这个签名至关重要客户端用它来验证服务器的身份。此时客户端和服务器各自使用对方的DH公钥和自己的DH私钥可以独立计算出相同的共享密钥K。包9 10SSH_MSG_NEWKEYS。双方互相发送此报文宣告密钥交换完成从此之后所有通信将使用刚刚协商出的密钥和算法进行加密。这是一个分水岭在Wireshark中NEWKEYS之后的SSH报文内容将无法直接解析显示为“Encrypted packet (xxx)”因为应用层数据已被加密。4.3 阶段三用户认证包11-?从NEWKEYS之后报文内容加密。但Wireshark如果配置了服务器的RSA私钥可以解密这些流量。在生产环境切勿泄露私钥此处仅为学习。假设我们使用公钥认证包11加密Wireshark解密后显示为SSH_MSG_USERAUTH_REQUEST。详情中会看到username,service name为ssh-connection,method为publickey。还有一个布尔值标志位表示这是否只是“探询”先发公钥问服务器是否接受。包12加密服务器回复SSH_MSG_USERAUTH_PK_OK表示认可该公钥。包13加密客户端发送正式的认证请求这次包含了一个用用户私钥对会话标识符等数据的签名。包14加密服务器验证签名通过回复SSH_MSG_USERAUTH_SUCCESS。如果是密码认证method字段会是password你会看到加密后的密码数据但Wireshark解密后会明文显示再次强调安全。4.4 阶段四会话建立与数据传输包15-...认证成功后开始建立会话通道。包15加密SSH_MSG_CHANNEL_OPEN。channel type为session请求打开一个会话通道。包16加密服务器回复SSH_MSG_CHANNEL_OPEN_CONFIRMATION分配本地和远程的通道ID。后续包你会看到SSH_MSG_CHANNEL_REQUEST请求启动一个pty伪终端然后是shell请求。之后你终端里输入的每一个字符如ls -l和服务器返回的每一个字符都会被打包成SSH_MSG_CHANNEL_DATA报文在加密隧道中传输。5. 基于抓包的经典故障排查实战理论结合实践抓包最大的威力体现在排错上。下面我们模拟并分析几种常见故障。5.1 连接被拒绝Connection refused现象ssh userhost后立刻返回 “Connection refused”。抓包分析客户端发送[SYN]包到服务器的22端口。服务器直接回复[RST, ACK]包。诊断这表明TCP层面连接被拒绝。根本原因是服务器22端口没有进程监听。可能的情况有SSH服务未启动 (systemctl status sshd)、防火墙规则丢弃了连接、或者服务器根本就不是你想象的IP。5.2 协议版本不匹配现象连接失败客户端或服务器日志提示协议版本不兼容。抓包分析完成TCP握手。客户端发送SSH-2.0-OpenSSH_8.9。服务器可能回复SSH-1.99-...表示支持1.99和2.0或者直接回复一个错误并关闭连接。如果服务器只支持SSH-1.0而客户端强制使用SSH-2.0现代客户端默认在版本字符串交换后连接会被重置。诊断查看双方交换的第一个明文协议版本包。确保客户端和服务器至少有一个共同的协议主版本号SSH-1.x 或 SSH-2.0。现代环境应统一使用SSH-2.0。5.3 密钥交换失败现象连接卡住一段时间后超时或提示“no matching key exchange method found”。抓包分析观察SSH_MSG_KEXINIT包。对比客户端和服务器的kex_algorithms列表。诊断如果两个列表完全没有交集密钥交换就无法进行。例如服务器只支持较老的diffie-hellman-group1-sha1已不安全且被许多客户端移除而客户端只支持curve25519-sha256等新算法。解决方案是修改客户端或服务器的SSH配置/etc/ssh/sshd_config中的KexAlgorithms增加双方共有的算法。5.4 认证失败Permission denied现象提示“Permission denied (publickey,password)”。抓包分析需解密密钥交换成功进入加密阶段。查看SSH_MSG_USERAUTH_REQUEST和服务器回复。如果服务器回复SSH_MSG_USERAUTH_FAILURE并且partial success为false说明尝试的认证方法完全失败。如果服务器回复的失败消息中列出了可继续尝试的方法如publickey,password说明公钥认证失败但还可以尝试密码。诊断公钥认证失败检查客户端发送的公钥是否在服务器的~/.ssh/authorized_keys文件中以及文件权限是否正确必须是600。密码认证失败用户名或密码错误。在解密包中可以直接看到明文用户名和密码安全风险。审计日志服务器的/var/log/auth.log或/var/log/secure通常会给出更具体的失败原因如“invalid user”、“user not allowed”等结合抓包可以精准定位。5.5 连接交互缓慢现象输入命令后响应很慢。抓包分析使用Wireshark的“统计” - “对话”功能查看TCP流。关注TCP包的Time since previous frame列。诊断TCP重传如果看到大量相同的Seq号重复发送说明网络丢包严重导致TCP层不断重传拖慢速度。延迟确认如果服务器对客户端数据的ACK回复很慢可能是系统启用了TCP延迟确认机制。可以尝试在客户端或服务器调整TCP参数如TCP_NODELAY。DNS反向解析服务器可能在尝试对客户端IP进行反向DNS解析如果解析超时会导致连接建立阶段变慢。在服务器SSH配置中设置UseDNS no可以解决。6. 高级技巧与安全注意事项掌握了基础分析后一些高级技巧和安全意识能让你更上一层楼。6.1 使用显示过滤器精确定位捕获过滤器用于抓取前过滤显示过滤器用于抓取后分析。在Wireshark顶部的过滤栏输入ssh显示所有SSH协议包。ssh.protocol 20只显示密钥交换初始化包。ssh.message_code 51只显示用户认证请求包。tcp.analysis.retransmission显示所有TCP重传包用于分析网络质量。ip.addr 10.0.0.5 tcp.port 22功能类似捕获过滤器但用于显示过滤。6.2 跟踪完整的TCP流或SSH流右键任意一个相关数据包选择“追踪流” - “TCP流”或“TLS流”对于加密后的SSHWireshark可能识别为TLS。这会弹出一个新窗口以ASCII或十六进制形式显示该连接的所有应用层数据拼接后的结果。对于分析交互式命令和响应非常有用尤其是解密后。6.3 绝对重要的安全警告切勿在生产环境解密流量为了解密SSH加密报文Wireshark需要服务器的私钥。绝对不要将生产服务器的私钥导入你的Wireshark。这等同于把保险箱钥匙交给别人。解密操作仅限在你自己完全控制的、隔离的测试环境中进行。注意隐私信息即使不解密SSH连接建立初期的版本信息、支持的算法列表等也是明文的。在分享抓包文件.pcapng时可以使用Wireshark的“文件” - “导出特定分组”功能并勾选“移除所有分组捕获信息”来匿名化或者至少编辑掉明文版本字符串中的具体软件版本号。理解局限性对于使用aes256-gcm等现代加密模式的SSH连接即使拥有私钥Wireshark也可能无法解密因为GCM模式的处理方式不同。抓包分析的重点应放在协议握手阶段和问题诊断上而非窥探加密后的内容。通过这次从理论到实践、从正常流程到故障排查的完整旅程你应该已经对SSH协议的内在工作原理有了立体的认识。下次再遇到SSH连接问题你手中的Wireshark就是最强大的诊断工具。记住协议本身是枯燥的文本但通过网络抓包这个“显微镜”你能亲眼看到这些文本如何转化为流动的比特构筑起我们每天依赖的安全通道。这种从抽象到具象的理解正是网络工程师和安全研究者核心能力的体现。尝试去分析一次SCP文件传输的流程你会发现它只是在会话通道中承载了不同的SSH_MSG_CHANNEL_REQUEST这种举一反三的乐趣才是技术探索中最大的回报。