1. SSH是什么
简单说,SSH是一种网络协议,用于计算机之间的远程加密登录。
SSH 为 Secure Shell的缩写,由 IETF 的网络小组(Network Working Group)所制定,SSH 为建立在应用层基础上的安全协议。SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。SSH最初是UNIX系统上的一个程序,后来又迅速扩展到其他操作平台。SSH安装容易、使用简单,而且比较常见,一般的Unix系统、Linux系统、FreeBSD系统都附带有支持SSH的应用程序包。Windows如果需要使用SSH,可以安装PuTTY或者Cygwin。
2. SSH原理
非对称加密技术
SSH 服务基于非对称加密(public-key cryptography,也称公开密钥加密)技术实现数据加密传输。该技术会生成一对数学相关的密钥,其中一个用于对数据进行加密,而且只能用于加密,而另一个只能用于解密。使用加密密钥加密后的数据,只能用对应的解密密钥才能解密。而且,只知道其中一个密钥,无法计算出另一个。因此,如果公开了一对密钥中的一个,并不会危害到另一个的秘密性质。通常把公开的密钥称为公钥(public key),而不公开的密钥称为私钥(private key)。
一般来说,非对称加密的应用场景有两个:
- 公钥是用来解密的。比如A给B发送消息,B使用A的公钥验证A发布的数据或文件的完整性、准确性,以防止数据篡改。相应的密钥称为数字签名(数字证书)。
- 公钥是用来加密的。比如A给B发送消息,A使用B的公钥给消息加密,以防被劫持后泄漏。SSH服务基于该场景实现。
与对称密钥加密相比,非对称加密的优点在于不存在共享的通用密钥。由于解密用的私钥无需发送给任何用户,所以可以避免密钥被劫持或篡改。而加密用的公钥即便被劫持或篡改,如果没有与其匹配的私钥,也无法解密数据。所以,截获的公钥是没有任何用处的。
当前,SSH主要采用 RSA 算法(协议 V2 默认算法)和 DSA 算法(协议 V1 仅支持该算法)来实现非对称加密技术。
3. SSH连接交互过程
SSH连接时,整个交互过程如上图。,主要可以分为三个阶段
服务端准备阶段
服务端在每次启动 SSH 服务时,都会自动检查 /etc/ssh/ 目录下相关密钥文件的有效性。如果相关文件检查发现异常,则会导致服务启动失败,并抛出相应错误信息。 如果文件相关不存在,则会自动重新创建。
默认创建的相关文件及用途说明如下:
ll /etc/ssh/
-rw-------. 1 root root 125811 Aug 13 2015 moduli → 用于 DH-GEX 算法
-rw-r--r--. 1 root root 2047 Aug 13 2015 ssh_config → SSH 客户端配置文件
-rw-------. 1 root root 3879 Aug 13 2015 sshd_config → SSH 服务配置文件
-rw-------. 1 root root 672 May 20 14:22 ssh_host_dsa_key → DSA 算法私钥
-rw-r--r--. 1 root root 590 May 20 14:22 ssh_host_dsa_key.pub → DSA 算法公钥
-rw-------. 1 root root 963 May 20 14:22 ssh_host_key → SSH V1 版RSA 算法私钥
-rw-r--r--. 1 root root 627 May 20 14:22 ssh_host_key.pub → SSH V1 版 RSA 算法公钥
-rw-------. 1 root root 1675 May 20 14:22 ssh_host_rsa_key → SSH V2 版 RSA 算法私钥
-rw-r--r--. 1 root root 382 May 20 14:22 ssh_host_rsa_key.pub → SSH V2 版 RSA 算法公钥
非对称加密协商
当服务器SSH服务启动,客户端也安装了SSH后,就可以进行连接了。
- 客户端向服务端发送连接请求。
客户端连接服务器有两种方式:1. 密码登录。2. 密钥登录。
客户端通过SSH工具连接服务端。相关信息通过明文发送,发送的请求包括IP地址和用户名,服务器识别对应的客户端公钥(保存在$HOME/.ssh/authorized_keys
中),找到该公钥后,服务器通过公钥加密一段随机字符串,并使用共享密钥加密后发送给客户端。如果未找到公钥,则需要输入密码。
- 客户端向服务端发送连接请求。
- 服务端返回公钥信息
根据客户端所使用的服务协议版本及算法设置,返回相应公钥信息。比如,默认情况下,客户端通过 SSH V2 版协议,基于 RSA 算法建立连接,则服务端将ssh_host_rsa_key.pub
文件中的内容返回客户端。相关信息通过明文发送。
- 服务端返回公钥信息
- 客户端对服务端公钥信息进行比对和确认
客户端接收到服务端公钥信息后,会进行如下比对,并让用户对相关信息进行确认。- 如果是首次连接服务端,客户端会收到类似如下信息,让用户确认公钥指纹的有效性:
The authenticity of host '192.168.0.1 (192.168.0.1)' can't be established. RSA key fingerprint is c2:49:d9:43:74:d5:ed:bc:28:9b:d2:7b:63:94:cf:bc. Are you sure you want to continue connecting (yes/no)?
- 如果用户输入 no ,则连接中断并报错(Host key verification failed)。
- 如果用户输入 yes,则会将相应的公钥信息,保存到当前用户家目录下 .ssh 目录内的 known_hosts 文件中。 比如:
cat ~/.ssh/known_hosts
# IP 明文显示: 192.168.0.1 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA3sdlboGEgY9buZpkPuygPw0NxAvmxYd0mc3fo2MgP+JqgFC9/9ZXOgDXKJrjE2HKBieJZSPKGncIh+zLxTvmykeJQBXv7i1GiUjW+H3VY69Ge3AdGfCd+XF+Cvi1e+j18zhHnjSzvIBoNpT5cBWWNbw7mNHCwTb0sHAVUkWR4Ck/LM5/rQ09A+m6BLfZJL8CRNGxKTbyINi6o812S+Cy64WqDs1nTpIXp2Bkcpjclb36bFSs9Z/tWNuJl7A//7HNtxMgFGBnE07Ykvvy8s06DUmkyFy8GcXGBpnfdg9utLodfQLFQnKflCQZ110BpQaCWlWPjU9dc4w3XLJ/XQOP4w== # IP 加密处理: 3efXAZ4sNHcUcHamBy4gDriblc8=|8idBhLq9aLl2sfh4KswMsk4sPFI= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwS4DE3hok8RCkxYlTxsexNrNa62e05UGSkoP7ie26DDWjG1Aoc74cCsE4is9p7lEfFUYYlAzeYhPqE/yGf5YxRZUOU2IeFI4cEqo8YZr7edVYpgAq2f2J0zMwk1syenD12lmUPkYA4mMB6it3jxXR5k+H0HZh9YA7mRXkiTjlkAMWirBcnUvtKYRv9LRIr3ikUiPy2gfZO291Ae9zuTsWwEtHQxIpiBgk3vwF2gCUFlX9y//IsMjdQq5prk7x3BjXhUorqgJO1gt1VHW8Xxx9Oe50YF1hi9DuE6VXwyh4xfHTmauRQybwsYafdA3HxrA2od6x9l19D9EH7xHAjDa5w==
- 如果服务端因重装系统等因素导致公钥指纹出现变化,则会直接导致连接失败(报错Host key verification failed),则需要删除已保存的条目后再重新连接。
- 如果之前已经成功连接,而且公钥指纹对比一致,则会继续下一步操作。
- 客户端对服务端公钥信息进行比对和确认
- 客户端生成临时密钥对
服务端公钥校验及确认后,客户端会生成一对临时密钥用于客户端加密。该密钥对不会存储到文件,而是记录在内存中。每次连接都会重新生成临时密钥对。
- 客户端生成临时密钥对
- 客户端发送公钥信息
客户端向服务端,发送前述生成的临时密钥对中的公钥信息。相关信息通过明文发送。
- 客户端发送公钥信息
后续数据交互过程
后续登录校验及正常的数据传输,都会通过双向加密方式进行。相关交互说明如下:
- 如果服务端需要发送数据给客户端:
- 服务端使用所持有的客户端公钥,对需要传输的数据进行加密,再发送给客户端。
- 客户端收到信息后,使用所持有的自身私钥解密后获取数据。
- 反之,如果客户端需要发送数据给服务端,也是类似的流程:
- 客户端使用所持有的服务端公钥,对需要传输的数据进行加密,再发送给服务端。
- 服务端收到信息后,使用所持有的自身私钥解密后获取数据。
3. SSH相关文件
从这个连接过程中,可以看出,主要使用到两个文件夹下的内容:
- ~/.ssh/
这里主要是客户端连接信息和密钥存储的敌方。这个文件夹下的内容可以使用命令ssh-keygen
生成,执行这个命令后,会生成两个文件,id_rsa
和id_rsa.pub
。第一个是私钥文件,第二个是公钥文件。但是这都是针对当前登录用户的。也就是说,只对当前用户有效。 - /etc/ssh/
这个主要是ssh配置和服务器密钥存储的地方。由SSH服务启动时生成。
在连接中的两个过程:
- 客户端存储服务器的公钥到本地
也就是上面的第二步。服务器返回回来的公钥是/etc/ssh
下的,比如
服务器下的/etc/ssh
ssh_host_ecdsa_key.pub
之所以有多组密钥,是因为使用了不同的加密算法。
客户端接收到之后,会存储在~/.ssh/known_hosts
文件里,查看这个文件,可以看到有一行与服务器ssh_host_ecdsa_key.pub
内容一致。
- 客户端将公钥存储到服务器中
在请求连接过程中,如果使用密钥的方式登录,那么就需要先把客户端的公钥存储到服务器中。
首先需要通过ssh-keygen
生成当前账户的私钥。然后将公钥传送到远程主机host上面:
$ ssh-copy-id user@host
其实,它是将客户端的~/.ssh/id_rsa.pub
文件内容追加到服务器文件~/.ssh/authorized_keys
中。
所以,~/.ssh/authorized_keys
里表示本机可以被哪些机器访问
~/.ssh/known_hosts
里表示本机访问过哪些机器
4. SSH相关配置
SSH配置文件有两个,一个是ssh_config
,一个是sshd_config
。前者是客户端配置,后者是服务器配置。也就是说,如果本机是作为客户端,那么就修改第一个配置,如果本机是作为服务器,那么就修改第二个配置,
一般来说,和密钥登录的配置有关的有以下几个,如果密钥配置好后无法登录,尝试配置以下三项。
RSAAuthentication yes
PubkeyAuthentication yes # 如果为yes,则无法使用密码登录
AuthorizedKeysFile .ssh/authorized_keys
其他
passwordAuthentication no # 只能通过私钥访问
4. SSH安全
中间人攻击
传统的网络服务程序,如FTP、Pop和Telnet在传输机制和实现原理上是没有考虑安全机制的,其本质上都是不安全的。因为它们在网络上用明文传送数据、用户帐号和用户口令,别有用心的人通过窃听等网络攻击手段非常容易地就可以截获这些数据、用户帐号和用户口令。而且,这些网络服务程序的简单安全验证方式也有其弱点,那就是很容易受到"中间人"(man-in-the-middle)这种攻击方式的攻击。
所谓"中间人"的攻击方式,就是"中间人"冒充真正的服务器接收你的传给服务器的数据,然后再冒充你把数据传给真正的服务器。服务器和你之间的数据传送被"中间人"一转手做了手脚之后,就会出现很严重的问题。中间人能够攻击,主要原因在于他能认识截取的信息,也能发出让接受者认识的信息。
使用SSH,你可以把所有传输的数据进行加密,这样"中间人"这种攻击方式就不可能实现了,而且也能够防止DNS欺骗和IP欺骗。使用SSH,还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。SSH有很多功能,它既可以代替Telnet,又可以为FTP、Pop、甚至为PPP提供一个安全的"通道"。
最初的SSH是由芬兰的一家公司开发的。但是因为受版权和加密算法的限制,现在很多人都转而使用OpenSSH。OpenSSH是SSH的替代软件包,而且是免费的,可以预计将来会有越来越多的人使用它而不是SSH。