嵌入式-常见协议(SSH )
Transport Layer(传输层)提供机密性、完整性、压缩(可选),负责密钥协商、加密通道建立,以及服务端主机密钥认证。常见内容:密钥交换(KEX)、对称加密算法、消息认证码(MAC)、压缩。User Authentication Layer(用户认证层)在安全通道上对用户进行认证:密码、publickey、keyboard-interactive、hostbased 等。Connectio
目录
5) 用户身份认证(User Authentication)
SSH(Secure Shell)是一个用于在不安全网络上做安全远程登录和安全通道的协议。主要功能:命令行远程登录、命令执行、端口转发、文件传输(SCP/SFTP)和隧道/代理。核心价值是提供机密性(加密)、完整性(MAC)和身份认证(主机与用户)。
第一部分概述
1) 协议分层(RFC 系列的三层模型)
SSH 协议通常按三层理解(RFC 4251 等):
-
Transport Layer(传输层)
-
提供机密性、完整性、压缩(可选),负责密钥协商、加密通道建立,以及服务端主机密钥认证。
-
常见内容:密钥交换(KEX)、对称加密算法、消息认证码(MAC)、压缩。
-
-
User Authentication Layer(用户认证层)
-
在安全通道上对用户进行认证:密码、publickey、keyboard-interactive、hostbased 等。
-
-
Connection Layer(连接/通道层)
-
在单个 SSH 会话内多路复用多个“channel”(pty、exec、subsystem、forwarding)。实现远程 shell、端口转发、SFTP 子系统等。
-
2) 关键步骤:建立一条 SSH 会话时发生了什么

-
TCP 三次握手建立到服务器的 TCP 连接(默认端口 22)。
-
双方交换协议版本字符串(如
SSH-2.0-OpenSSH_8.6)。 -
密钥协商(KEX):协商使用的 KEX 算法、对称加密、MAC、压缩等,并基于协商使用 Diffie-Hellman / ECDH / Curve25519 等生成会话密钥(在此阶段也进行服务器主机密钥签名以防中间人)。
-
建立加密通道(Transport layer)并完成服务器主机验证(known_hosts / TOFU)。
-
用户认证(UserAuth):客户端以密码或公钥等方式进行认证。
-
连接层:认证通过后,客户端可以打开 channel 来请求 shell、执行命令、建立端口转发或请求 SFTP 子系统。
3) 密钥交换(KEX)与算法
常用 KEX 算法(安全性随时演进,请参照你系统的 OpenSSH 版本):
-
curve25519-sha256/curve25519-sha256@libssh.org(现代且推荐) -
ecdh-sha2-nistp256/ nistp384 等(椭圆曲线 DH) -
diffie-hellman-group14-sha256(传统的安全选择)
对称加密(示例,优先现代 AEAD):
-
推荐:
chacha20-poly1305@openssh.com、aes256-gcm@openssh.com、aes128-gcm@openssh.com -
旧但仍见:
aes256-ctr、aes128-ctr
MAC(消息认证,不同实现名称不同):
-
推荐 AEAD(如 GCM/ChaCha20-Poly1305)已经包含认证。若使用单独 MAC:
umac-64-etm@openssh.com、hmac-sha2-256-etm@openssh.com(ETM = encrypt-then-MAC 更安全)
注:实际使用时以 OpenSSH 的默认优先级为准,但你可以在 sshd_config / ssh_config 中强制配置。
4)主机身份认证(Host Authentication)
-
当你第一次连接
ssh user@host时,客户端会检查远程服务器的 host key(主机公钥)。 -
作用:保证你连接的确实是目标主机,而不是中间人(MITM 攻击)。
-
过程:
-
客户端拿到服务器的 host key(第一次会提示确认指纹,之后保存到
~/.ssh/known_hosts)。 -
后续连接时,客户端比对 host key,确认一致。
-
-
这步其实不是认证你身份,只是验证远程主机“可信”。
-
算是 SSH 协议自动协商的一部分(握手 + 密钥交换 + host key 验证),用户几乎不用管。
🔹 技术上这是非对称加密 + 签名,确保通道安全,但它只认证服务器,不认证你。
5) 用户身份认证(User Authentication)
-
真正让远程主机“相信是你可以登录”的步骤。
-
方式:
-
密码认证:直接发送密码(通过已经加密的通道)。
-
公钥认证:客户端用私钥对服务器 challenge 签名,服务器用公钥验证。
-
其他方式:keyboard-interactive、GSSAPI 等。
-
-
只有用户身份验证通过后,才允许打开 session channel 执行命令。
-
这才是真正意义上的“认证你可以访问远程系统”。
6)ssh的生态

