一直对 SSH 、SSL 以及 HTTPS 和它们互相之间的关系都云里雾里的,下面参考网上的文章和自己的理解梳理一下,晕了就再回来看一下,总会记住的。
加密算法
首先先说下加密算法,可以分为两大类,对称加密
和 非对称加密
。
对称加密
通信双方的数据都是用同一套密钥来进行加密和解密。
在1976年以前,所有的加密都采用对称加密,这种加密方式最大的问题就是如何管理秘钥?既要保证秘钥不泄露,同时还要保证秘钥的共享性。
非对称加密
1976年有两位数学家提出的一个新的加密概念:
- A生成一对两把密钥(公钥和私钥)。
- B获取A生成的公钥,然后用公钥对信息加密。
- A收到B的加密信息后,用自己的私钥解密。
非对称加密引入了公钥和私钥的概念。公钥加密,私钥解密。公钥是面向所有使用者公开的。
目前计算机领域使用最广泛的非对称加密算法是RSA。
对称加密看起来很强大,但是也有缺点:
- 加密更耗时:算法更复杂。
- 容易受到中间人攻击:即如果有C冒充A利用A的公钥给B发消息,B的所有消息对C其实就是透明的了。
针对中间人攻击,一般就采用非对称加密+摘要算法+数字签名的机制来确保传输安全。
摘要算法(hash算法)
Hash 算法的特点是单向不可逆。利用这个特性,可以通过hash对目前信息加密生成特定长度且唯一的hash值,该值也不能被逆向破译。因此hash算法进场用在不可还原的密码存储、信息完整性校验等领域。常见的hash算法:MD2,MD4,MD5,SHA等
数字签名
数字签名,是为了保证信息在传输过程中没有被篡改。使用hash算法生成要发送明文的摘要,然后 把明文和摘要都通过私钥加密,加密后的摘要作为数字签名(digital signature)
跟加密后的内容一起发送给接受者。接受者收到数据信息后,使用公钥分别对内容和信息解密,得到数据和内容摘要,然后用一样的算法对内容生成摘要,比较摘要是否相同来确认信息的完整性。
数字证书
以上的流程还是存在一个问题就是,有人冒充通信人发放公钥。这种场景的出现,我们就需要有个公证人了,告诉我们到底有是真的注册登记过的。这个公证人就是证书中心(certificate authority)简称CA。
所有想发放公钥的人,都需要去CA为自己的公钥做认证。证书中心会用自己私钥和公钥以及公钥人信息一起进行加密,生成的东西就叫数字证书。以后所有类似的场景,都是统一用CA的公钥解开数字证书,拿到通信用的公钥,然后证明数字签名确实是来自哪里的了。
关于数字签名和数字证书,阮一峰老师的这篇文章讲的特别生动blog
SSH
wiki上对SSH的定义:
Secure Shell(缩写为SSH),由IETF的网络工作小组(Network Working Group)所制定;SSH为一项创建在应用层和传输层基础上的安全协议,为计算机上的Shell(壳层)提供安全的传输和使用环境。
传统的网络服务程序,如rsh、FTP、POP和Telnet其本质上都是不安全的;因为它们在网络上用明文传送数据、用户帐号和用户口令,很容易受到中间人(man-in-the-middle)攻击方式的攻击。就是存在另一个>人或者一台机器冒充真正的服务器接收用户传给服务器的数据,然后再冒充用户把数据传给真正的服务器。
而SSH是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用SSH协议可以有效防止远程管理过程中的信息泄露问题。通过SSH可以对所有传输的数据进行加密,也能够防止DNS欺骗和IP欺骗。
SSH之另一项优点为其传输的数据可以是经过压缩的,所以可以加快传输的速度。SSH有很多功能,它既可以代替Telnet,又可以为FTP、POP、甚至为PPP提供一个安全的“通道”。
看了以后显然更晕了,注意一下他是一个SHELL
, 可以理解为 SSH 服务器之间安全通信的一个协议,既然称之为安全的,想必是通信过程使用了加密手段。
这时候就用上了我们上一节的知识了,我们现在要在服务器之前就行安全的通信:
- A、B之间建立TCP连接
- B生成一对公私密钥
- B把公钥发送给A
- A生成一个用于加密数据的密钥K(既我们想通知给客户端的密钥,之后的数据通信都使用这个密钥加密,这个密钥不可让第三方知道)
- A把K用公钥加密发送给B,B解密后,从此A、B之间的通信数据都用K密钥进行加密和解密(转为了安全的对称加密方式)。
这个过程还是会有一样的问题,加入中间有C、D,假冒B发放公钥给A,夹在了A和B之间,不是又不安全了吗。
为了解决这个问题SSH协议采用由人工判断公钥的fingerprint是否可信的方式:
1 | The authenticity of host '172.20.7.211 (<no hostip for proxy command>)' can't be established. |
输入yes之后才会连接到远程服务器,同时这个信息会存储到用户的.ssh/known_hosts文件中,下次再登录的时候,会检查known_host文件,如果存在相同的公钥信息,就不在提示用户确认了.相当于中间加了一步人工验证,确定下要连接的机器,作为客户端一般也确实是知道自己要连谁的。
当然这一步也可以手动跳过:
1 | ssh -o PubkeyAuthentication=yes -o stricthostkeychecking=no |
我们都用过ssh-keygen
命令,他就是为我们生成一对密钥(公钥+私钥),用于我们所说的非对称加密过程
1 | ssh-keygen -t rsa |
将id_rsa.pub的内容写入authorized_keys文件中,表示该机器目前授权的使用该公钥访问
1 | cat id_rsa.pub >> authorized_keys |
这样就将公钥内容追加到authorized_keys中了,然后需要注意配置权限了,否则SSH不会工作:
- 将.ssh目录的权限为700
- 将authorized_keys目录的权限为600
有个ssh-copy-id
工具很好用,一行命令就可以复制公钥到对应服务器下的 authorized_keys。1
ssh-copy-id -i username@remote-server
一个完整的SSH客户端认证流程
一般我们能接触到的的认证方式有两种:
- 密码认证
- 密钥认证
密码认证很好理解,就是我们在登录远程linux服务器的时候提供用户名和密码。
每次登录都要输入密码很麻烦,且密码如果简单的话可能还会被暴力破解,而且很多自动化场景要求我们实现免密登录服务器。密钥认证提供了一种更安全便捷的认证客户端的方式。这个技术也用到了非对称加密技术,由客户端生成公私密钥对,然后将公钥保存在服务器上。认证的过程大体如下:
- 客户端发起一个公钥的认证请求,并发送RSA Key的模数作为标识符。
- 服务端检查是否存在请求帐号的公钥(Linux中存储在~/.ssh/authorized_keys文件中),以及其拥有的访问权限。
- 服务端使用对应的公钥对一个随机的256位的字符串进行加密,并发送给客户端
- 客户端使用私钥对字符串进行解密,并将其结合session id生成一个MD5值发送给服务端。
- 服务端采用同样的方式生成MD5值与客户端返回的MD5值进行比较,完成对客户端的认证。
疑点:这个流程确实是一个完整的非对称加密处理的认证过程,但是实际使用中我发现客户端并没有发送自己的公钥,因为我把客户端的公钥删了,或者只复制私钥到一个新的客户端上,最终还是可以登入authorized_keys中配置了对应公钥的服务器。
- 所以我猜测客户端发送请求后,服务端这边是把authorized_keys中的锁让客户端的钥匙循环匹配的?能打开其中的一把锁就能登录,但是这样key多的话,建立连接就会有效率问题。
- 另一个猜测,这个发送的RSA_KEY的模数是通过私钥就能产生的,就是说通过私钥有办法直接得到它对应公钥的标志,所以客户端也就用不着专门保存公钥,也不用直接发送的公钥进行认证。
目前我也不确定为啥客户端没发送自己的公钥,最后也能登录的真正原因。
SSL
TLS(Transport Layer Security:它相当于是SSL协议的一个后续版本,他是SSL经过IETF标准化之后的产物。
上面wiki上也有写,SSH其实是专门为shell设计的一种通信协议,它垮了两个网络层(传输层和应用层)。通俗点讲就是只有SSH客户端,和SSH服务器端之间的通信才能使用这个协议,其他软件服务无法使用它。但是其实我们非常需要一个通用的,建立在应用层之下的一个传输层安全协议,它的目标是建立一种对上层应用协议透明的,不管是HTTP、FTP、还是电子邮件协议或其他任何应用层协议都可以依赖的底层的可安全通信的传输层协议。SSL(Secure Sockets Layer)协议就是在此背景下诞生的。
对于一个通用的协议来说,类似SSH使用printfinger来防止中间人攻击不一样,互联网上所有的客户端和服务器是不可能自己判断对方是不是可信。这个时候就用到了我们所说的 数字证书
的概念,在SSL中引入了一个公证机关,就是我们熟知的 CA
。有了数字证书,浏览器在建立SSL连接之前,并不只是简单获取服务器的公钥,而从服务器获取数字证书。有了信任机制之后,剩下的交互过程还是我们所熟知的非对称加密过程。
图解SSL/TLS协议-阮一峰
HTTPS
上面的概念清晰了以后,理解HTTPS就简单了。HTTPS的全程是 Hypertext Transfer Protocol Secure,就是 运行在 SSL/TLS 之上的 HTTP协议。
做为网站管理员,可能会遇到申请数字证书的任务,理解了上面的概念,申请数字证书就不那么一头雾水了,首先你要为服务器生成一对公司密钥,然后把你网站的信息连同你的公钥一起发送给某个权威的CA,CA会通过某种方式认证申请人是否真的是网站的所有人,比如让你在网站的指定路径上传他指定的特殊蚊子序列。验证通过就会得到证书了。