介绍
OpenSSH是SSH(Secure SHell)协议的免费开源实现,可以用来进行远程控制或在计算机之间传送文件,比传统的telnet、rcp ftp等工具更安全1。
OpenSSH的开源代码可以在这里下载,也可以在GitHub上查看。
OpenSSH主要提供了以下功能
- ssh:客户端程序,用来连接到远程服务器,执行命令或传输文件。
- sshd:服务端程序,用来监听客户端的连接请求,验证身份,提供服务。
- scp:客户端程序,用来在本地和远程之间复制文件。
- sftp:客户端程序,用来在本地和远程之间交互式地传输文件。
- ssh-keygen:客户端程序,用来生成密钥对,用于公钥认证。
- ssh-agent:客户端程序,用来管理私钥,避免重复输入密码。
- ssh-add:客户端程序,用来向ssh-agent添加私钥。
- ssh-keyscan:客户端程序,用来收集远程主机的公钥。
- ssh-keysign:服务端程序,用来为主机认证签名。
- ssh-pkcs11-helper:客户端程序,用来支持PKCS#11令牌设备。
- sftp-server:服务端程序,用来提供sftp服务。
- ssh_config:客户端配置文件,用来设置连接参数。
- sshd_config:服务端配置文件,用来设置服务参数。
OpenSSH源码分析
openssh的目录结构有些松散,没有对其代码按照特性或者功能去划分,其主要目录如下
目录名 | 功能 |
openbsd-compat | 兼容BSD操作系统的代码实现 |
regress | 相关测试用例和脚本实现 |
m4 | 存放的是一些宏处理器的文件,用于配置文件和脚本的生成 |
其余零散源文件 | openssh主体功能代码实现 |
主体功能代码分析
功能板块 | 具体功能 | 文件名 | 功能点 |
SSH客户端 | 交互式会话主循环 | clientloop.c | 包含了SSH客户端的主要事件循环,它处理输入和输出,管理通道,等等; |
ssh客户端守护进程 | ssh.c | SSH客户端的主要入口点,它初始化客户端,处理命令行参数,然后进入主事件循环等 具体而言,ssh.c文件负责以下功能:
| |
SSH服务端 | ssh服务端守护进程 | sshd.c | SSH服务器的主要入口点,它初始化服务器,处理命令行参数,然后进入主事件循环等 具体而言,sshd.c文件负责以下功能:
|
算法套实现 | 加密算法实现 (cryptographic cipher implementations) | cipher.c/cipher.h, cipher-*.c | 这处理SSH加密和解密,它们包含了处理各种加密算法的函数; |
秘钥交换算法实现 (Key exchange algorithms implementations, KEX) | kex.c/kex.h, kexdh.c , kexecdh.c , kexgex.c , etc.. | 实现不同处理各种密钥交换方法的函数 方法,如 Diffie-Hellman、ECDH、Group Exchange | |
消息完整性算法实现 (Message authentication code algorithms implementations, MAC) | mac.c , mac.h, mac-*.c | 数据完整性检查的各种 MAC 算法(例如 HMAC-SHA1、HMAC-SHA256)的实现和支持 | |
通用工具 | 网络地址处理 | addr.* | socket地址处理相关工具函数实现 |
对socket使用的封装 | atomicio.* | 封装socket数据读写接口,用于保证保证数据在套接字上完整传输的函数; | |
事件记录和报告 | audit*.* | 用于实现记录和报告SSH事件实现,可以根据不通平台和配置,调用相应的审计模块来处理SSH事件 | |
用户认证 | 用户认证(User Authentiucation) | auth*.* | 处理用户身份验证,它们包含了处理各种身份验证方法(如密码、公钥等)的函数; |
channels.c/channels.h | 处理SSH通道的创建和管理,SSH通道用于在客户端和服务器之间创建加密的通信路径; | ||
配置读取 | 配置读取 | readconf.c/readconf.h | 处理SSH配置文件的读取和解析; |
SSH主体流程在开源代码中的实现分析
源码文件 | 函数名 | |
ssh.c | main | 入口函数,它负责解析命令行参数、初始化日志、读取配置文件、加载密钥、创建套接字等; |
ssh_connect | 负责与服务器建立TCP连接,并协商协议版本、交换密钥、验证服务器身份等; | |
ssh_login | 登录函数,它负责根据配置文件和服务器请求,调用不同的认证方法,如密码认证、公钥认证、Kerberos认证等,并检查服务器权限和登录限制; | |
client_loop | 主循环函数,它负责处理客户端的输入和输出,包括转发X11、TCP/IP、认证连接,以及执行shell命令或子系统请求等; | |
sshd.c | main | sshd的入口函数,它负责解析命令行参数、初始化日志、读取配置文件、设置信号处理器、创建主进程和子进程等; |
server_accept_loop | sshd的主循环函数,它负责接受新的连接请求,并为每个连接创建一个子进程; | |
server_loop2 | sshd的子进程函数,它负责处理一个连接的所有操作,包括协商协议版本、交换密钥、验证用户、分发消息等; | |
do_ssh2_kex | sshd的密钥交换函数,它负责与客户端协商加密算法、压缩算法、MAC算法等,并生成会话密钥; | |
do_authentication2 | sshd的认证函数,它负责根据配置文件和客户端请求,调用不同的认证方法,如密码认证、公钥认证、Kerberos认证等,并检查用户权限和登录限制; | |
do_authenticated2 | sshd的会话管理函数,它负责根据客户端请求,创建和销毁通道(channel),并调用不同的服务函数,如shell服务、exec服务、subsystem服务; |