30 分钟

前言

这篇文章介绍了SSH的基本工作原理,列出了可能有用的参考资料,专业性可能会偏强,但我会在保留学术严谨表达的同时,使用通俗语气,让文章不会显得太过难以理解。

说不定会插入几张美图,毕竟学习很辛苦,营造归属感是很重要的

毕竟,总体来说,SSH的工作流本来就不难,是很容易理解的。接下来我会尝试以自己的话解释SSH的完整工作逻辑和使用SSH的原因


-はい! 始まるよ~

SSH的定义

SSH是主要应用于肿瘤研究的用于基因差异表达分析的实验方法

不对,什么鬼

SSH(Secure Shell),安全外壳协议是一种加密的网络传输协议

作为一种协议,SSH存在多种实现,包括商业开源实现(OSSH,OpenSSH)

SSH的核心在于,如何在完全不加密的网络通道上,建立起绝对安全的加密会话

SSH的通信原理

SSH的通信认证过程主要分为两个阶段:密钥交换身份认证

第一阶段:密钥交换(Key Exchange / Handshake)

密钥交换后,可以根据 双方共有仅双方共有 的数据,来加密信息流

所以如何获取符合要求的共享密钥是关键

1. 版本协商(明文传输)

SSH有很多版本,不同设备支持的版本可能不同,需要先进行版本协商,确定双方都能接受的版本方案

具体操作如下:

  1. 服务器端监听
    • 服务器开放 TCP 端口 22,等待客户端连接
  2. 客户端发起连接
    • 客户端向服务器端发起 TCP 初始连接请求
  3. 服务器发送版本标识
    • 服务器向客户端发送第一个报文,包含版本标志字符串,格式为:
        SSH-<主协议版本号>.<次协议版本号>.<软件版本号>
      
    • 其中,协议版本号 = 主版本号 + 次版本号,软件版本号主要用于调试和实现标识
  4. 客户端解析并选择协议版本
    • 若服务器协议版本低于客户端版本,且客户端支持该低版本,则采用服务器端协议版本
    • 否则,使用客户端自身的协议版本
  5. 客户端回应版本号
    • 客户端向服务器发送报文,告知最终选定的协议版本号。
  6. 服务器确认协商结果
    • 若协商成功,进入密钥交换与算法协商阶段
    • 若协商失败,服务器直接断开 TCP 连接。

参考资料:

具体数据字节可以参考这篇博客,解释的非常清楚

具体流程如下,参考了这篇博客

2. 算法协商

双方交换支持的加密算法列表(如 Ed25519, AES-GCM 等),并选择最优解

  1. 服务器端与客户端分别向对端发送算法协商报文
    报文中包含各自支持的:
    • 公钥算法列表
    • 对称加密算法列表
    • MAC(Message Authentication Code,消息验证码)算法列表
    • 压缩算法列表等。
  2. 服务器端与客户端根据双方支持算法的交集,协商并确定最终使用的算法组合。

参考文献:RHCE 作业2

3. 生成共享密钥

这里就是魔法的发生点,是涉及数学密码学原理的核心

服务器端与客户端通过 Diffie–Hellman(DH)密钥交换,结合主机密钥对等参数,生成:

  • 会话密钥(Session Key)
  • 会话 ID(Session ID)
Diffie-Hellman密钥交换流程:
参数选择 → 密钥生成 → 公共值交换 → 共享密钥计算

具体的DH密钥交换操作主要是由 模幂运算 实现的

3.1 数学方式

  • 运算技术: 模运算
  • 安全性基础: 离散对数问题

基本流程:

  1. 约定参数:双方约定两个大质数 $g$(生成元)和 $p$(大质数模数)(均公开)
  2. 私有选择:亚澄选择一个随机大整数 $a$ 作为私钥;妃爱选择一个随机大整数 $b$ 作为私钥
  3. 计算并交换公钥:亚澄计算 $A = g^a \bmod p$,发送给妃爱;妃爱计算 $B = g^b \bmod p$,发送给亚澄
  4. 算出共享密钥 (K):亚澄计算 $K = B^a \bmod p$;妃爱计算 $K = A^b \bmod p$。

根据数学交换律:

\[K = (g^b \bmod p)^a \bmod p = (g^a \bmod p)^b \bmod p = g^{ab} \bmod p\]

所以最后可以得出相等的密钥,且根据离散对数问题,仅由$g$、$p$、$A$、$B$是很难直接推出各自的私钥$a$、$b$,并进而很难推出会话的密钥$K$


