应用层 SSH 协议及其实现总结
连接协议对比
常见的几种连接协议:
- SSH2(默认,相对于SSH1进行了加密算法的改进,使用最广泛)
- SSH1
- Telnet
- Telnet/SSL
- Rlogin
- Serial
- TAPI
在出现 SSH 之前,系统管理员需要登入远程服务器执行系统管理任务时,都是用 telnet
来实现的,telnet 协议底层使用 TCP 协议,端口号 23
,采用明文密码传送,在传送过程中对数据也不加密,很容易被不怀好意的人在网络上监听到密码。
同样,在 SSH 工具出现之前 R 系列命令也很流行(由于这些命令都以字母 r 开头,故把这些命令合称为 R 系列命令,R 是 remote 的意思),比如 rexec
是用来执行远程服务器上的命令的,和 telnet
的区别是 telnet
需要先登录远程服务器再实行相关的命令,而 R 系列命令可以把登录和执行命令并登出系统的操作整合在一起。这样就不需要为在远程服务器上执行一个命令而特地登录服务器了。
SSH 全称 Secure SHell,顾名思义就是非常安全的 shell 的意思,SSH 协议是 IETF(Internet Engineering Task Force) 的 Network Working Group 所制定的一种协议。SSH 的主要目的是用来取代传统的 telnet 和 R 系列命令(rlogin
、rsh
、rexec
等)远程登录和远程执行命令的工具,实现对远程登录和远程执行命令加密。防止由于网络监听而出现的密码泄漏,对系统构成威胁。
SSH 是一种加密协议,不仅在登录过程中对密码进行加密传送,而且对登录后执行的命令的数据也进行加密,这样即使别人在网络上监听并截获了你的数据包,他也看不到其中的内容。SSH 协议底层使用 TCP 协议,端口号 22
。
鉴权方式对比
不同于 telnet
只支持 Password 密码鉴权,SSH 同时支持以下几种鉴权方式(Authentication):
- Password(密码)
- Public Key(公钥)
- Keyboard Interactive(键盘交互)
- GSSAPI
目前 SSH 最常用的鉴权方式有 Password 和 Public key 。Public Key 非对称(asymmetric)鉴权认证使用一对相关联的 Key Pair(一个公钥 Public Key,一个私钥 Private Key)来代替传统的密码(Password)。顾名思义,Public Key 是用来公开的,可以将其放到 SSH 服务器自己的帐号中,而 Private Key 只能由自己保管,用来证明自己身份。
使用 Public Key 加密过的数据只有用与之相对应的 Private Key 才能解密。这样在鉴权的过程中,Public Key 拥有者便可以通过 Public Key 加密一些东西发送给对应的 Private Key 拥有者,如果在通信的双方都拥有对方的 Public Key(自己的 Private Key 只由自己保管),那么就可以通过这对 Key Pair 来安全地交换信息,从而实现相互鉴权。
OpenSSH
OpenSSH 是 SSH 协议的免费开源实现。OpenSSH 套件由以下工具集组成:
远程操作工具:
ssh
(替代telnet
和rlogin
)scp
(替代rcp
)sftp
(替代ftp
)
公私钥管理工具:
ssh-add
Tool which adds private keys to the authentication agent.ssh-keygen
Key generation tool.ssh-keysign
Helper program for host-based authentication.ssh-keyscan
Utility for gathering public host keys from a number of hosts.
客户端工具:
ssh-agent
An authentication agent that can store private keys.
服务端工具:
sshd
一个运行于服务端的独立守护进程(standalone daemon)sftp-server
SFTP 服务器
常用命令
当管理的服务器较多时,ssh 远程需要频繁的输入用户名、密码、服务器 IP,操作非常繁琐,下面介绍一些命令结合配置以简化操作。
ssh
ssh
命令用法:
1 | $ ssh [-p port] [user@]hostname [command] |
有时候输入 ssh
的参数繁琐,一旦服务器较多,要一个个记住并且敲入时非常低效。因此 ssh
提供了配置文件的方式简化命令行选项。ssh
依序从下列来源中获取配置,最先获取的值将优先使用:
- 命令行选项(command-line options)
- 用户配置文件
~/.ssh/config
- 系统配置文件
/etc/ssh/ssh_config
常用配置项如下:
1 | Host 别名 |
通过配置,ssh
远程命令简化如下:
1 | $ ssh 别名 |
例如:
1 | $ ssh pc2 /sbin/ifconfig |
pc2
是从 ~/.ssh/config
中获取的 hostname 别名。
ssh-keygen
在使用 ssh
进行远程登录时,由于默认使用的是 Password 鉴权方式,因此每次登录都需要输入密码,操作麻烦。下面介绍使用 Public Key 鉴权方式实现免密登录。
一、创建一对公私钥:
1 | $ ssh-keygen -t rsa -C who@where |
二、启动 SSH 认证代理程序:
1 | $ eval `ssh-agent` |
三、添加私钥:
1 | $ ssh-add ~/.ssh/id_rsa |
四、将公钥上传到服务端,添加到被登录帐户的可信列表文件:
1 | $ scp ~/.ssh/id_rsa.pub who@where:~/.ssh/authorized_keys |
五、修改服务端文件权限:
1 | $ chmod 700 ~/.ssh |
之后再使用 ssh
登录时,客户端的 ssh-agent
会发送私钥去和服务端上的公钥做匹配,如果匹配成功就可以免密登录了。
ssh-add
ssh-add
命令常见用法:
1 | usage: ssh-add [options] [file ...] |
例如:
1 | $ ssh-add -D |
参考:http://linux.101hacks.com/unix/ssh-add/
scp
scp
命令常用参数:
1 | -r 递归复制(用以传输文件夹) |
可以结合 bash 的 for
循环实现批量 scp
目录:
1 |
|
相关文件
SSH 相关文件和配置:
文件 | 描述 |
---|---|
~/.ssh/id_rsa.pub | 公钥(Public Key) |
~/.ssh/id_rsa | 私钥(Private Key) |
~/.ssh/known_hosts | 位于客户端的公钥列表文件,首次与目标主机建立 SSH 连接时,需要添加对方的公钥到这个文件以便后续通信 《关于 Linux 中 known_hosts 文件的必知必会》 |
~/.ssh/authorized_keys | 位于服务端的公钥列表文件,列出了所有被允许登录进来的可信公钥信息(Lists the public keys that are permitted for logging in) |
~/.ssh/config | 客户端用户配置文件,可以通过 man ssh_config 命令查看帮助。 |
/etc/ssh/ssh_config | 客户端系统配置文件 |
/etc/ssh/sshd_config | 服务端配置文件 |
ssh banner
https://en.wikipedia.org/wiki/ASCII_art
保持会话不掉线
1 | Host * |
ServerAliveInterval
设置了客户端在发送保持连接信号之前的等待时间。
OpenSSL
OpenSSL 加密库 ( libcrypto
) 实现了各种 Internet 标准中使用的各种加密算法。该库提供的服务被 TLS 和 CMS 的 OpenSSL 实现使用,它们也被用于实现许多其它第三方产品和协议。
该库的功能包括对称加密、公钥加密、密钥协商、证书处理、加密散列函数、加密伪随机数生成器、消息身份验证代码 (MAC)、密钥派生函数 (KDF) 和各种实用程序。
Generate Private and Public Key
https://www.openssl.org/docs/man3.0/man1/openssl.html
- Create Private Key
1 | openssl genrsa -out rsa_private_key.pem 2048 |
- Generate Public Key
1 | openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout |
- Encode Private Key to PKCS#8
1 | openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt |
For signature, please use pkcs8_rsa_private_key.pem (result of step 3).
rsync
批量 scp
的缺点是会全量同步,且删除行为无法同步,可以用 rsync
命令优化:
1 | 拉取: |
如果双方都修改了同一文件的同一个地方,rsync
不管源和目标的修改时间谁先谁后,而是以源作为基准去覆盖目标文件。
常用参数:
-a
:归档模式,等价于-rlptgoD
(不包括-H
,-A
,-X
)-r
,--recursive
:递归遍历目录-l
,--links
:复制软链接(symbolic link, symlinks)-p
,--perms
:保留权限-t
,--times
:保留修改时间-g
,--group
:保留属组-o
,--owner
:保留属主-D
:等价于:--devices
:保留设备文件--specials
:保留特殊文件
-v
,--verbose
:详细输出信息-H
,--hard-links
:保留硬链接(hard links)
批量 rsync
1 |
|
进行如下文件操作测试:
- 新增文件:web-banner-20170717.jpg
- 删除文件:web-banner-20170716.jpg
从输出可见,只会增量同步并删除指定的文件:
1 | sending incremental file list |
参考
https://en.wikipedia.org/wiki/Telnet
https://en.wikipedia.org/wiki/Secure_Shell
在 Linux 上保护 SSH 服务器连接的 8 种方法 | 良许 Linux
《5 Unix / Linux ssh-add Command Examples to Add SSH Key to Agent》
《ssh keygen 中生成的 randomart image 是什么》
《SSH Not Working In MacOS Ventura: How To Fix》