| 功能模块 / 工具 | 是否独立程序 | 是否必须 | 说明 |
|---|---|---|---|
| SSH 协议 | ❌ 协议规范 | ✅ 必须 | 客户端和服务端都必须实现才能通信 |
| SSH shell | ❌ shell | ✅ 协议必须支持❌ 实际可用视服务器配置 | 协议定义必须支持 shell 通道,但服务器可选择禁用,只做 SFTP 或端口转发也可以 |
| SCP | ✅ scp 命令 | ❌ 可选 | 文件复制工具,依赖服务器端 scp 命令(shell) |
| SFTP | ✅ sftp / sftp-server | ❌ 可选 | 文件传输子系统,依赖服务器端 sftp-server |
| 端口转发(本地/远程/动态) | ❌ 内置功能 | ❌ 可选 | 内建在客户端 ssh 命令中,无需额外程序 |
| ssh-keygen | ✅ 程序 | ❌ 可选 | 用于生成密钥,实现免密登录 |
| ssh-agent / ssh-add | ✅ 程序 | ❌ 可选 | 管理私钥,安全便捷 |
| authorized_keys | ❌ 文件 | ❌ 可选 | 服务器端保存公钥,实现免密登录 |
| rsync over SSH | ✅ 程序 | ❌ 可选 | 基于 SSH 的高效文件同步工具 |
| Ansible / Fabric / Paramiko | ✅ 程序/库 | ❌ 可选 | SSH 自动化运维工具,应用层扩展 |
第二部分实用功能(命令示例与说明)
1)远程登录
远程登录的作用是让你像在本地一样访问和控制另一台机器——执行命令、查看/修改文件、运行服务或做维护,而不需要物理接触那台主机;其原理是客户端先与服务器建立 TCP 连接并通过密钥交换协商出一个对称会话密钥以构建加密通道,客户端验证服务器的 host key 以防中间人,然后在该安全通道内进行用户认证(如密码或公钥);认证通过后客户端在该通道上打开一个 session channel,发送 exec 或 shell 类型的协议消息把命令或按键输入传给远端,远端在本地系统上执行并把 stdout/stderr、退出码等作为协议消息加密返回,整个过程的数据传输、完整性校验和会话管理都由 SSH 协议的报文(packet)和 channel 机制负责。命令行示例如下
ssh user@host
ssh -p 2222 user@host # 指定端口
ssh -i ~/.ssh/id_ed25519 user@host # 指定私钥
2)文件传输(SCP/SFTP)
文件传输的作用是让本地主机与远程主机之间安全、可靠地交换文件,用于上传配置、下载日志、备份数据或同步代码。其原理是在已有的通信协议(如 SSH、FTP、HTTP 等)上,通过定义文件读写与数据分块传输的规则,实现文件内容在两端之间的复制。以 SCP/SFTP(基于 SSH) 为例:客户端与服务器先建立加密的 SSH 通道,协商算法并完成用户认证;随后在该安全通道内,客户端通过协议消息(如 OPEN、READ、WRITE、CLOSE)分块读取或写入远程文件,服务器执行相应的文件操作并返回结果。整个过程的数据传输与命令控制都在加密隧道中完成,从而保证文件内容和操作指令的机密性、完整性与可靠性。命令行示例如下
scp file.bin user@host:/tmp/
scp -r ./dir user@host:/tmp/
sftp user@host
sftp> put file.bin
sftp> get file.bin
3)端口转发
SSH 端口转发(Port Forwarding,又称隧道 tunneling)的作用是:让本地或远程的网络流量通过一条 安全的 SSH 加密通道 转发,从而实现对内部服务的安全访问、绕过防火墙限制、或在不暴露端口的情况下远程使用资源。
SSH 建立连接时,除了可用于登录和命令执行外,还可以在会话中创建一个 通用的数据通道(Channel) 来转发 TCP 数据。
这意味着:
-
客户端或服务器在本地监听一个端口(比如 8080)。
-
当该端口收到连接请求时,SSH 会把该 TCP 数据封装成 SSH 数据包(CHANNEL_DATA),通过已经加密的通道发送给另一端。
-
另一端的 SSH 进程再把数据转发给目标主机和端口(如数据库、Web 服务等)。
-
返回数据反向传输,仍然通过 SSH 隧道加密回传。
整个过程相当于把一条 TCP 连接“套进”SSH 的加密通道里,让原本明文的通信安全传输。
| 类型 | 命令示例 | 作用 | 数据流向 |
|---|---|---|---|
| 本地转发(Local Forwarding) | ssh -L 8080:intranet.server:80 user@remote |
把本地 localhost:8080 的访问通过 SSH 隧道转发到远程内网的 intranet.server:80 |
本地 → 远程 |
| 远程转发(Remote Forwarding) | ssh -R 9090:localhost:22 user@remote |
让远程主机的 9090 端口转发到本地 22(可远程访问本地服务) |
远程 → 本地 |
| 动态转发(Dynamic Forwarding / SOCKS) | ssh -D 1080 user@remote |
创建本地 SOCKS5 代理,通过 SSH 动态转发任意目标流量(常用于科学上网或代理访问) | 本地 ↔ 任意目标 |
4)X11 转发(图形界面,需服务端允许)
X11(或称 X Window System)是一种用于 Unix/Linux 系统的图形显示协议与系统架构,它定义了图形界面程序(X Client)与显示服务器(X Server)之间的通信方式。其核心思想是显示与计算分离:应用程序负责计算与绘图请求,而显示服务器负责在屏幕上实际渲染图形、处理键盘和鼠标输入。X11 使用网络透明的通信机制,允许应用程序运行在远程主机上,而图形界面显示在本地主机上,因此常与 SSH 结合,通过 X11 Forwarding 实现“远程运行图形程序,本地显示窗口”,在保持安全加密传输的同时提供完整的图形交互体验。
SSH 的 X11 转发是一种利用 SSH 加密通道安全地传输图形界面数据的机制,其作用是让用户在本地终端中运行远程主机上的图形化程序,并在本地显示窗口界面。其原理是在建立 SSH 连接时,客户端请求开启 X11 转发(例如使用 ssh -X user@host),服务器端将远程应用的图形输出通过 SSH 协议封装后加密传输回客户端;客户端再把这些图形数据交给本地的 X Server(如 XQuartz、VcXsrv)显示。这样,远程程序的界面、鼠标与键盘事件都通过安全的 SSH 隧道双向传输,实现远程运行、本地显示的安全图形交互。
ssh -X user@host # 或 -Y(可信 X11)
5)跳板机(ProxyJump)
SSH 跳板机(Jump Server 或 Bastion Host)的作用是作为受控的中转节点,用于安全地访问位于内网或受限网络中的服务器,从而实现分层防护与集中审计。其原理是:用户首先通过 SSH 连接到跳板机(这通常是唯一可从外网访问的主机),然后由跳板机再向目标内网服务器发起二次 SSH 连接。这样外部用户不会直接接触目标主机,所有操作都经过跳板机的身份验证、授权与日志记录。现代 SSH 客户端还支持自动跳转方式(如 ssh -J jump@bastion target@internal 或 ProxyJump 配置),在协议层通过建立多级隧道把命令与数据加密转发到最终目标主机,实现隔离访问、安全审计与精细化控制
# 从 local -> jump -> target
ssh -J jumpuser@jump.example.com targetuser@target.internal
# 或配置 ~/.ssh/config 中 ProxyJump
第三部分常用工具及三方库
-
OpenSSH (ssh, scp, sftp) — CLI 为主,Linux/macOS 原生,Windows 可安装;服务端与客户端都很常见。
-
PuTTY — Windows 下经典轻量 GUI 客户端,支持 key、会话保存。
-
KiTTY — PuTTY 的派生,增加许多功能(脚本、自动登录等)。
-
MobaXterm — Windows 上的增强终端,内置 X11、SFTP、会话管理,适合开发/运维。
-
SecureCRT — 商业级终端(多协议、强管理功能),企业用户常用。
-
Bitvise SSH Client — Windows GUI 客户端,支持 SFTP、端口转发、代理。
-
Termius — 跨平台(桌面/手机)的 SSH 客户端,支持同步会话与密钥。
-
Dropbear — 轻量级 SSH 服务端/客户端,常见于嵌入式设备。
-
OpenSSH for Windows / Windows OpenSSH Server — 在 Windows 上提供原生 sshd/ssh 支持。
-
WinSCP — 主要做 SFTP/SCP 文件传输,但也能用来启动远程终端(带 GUI)。
-
Remmina — Linux 下的远程桌面/SSH 客户端,适合多协议管理多主机。
嵌入式 / 库 / 自动化工具
-
libssh / libssh2 / paramiko (Python) — 用于在程序中实现 SSH 功能(自动化、脚本化、备份、配置管理)。
-
Ansible / Salt / Fabric / Capistrano — 自动化运维工具,基于 SSH 批量执行命令、部署与管理(适合大规模运维)。
附录A 命令行详解
基本语法
ssh [选项] [user@]host [命令]
-
user:远程登录用户名,可省略(默认取当前用户)。
-
host:目标主机的 IP 或域名。
-
命令(可选):若提供,将在远程主机执行该命令后退出;若省略,则进入交互式 shell。
| 选项 | 说明 |
|---|---|
-p <port> |
指定 SSH 连接端口(默认 22)。 |
-i <identity_file> |
指定私钥文件路径(如 ~/.ssh/id_rsa)。 |
-l <user> |
指定远程登录用户名(等价于 user@host)。 |
-v, -vv, -vvv |
显示调试信息(连接问题排查利器)。 |
-X |
开启 X11 转发(远程图形程序显示在本地)。 |
-Y |
开启可信的 X11 转发(比 -X 权限更高)。 |
-L <[bind_address:]port:host:hostport> |
本地端口转发,将本地端口流量转发到远程主机。 |
-R <[bind_address:]port:host:hostport> |
远程端口转发,将远程主机端口流量转发到本地。 |
-D <[bind_address:]port> |
动态端口转发(SOCKS 代理模式)。 |
-J <user@jump_host> |
通过跳板机连接目标主机(等价于 ProxyJump)。 |
-C |
启用压缩,提高低带宽环境下的性能。 |
-N |
不执行远程命令,仅建立连接(常用于端口转发)。 |
-T |
不分配伪终端(适合执行脚本命令)。 |
-t |
强制分配伪终端(即使执行单条命令)。 |
-o <option=value> |
指定临时配置项(如 -o StrictHostKeyChecking=no)。 |
-4, -6 |
强制使用 IPv4 或 IPv6。 |
-q |
静默模式,减少输出信息。 |
| 功能 | 示例命令 | 说明 |
|---|---|---|
| 登录远程主机 | ssh user@192.168.1.10 |
最常见方式,进入远程 shell。 |
| 指定端口 | ssh -p 2222 user@server |
登录非默认端口。 |
| 执行单条命令 | ssh user@host "ls /var/log" |
执行完命令后自动退出。 |
| 使用指定密钥 | ssh -i ~/.ssh/id_rsa user@host |
指定私钥文件认证。 |
| 禁止主机验证提示 | ssh -o StrictHostKeyChecking=no user@host |
自动接受主机 key(自动化场景)。 |
| 本地端口转发 | ssh -L 8080:intranet:80 user@bastion |
访问内网 Web 服务。 |
| 远程端口转发 | ssh -R 9090:localhost:22 user@remote |
让远程主机访问本地服务。 |
| 动态转发(SOCKS 代理) | ssh -D 1080 user@remote |
让本地变成一个安全代理。 |
| 使用跳板机 | ssh -J jump@bastion target@internal |
通过跳板机登录内网主机。 |
| 开启 X11 转发 | ssh -X user@remote |
运行远程图形应用并显示在本地。 |
| 测试连接调试 | ssh -vvv user@host |
输出详细调试信息。 |
你也可以把常用参数放到配置文件中简化命令行:
Host myserver
HostName 192.168.1.10
User root
Port 2222
IdentityFile ~/.ssh/id_rsa
Compression yes
ServerAliveInterval 60
然后直接执行:
ssh myserver
附录B 协议讲解
SSH(Secure Shell)协议是一个分层的网络协议,用于安全的远程登录和服务。根据 RFC 4251,SSH 协议分为三个主要子协议:
- 传输层协议(RFC 4253):建立安全通道、密钥交换、服务器认证。
- 用户认证协议(RFC 4252):用户身份验证。
- 连接协议(RFC 4254):多路复用通道(如 shell、端口转发)。
所有子协议使用二进制报文格式,报文通过 TCP 传输。以下详细解析通用报文格式和各层功能码(消息码)。所有字段使用网络字节序(big-endian),数据类型包括:
- byte:1 字节。
- uint32:4 字节无符号整数。
- string:uint32 长度 + 数据(UTF-8 或 ASCII)。
- name-list:逗号分隔的字符串列表。
- mpint:多精度整数(用于密钥)。
- boolean:0(false)或 1(true)。
1. 通用报文格式(Binary Packet Protocol)
根据 RFC 4253,每个 SSH 报文结构如下:
| 字段 | 类型 | 长度(字节) | 描述 |
|---|---|---|---|
| packet_length | uint32 | 4 | 整个报文长度(不包括本字段和 mac)。 |
| padding_length | byte | 1 | 随机填充长度(4-255 字节)。 |
| payload | byte[n1] | n1 | 有效载荷(n1 = packet_length - padding_length - 1)。 以 message_code(1 字节)开头。 如果协商压缩,则压缩。 |
| random_padding | byte[n2] | n2 | 随机填充(n2 = padding_length)。 总长度(不含 mac)必须是加密块大小(或 8)的倍数。 |
| mac | byte[m] | m | 消息认证码(MAC),基于共享密钥 + 序列号 + unencrypted_packet 计算。 |
- 总大小:最小 16 字节 + mac;最大 payload 32768 字节,总报文 ≤ 35000 字节。
- 加密:packet_length、padding_length、payload、random_padding 被加密;mac 在外。
- 序列号:隐式 uint32,从 0 开始递增(每报文 +1,溢出 2^32)。
- 示例报文大小计算:
text
packet_length = 1 (message_code) + 方法特定数据 + padding_length + 1 总加密部分 = packet_length + 4 (packet_length 字段) - 处理流程:
- 接收前 8 字节解密 packet_length。
- 读取完整报文,解密 payload。
- 验证 MAC。
- 解压 payload(如果启用)。
- 解析 message_code 和数据。
2. 功能码(Message Codes)解析
消息码范围:1-255。
- 1-19:传输层通用。
- 20-29:算法协商。
- 30-49:密钥交换特定。
- 50-59:认证通用。
- 60-79:认证方法特定。
- 80-89:连接全局请求。
- 90-127:连接通道相关。
- 128-191:客户端协议保留。
- 192-255:本地扩展。
2.1 传输层协议功能码(RFC 4253)
| 消息码 | 名称 | 功能描述 | 主要字段示例 |
|---|---|---|---|
| 1 | SSH_MSG_DISCONNECT | 断开连接。 | uint32 reason_code, string description |
| 2 | SSH_MSG_IGNORE | 忽略(防流量分析)。 | string data |
| 3 | SSH_MSG_UNIMPLEMENTED | 未实现消息响应。 | uint32 sequence_number |
| 4 | SSH_MSG_DEBUG | 调试消息。 | boolean always_display, string message |
| 5 | SSH_MSG_SERVICE_REQUEST | 请求服务(如 "ssh-userauth")。 | string service_name |
| 6 | SSH_MSG_SERVICE_ACCEPT | 服务接受。 | string service_name |
| 20 | SSH_MSG_KEXINIT | 密钥交换初始化。 | name-list kex_algorithms 等 |
| 21 | SSH_MSG_NEWKEYS | 新密钥激活。 | 无 |
| 30 | SSH_MSG_KEXDH_INIT | Diffie-Hellman 密钥交换发起。 | mpint e |
| 31 | SSH_MSG_KEXDH_REPLY | DH 响应。 | string host_key, mpint f, string signature |
- 密钥交换流程:KEXINIT → 方法特定(30-49)→ NEWKEYS。
- 原因码(Disconnect):1=主机不允许,2=协议错误 等(详见 RFC)。
2.2 用户认证协议功能码(RFC 4252)
| 消息码 | 名称 | 功能描述 | 主要字段示例 |
|---|---|---|---|
| 50 | SSH_MSG_USERAUTH_REQUEST | 认证请求。 | string user_name, string method ("publickey"/"password") |
| 51 | SSH_MSG_USERAUTH_FAILURE | 认证失败。 | name-list authentications, boolean partial_success |
| 52 | SSH_MSG_USERAUTH_SUCCESS | 认证成功。 | 无 |
| 53 | SSH_MSG_USERAUTH_BANNER | 认证横幅。 | string message |
| 60 | SSH_MSG_USERAUTH_PK_OK | 公钥可接受(publickey 方法)。 | string public_key_algorithm, string public_key |
| 60 | SSH_MSG_USERAUTH_PASSWD_CHANGEREQ | 密码变更请求(password 方法)。 | string prompt |
- 认证方法:
方法 请求格式(在 REQUEST 中) 签名数据 publickey boolean FALSE/TRUE, string alg, string key session_id + 请求数据 password boolean FALSE (标准)/TRUE (变更), string pw 无 hostbased string host_key, string client_host 等 session_id + 请求数据
2.3 连接协议功能码(RFC 4254)
全局请求(80-82)
| 消息码 | 名称 | 功能描述 | 示例 |
|---|---|---|---|
| 80 | SSH_MSG_GLOBAL_REQUEST | 全局请求(如端口转发) | string "tcpip-forward", uint32 port |
| 81 | SSH_MSG_REQUEST_SUCCESS | 请求成功 | uint32 bound_port |
| 82 | SSH_MSG_REQUEST_FAILURE | 请求失败 | 无 |
通道消息(90-100)
| 消息码 | 名称 | 功能描述 | 主要字段 |
|---|---|---|---|
| 90 | SSH_MSG_CHANNEL_OPEN | 打开通道(如 session)。 | string type ("session"), uint32 sender_channel |
| 91 | SSH_MSG_CHANNEL_OPEN_CONFIRMATION | 打开确认。 | uint32 recipient_channel |
| 92 | SSH_MSG_CHANNEL_OPEN_FAILURE | 打开失败。 | uint32 reason_code (1=禁止 等) |
| 93 | SSH_MSG_CHANNEL_WINDOW_ADJUST | 窗口调整。 | uint32 bytes_to_add |
| 94 | SSH_MSG_CHANNEL_DATA | 通道数据。 | string data |
| 95 | SSH_MSG_CHANNEL_EXTENDED_DATA | 扩展数据(如 stderr)。 | uint32 data_type_code (1=STDERR) |
| 96 | SSH_MSG_CHANNEL_EOF | 通道结束。 | 无 |
| 97 | SSH_MSG_CHANNEL_CLOSE | 关闭通道。 | 无 |
| 98 | SSH_MSG_CHANNEL_REQUEST | 通道请求(如 shell)。 | string type ("shell"/"exec"), string command |
| 99 | SSH_MSG_CHANNEL_SUCCESS | 请求成功。 | 无 |
| 100 | SSH_MSG_CHANNEL_FAILURE | 请求失败。 | 无 |
- 通道类型:session(shell)、direct-tcpip(本地转发)、forwarded-tcpip(远程转发)。
- 终端模式(pty-req):使用操作码表(详见下表)。
终端模式操作码表(部分)
| 操作码 | 助记符 | 描述 |
|---|---|---|
| 1 | VINTR | 中断字符 |
| 3 | VERASE | 擦除字符 |
| 50 | ISIG | 启用信号 |
| 53 | ECHO | 回显输入 |
| 128 | TTY_OP_ISPEED | 输入波特率 |
| 0 | TTY_OP_END | 结束 |
3. 协议流程示例
- 版本交换:纯文本 "SSH-2.0-software"。
- 传输层:KEXINIT → NEWKEYS。
- 认证:SERVICE_REQUEST ("ssh-userauth") → USERAUTH_REQUEST → SUCCESS。
- 连接:SERVICE_REQUEST ("ssh-connection") → CHANNEL_OPEN ("session") → CHANNEL_REQUEST ("shell")。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐

所有评论(0)