参考文献:OSChina:SSH传输层协议Tencent:Diffie-Hellman密钥交换技术解析

图源引用自:一文搞懂Diffie-Hellman密钥交换协议


3.2 直观解释

基本流程:

  1. 双方公开选择一种底色(如蓝色
  2. 亚澄随机选取一个只有自己知道的颜色(绿色);妃爱机选取一种只有自己知道的颜色(红色
  3. 亚澄把公共蓝色绿色(得到青色)混合;妃爱公共蓝色红色(得到紫色)混合,互相交换颜色
  4. 亚澄拿到紫色,再和绿色混合;妃爱拿到青色,再和红色混合,两者都获得了一模一样的神秘深褐色

虽然第三方拿到了紫色和青色,但是也无法分离出红色和绿色

3.3 共享密钥的前向安全性

得到的共享密钥K仅在单次会话中有效,所以即使私钥泄露,也不会造成历史通信流量泄露

3.4 Diffie-Hellman的中间人攻击模式

攻击者截获计算得到的A和B,而是向亚澄和妃爱两者分别发送自己的C1,C2

这样就会在自己和亚澄、妃爱两者之间分别建立安全连接,而亚澄和妃爱都不知道通信被截获,信息劫持成功

结语

至此,双方获得相同的会话密钥和会话 ID。后续数据传输均使用该会话密钥进行加密与解密,以保证通信安全

第二阶段: 身份认证:挑战-响应机制

现在,我们已经有了一段安全的‘悄悄话通道’(对称加密)

但妃爱还得确认,对面坐着的真的是亚澄,而不是伪装成亚澄的黑客。

具体过程:

  1. 发送钥匙 ID: 亚澄告诉妃爱“我想用指纹为 SHA256:… 的这把钥匙登录。”

  2. 检查名单:妃爱在账户设置(Settings -> SSH keys)里查找。如果找到了匹配的公钥,它会生成一个随机数(Challenge)

  3. 加密挑战:妃爱用你的公钥对这个随机数进行加密,然后发给亚澄。公钥加密的东西,只有对应的私钥能解开

  4. 解密与签名:亚澄收到密文,动用保存在 ~/.ssh/id_ed25519 的私钥将其解开。

  5. 为了证明自己确实解开了,亚澄会将解出的随机数加上当前会话的 ID,再用私钥进行数字签名(Signature),发回给妃爱

  6. 最终验证:妃爱用公钥验证这个签名。如果签名有效,说明亚澄确实持有私钥。


数学背景:

  • 核心概念:陷门函数
  • RSA加密:基于大数分解
  • ECC(椭圆曲线算法):基于几何轨迹

由于技术比较成熟,而且网络文献比较多,我就不详细介绍了,可以去B站或者Bing查

可以参阅这篇文章:椭圆曲线加密算法(ECC)

图源引用自:知乎:SSH 密钥身份验证和管理

后期通信

在获得共享密钥$K$之后,后期信息流都是通过加密算法加密传输

目前最主流、最安全的对称加密算法是 AES(高级加密标准),可以参考 知乎:高级加密标准(AES)

在 SSH 连接中,通常配合 GCM(伽罗瓦/计数器模式) 或 ChaCha20-Poly1305 使用。它的特点是:加密和解密用的是同一个密钥 $K$


加密传输过程:

  1. 分组与填充:数据被切成固定大小的数据块。如果最后一块不够大,会填入一些随机数。
  2. “异或”运算与置换:将数据块和密钥$K$进行一次异或运算,再进行字节代换行移位列混淆生成密文
  3. 解密:只需要使用共享密钥$K$进行反向操作即可

数据的加密传输过程中,加密和解密的速度都是非常快的,能保证数据传输的效率

AES 如此之快,是因为现代 CPU(包括树莓派 4B 搭载的 ARM 处理器)通常都有专门的硬件指令集加速这些逻辑运算,它不像 RSA 那样需要消耗大量 CPU 周期去算大数的幂次方

至此,SSH通信的基本原理和流程就讲清楚了。我们可以使用现成的OpenSSH进行各种远程信息传输了(虽然其实没搞懂也能轻松使用SSH就是了,不过能搞懂原理总是对使用有利无害)

为什么要从HTTPS切换到SSH?

拿Github来讲,我之前的Git操作都是通过HTTPS协议完成的

比如,我的远程仓库就是https://github.com/Eganchiyu

那么我就直接push到这个网址就行了,握手后,服务器会做一系列操作,本次请求就算完成

但是在中国用过github的都知道,github的网络是何等的不稳定,一旦dns污染了,就根本完成不了这些基本的操作了

HTTPS和SSH协议比对

特性 HTTPS (HyperText Transfer Protocol Secure) SSH (Secure Shell)
底层协议 建立在 TLS/SSL 之上,运行在 443 端口。 独立的 SSH 协议,通常运行在 22 端口。
身份验证 主要是基于证书颁发机构(CA)。客户端验证服务器的证书是否由受信任的机构签发。 基于非对称加密。客户端将公钥给服务器,服务器通过挑战/响应机制验证客户端持有的私钥。
连接过程 涉及复杂的 TLS 多次握手(Client Hello、Server Hello、交换证书等)。 相对简洁的密钥交换和身份验证流程。
主要用途 网页浏览、通用 API 调用。 远程管理服务器、代码托管同步(Git)。

为什么SSH更稳定?

我们常遇到的 GnuTLS recv error (-110) 本质上是连接重置(Connection Reset)或握手超时

SSH 能够解决这个问题,主要有以下几个原因:

1. 规避深度包检测 (DPI) 的干扰

HTTPS (443端口) 流量巨大且复杂。国内网络环境会对 TLS 握手包进行高强度的扫描和检测(为了识别 SNI 信息)

如果检测过程中出现丢包或延迟,握手就会失败

SSH (22端口) 的流量特征与网页浏览完全不同,其流量相对“纯粹”,受到的针对性协议干扰有时比 HTTPS 略小。

2. 状态保持与重连机制

HTTPS 是无状态的短连接,每次 git push/pull 都要重新经历完整的 TLS 握手流程,任何一次握手失败都会报错

SSH 在建立连接时,验证的是你预先存放在 GitHub 上的公钥。只要 RSA/Ed25519 的密钥交换完成,连接就会非常稳固

对于 Git 操作,SSH 的处理逻辑更直接,减少了因证书校验失败导致的意外中断。

3. 绕过过载的 Web 代理/网关

很多运营商或校园网会对 443 端口(网页流量)进行复杂的流量整形(Traffic Shaping)或代理缓存

由于 SSH 流量通常被视为“运维/管理”流量,往往能避开这些针对普通网页访问的限速或过滤规则(装大佬这一块)

局限性:HTTPS和SSH都无法解决DNS污染

在正常的网络环境下,DNS 服务器会返回 GitHub 真实的 IP(比如 20.205.243.166)。但在受污染的环境下,中间节点返回一个错误的、无法访问的、甚至是虚假的 IP 地址。

这在HTTPS和SSH中都会有表现:

  1. HTTPS 表现:获取Ip错误,浏览器尝试去跟这个错误 IP 建立 TLS 连接。由于 IP 根本不对,握手会直接超时,或者报错“证书不匹配”

  2. SSH 表现:解析出的 github.com 错误,ssh -T git@github.com 会连接失败

结语

辛苦读了这么久文章,现在起身去活动一下吧。一直坐在电脑桌前总是对身体不好的。

身体是革命的本钱。搞好身体才能用现有技术去创造全新的技术,并更好地服务大众。

作为知识的拓荒者,要深入到生活中,或者工业、军事、国际等,去了解,到底现在需要什么,然后看准了就不怕麻烦、有节奏地去做好

作为百姓,我们也不能因为技术的发展而完全依赖。要开动自己的脑子,去做更多有意义的事情。作为人类,有意义的事情莫过于和重要的人一起待着,去给世界提供更多的感动,去为自己和重要的人创造更多美好的回忆,让这一生至少值得被自己记住

所以,想一想吧,现在开始,能做些什么,让你的今天变得值得回忆呢?

去外面走走,去邂逅猫猫狗狗,去和家人逛街,精心准备礼物,用相机镜头记录下一切,或者是听歌、唱歌

这个世界很简单,简单到人与人的沟通其实不需要通讯加密。但是好多人都忘记了。网络梗、没必要的博弈在包装着情感。当然,这也是有必要的,只不过应该在需要用它的时候再启用。

如果找到了心有灵犀的伙伴,就把公钥给他一份,然后创造一个安全通信空间,用真心对待和珍惜


接下来我会记录在笔记本与树莓派树莓派与github之间SSH认证和通信的过程,写成一篇新的博客,敬请期待!

附:会有一些我折腾词典笔的珍贵记录

留下评论