web安全之https详解
# 1 HTTPS 概念
HTTPS(HyperText Transfer Protocol over Secure Socket Layer)超文本传 输安全协议, 近两年 Google、Baidu、Facebook 等这样的互联网巨头,不谋而合地开始大力推行 HTTPS, 国内外的大型互联网公司很多也都已经启用了全站 HTTPS,这也是未来互联网发展的趋势。
为鼓励全球网站的 HTTPS 实现,一些互联网公司都提出了自己的要求:
- Google 已调整搜索引擎算法,让采用 HTTPS 的网站在搜索中排名更靠前;
- 从 2017 年开始,Chrome 浏览器已把采用 HTTP 协议的网站标记为不安全网站;
- 苹果要求 2017 年 App Store 中的所有应用都必须使用 HTTPS 加密连接;
- 当前国内炒的很火热的微信小程序也要求必须使用 HTTPS 协议;
- 新一代的 HTTP/2 协议的支持需以 HTTPS 为基础。
因此在不久的将来,全网 HTTPS 势在必行。
- 作用
- 对数据进行加密,并建立一个信息安全通道,来保证传输过程中的数据安全;
- 对网站服务器进行真实身份认证。
- 使用特征 我们经常会在 Web 的登录页面和购物结算界面等使用 HTTPS 通信。
- 使用 HTTPS 通信时,不再用 http:// ,而是改用 https:// 。
- 当浏览器访问 HTTPS 通信有效的 Web 网站时,浏览器的地址栏内会出现一个带锁的标记。
# 2 架构图
HTTPS 并非是应用层一个新的协议,通常 HTTP 直接和 TCP 通信,HTTPS 则先 和安全层(SSL/TLS)通信,然后安全层再和 TCP 层通信
SSL/TLS 协议就是为了解决上面提到的 HTTP 存在的问题而生的,下面我们来看 一下它是怎么解决的:
- 所有的信息都是加密传输的,第三方无法窃听
- 配备身份验证(服务端程序),防止身份被冒充
- 具有校验机制,一旦被篡改,通信双方会立刻发现
# 3 HTTPS 工作原理
HTTPS 是身披 SSL/TLS 外壳的 HTTP
协议版本 | 描述 |
---|---|
SSL 1.0 | 存在严重的安全漏洞,从未公开过 |
SSL 2.0 | 2.0 版本在 1995 年 2 月发布,但因为存在数个严重的安全漏洞而被 3.0 版本替代 |
SSL 3.0 | 3.0 版本在 1996 年发布 |
TLS 1.0 | IETF 对 SSL3.0 进行了标准化,并添加了少数机制(但是几乎和 SSL3.0 无差异) |
TLS 1.1 | LS 1.1 在 RFC 4346 中定义,于 2006 年 4 月发表 |
TLS 1.2 | TLS 1.2 在 RFC 5246 中定义,于 2008 年 8 月发表 |
TLS 1.3 | TLS 1.3 在 RFC 8446 中定义,于 2018 年 8 月发表 |
TLS 协议是由 TLS 记录协议(TLS record Protocol)和 TLS 握手协议(TLS handshake Protocol)这两层协议叠加而成的。
- 记录协议:TLS Record protocol
- TLS 记录协议位于 TLS 握手协议的下层,是负责使用对称密码对消息进行加密通信的部分
- 加密使用的密钥是通过握手协议在服务器和客户端之间协商决定的
- 握手协议:TLS Handshaking Protocols 由 TLS Change Ciper Spec Protocol(密码规格变更协议)和 TLS Alert Protocol(警告协议)组成
- 负责在客户端和服务器之间协商决定密码算法和共享密钥。
- 密码规格变更协议负责向通信对象传达变更密码方式的信号,当协议中途发生错误时,就会通过警告协议传达给对方。
- 警告协议是 TLS 握手协议负责在发送错误时将错误传达给对方。
HTTPS 和 HTTP 协议相比提供了
- 数据完整性:内容传输经过完整性校验
- 数据隐私性:内容经过对称加密,每个连接生成一个唯一的加密密钥
- 身份认证:第三方无法伪造服务端(客户端)身份
其中,数据完整性和隐私性由 TLS Record Protocol 保证,身份认证由 TLS Handshaking Protocols 实现。
理解 HTTPS 前需要理解这些概念:对称加密、非对称加密、摘要算法、数字签 名、证书、认证中心(CA - Certificate Authority)
# 3.1 对称加密算法
(1)定义:
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。
(2)要素:
原文、秘钥、算法
秘钥:在密码学中是一个定长的字符串、需要根据加密算法确定其长度
(3)工作过程:
对称加密通常使用的是相对较小的密钥,一般小于 256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。如果你只用 1 bit 来做这个密钥,那黑客们可以先试着用 0 来解密,不行的话就再用 1 解;但如果你的密钥有 1 MB 大,黑客们可能永远也无法破解,但加密和解密的过程要花费很长的时间。密钥的大小 既要照顾到安全性,也要照顾到效率。
加密:明文 + 密钥 -> 密文
解密:密文 + 密钥 -> 明文
2
DES(Data Encryption Standard):数据加密标准(现在用的比较少,因为它的加密强度不够,能够暴力破解)
3DES:原理和 DES 几乎是一样的,只是使用 3 个密钥,对相同的数据执行三次加密,增强加密强度。(缺点:要维护 3 个密钥,大大增加了维护成本)
AES(Advanced Encryption Standard):高级加密标准,用来替代原先的 DES,目前美国国家安全局使用的,苹果的钥匙串访问采用的就 AES 加密。是现在公认的最安全的加密方式,是对称密钥加密中最流行的算法。 AES128 和 AES256 主要区别是密钥长度不同(分别是 128bits,256bits)、加密处理轮数不同(分别是 10 轮,14 轮),后者强度高于前者。
(5)特点
优点:算法公开、计算量小、加密速度快、加密效率高。
缺点:相对来说不算特别安全,只有一把钥匙,密文如果被拦截,且密钥也被劫持,那么,信息很容易被破译。
(6)推演
为了防止上述现象的发生,人们想到一个办法:对传输的信息加密(即使黑客截获,也无法破解)
加密公式: f1 ( key(密钥),data ) = X(密文)
解密公式: f2 ( key(密钥),X(密文) ) = data
2
- 缺陷:
加密和解密同用一个密钥,加密和解密都会用到密钥,没有密钥就无法对密码解密,反过来说,任何人只要持有密钥就能解密。
- 改进:
比如服务器为每一个客户端请求的 TCP 连接生成一个唯一的 key
缺陷:
不同的客户端、服务器数量庞大,所以双方都需要维护大量的密钥,维护成 本很高
因每个客户端、服务器的安全级别不同,密钥极易泄露
# 3.2 非对称加密算法
(1)简介:
非对称加密是计算机通信安全的基石,保证了加密数据不会被破解
非对称加密算法需要两个密钥:公开密钥(public key) 和私有密(private key) 公开密钥和私有密钥是一对
(2)特点: 如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密。 如果用私有密钥对数据进行加密,只有用对应的公开密钥才能解密。 由于其算法复杂,而使得加密、解密速度没有对称加密解密的速度快。有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了,这样安全性就大了很多。
(3)常用算法:
RSA、DSA、ECDSA
(4)推演 - 非对称加密
公钥加密:f1 ( publicKey,data ) = X
私钥解密:f2 ( privateKey,X ) = data
私钥加密:f3 ( privateKey,data) = X
公钥解密:f1 ( publicKey,X) = data
2
3
4
私钥保存在服务端,公钥保存在客户端,私钥永远不对外暴露
缺陷:
公钥是公开的(也就是黑客也会有公钥),所以第 ④ 步私钥加密的信息,如果被黑客截获,其可以使用公钥进行解密,获取其中的内容。
(5)推演 - 对称加密和非对称加密
非对称加密既然也有缺陷,那我们就将对称加密,非对称加密两者结合起来, 取其精华、去其糟粕,发挥两者的各自的优势。
解决问题:
通过对称加密和非对称加密的组合使用,解决内容可能被窃听的问题
存在缺陷: 解决报文可能遭篡改问题 解决通信方身份可能被伪装的问题
解决方案:
- 解决报文可能遭篡改问题——数字签名
- 解决通信方身份可能被伪装的问题——数字证书
# 3.3 数字签名
(1)数字签名有两种功能:
能确定消息确实是由发送方签名并发出来的,因为别人假冒不了发送方的签 名。
数字签名能确定消息的完整性,证明数据是否未被篡改过。
(2)数字签名如何生成
将要发送的数据先用 Hash 算法(摘要算法、散列算法)生成消息摘要,然后用发送者的私钥加密生成数字签名,与原文一起传送给接收者。
接下来就是接收者校验数字签名的流程了。
接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用 HASH 函数对收到的原文产生一个摘要信息,与上一步得到的摘要信息对比。如果相同,则说明收到的信息是完整的,在传输过程中没有被修改,否则说明信息被修改过,因此数字签名能够验证信息的完整性。
假设消息传递在客户端、服务器之间发生。 服务器将消息连同数字签名一起发送给客户端
客户端接收到消息后,通过校验数字签名,就可以验证接收到的消息就是服务器发送的。
问题:
这个过程的前提是客户端知道服务器的公钥。问题的关键的是,和消息本身 一样,公钥不能在不安全的网络中直接发送给客户端,或者说拿到的公钥如何证明是服务器的。此时就需要引入了证书颁发机构(Certificate Authority,简 称 CA),CA 数量并不多,客户端内置了所有受信任 CA 的证书。
消息摘要算法分为三类:
- MD(Message Digest):消息摘要算法
- SHA(Secure Hash Algorithm):安全散列算法
- MAC(Message Authentication Code):消息认证码
# 3.4 证书
数字证书:是一个经证书认证结构数字签名的包含公开密钥、拥有者信息的文件,有点像生活中的身份证、护照等,是由一个官方的证书颁发机构签发的一组数据。这种证书很难伪造,用于使用者的身份证明。
实际上,我们使用的证书分很多种类型,SSL 证书只是其中的一种,SSL 证书负责传输公钥。我们常见的证书根据用途不同大致有以下几种:
1、SSL 证书,用于加密 HTTP 协议,也就是 HTTPS,TLS。如果一个 web 应用想要升级为 https,需要购买证书。
2、代码签名证书,用于签名二进制文件,比如 Windows 内核驱动,Firefox 插件,Java 代码签名等等
3、客户端证书,用于加密邮件
4、双因素证书,网银专业版使用的 USB Key 里面用的就是这种类型的证书
证书中包含:组织信息、域名信息、公钥(比如网站的公钥)、证书有效期等信息。
# CA - 数字证书认证机构:
CA 是证书的签发机构,它是公钥基础设施(Public Key Infrastructure, PKI)的核心。CA 是负责签发证书、认证证书、管理已颁发证书的机关。
认证过程(升级 HTTPS):
- 服务器的运营人员(网站的运营)向第三方机构 CA(或者其代理机构)提交公钥、组织信息、域名等信息并申请认证;
- CA 通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等;
- 如信息审核通过,CA 会向申请者签发认证文件-证书。
证书包含以下信息: 申请者公钥(如网站的公钥)、申请者的组织信息和个人信息、签发机构的信息、有效时间、证书序列号等信息的明文,同时包含一个 CA 机构的数字签名。
其中签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用 CA 的私钥对信息摘要进行加密,密文即签名
用户向 web 服务器发起一个安全连接的请求服务器返回经过 CA 认证的数字证书,证书里面包含了服务器的 public key。
用户拿到数字证书,怎么确保 CA 证书不被劫持,黑客完全可以把一个假的 CA 证书发给 Client,进而欺骗 Client,用户如何辨识证书真伪?
CA 的大杀器就是,CA 把自己的 CA 证书集成在了浏览器和操作系统里面。 Client 拿到浏览器或者操作系统的时候,已经有了 CA 证书,没有必要通过网络获 取,那自然也不存在劫持的问题。 查看浏览器 CA 证书:设置-->安全检查-->安全-->管理证书 查看操作系统 CA 证书:certmgr.msc
Client 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后利用对应 CA 的公钥解密签名数据,对比证书的信息摘要,如果一致, 则可以确认证书的合法性,即服务器的公开密钥是值得信赖的。
客户端还会验证证书相关的域名信息、有效时间等信息; 客户端会内置信任 CA 的证书信息(包含公钥),如果 CA 不被信任,则找不到对应 CA 的证书,证书也会被判定非法。
SSL 证书分类:
- DV(域名型 SSL):个人站点
- OV(企业型 SSL):企业官网
- EV(增强型 SSL):对安全需求更强的企业官网、电商、互联网金融网站
# 3.5 完整的 HTTPS 的通信
TLS 握手过程:
明文----->非对称加密----->对称加密
第一步,浏览器给出 TLS 协议版本号、一个客户端生成的随机数 1(Client random),以及客户端支持的加密方法。(明文通讯)
- 第二步,服务器确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数 2(Server random)。(明文通讯)
第三步,浏览器确认数字证书有效,然后生成一个新的随机数 3(Pre-master secret),并使用数字证书中的公钥加密这个随机数,发给服务器。(使用非对称加密算法)
浏览器确认数字证书有效:浏览器和操作系统内部内置了很多 CA 机构的证 书,是否篡改、是否在有效期内、域名和访问的网站是否匹配。
第四步,服务端使用自己的私钥,获取客户端发来的随机数(即 Premaster secret)。
双方就都有三个一模一样的随机数,前两个是明文发送的,最后客户端生成 的这个是使用证书中的公钥密文发送的。
第五步,客户端和服务器根据约定的加密方法,使用前面的三个随机数经过特定的算法,生成"对话密钥"(session key),用来加密接下来的整个对话过程。
三个随机数----->第三个是使用非对称加密---->相同的算法------->会话密钥
第六步:客户端和服务器都会第一次使用会话密钥加密一个消息发送给对方。
备注:客户端收到服务端发送的 Certificate 报文后首先会校验证书的合法性:
- 证书路径信任链逐级校验通过(证书确由可信 CA 认证签发);
- 签名解密成功(确系证书持有者亲笔);
- 从签名解析出的摘要和证书公开内容的摘要一致(证书内容完整,未被篡改);
- 主题子域与 URL 中的 HOST 一致,综上确保访问的网站是来自预期目标服务器且非劫持或钓鱼。
session 的恢复:
握手阶段用来建立 SSL 连接。如果出于某种原因,对话中断,就需要重新握手。 这时有两种方法可以恢复原来的 session:一种叫做 session ID,另一种叫做 session ticket。
session ID 的思想很简单,就是每一次对话都有一个编号(session ID)。如果对话中断,下次重连的时候,只要客户端给出这个编号,且服务器有这个编号的记录,双方就可以重新使用已有的"对话密钥",而不必重新生成一把。
上图中,客户端给出 session ID,服务器确认该编号存在,双方就不再进行握手阶段剩余的步骤,而直接用已有的对话密钥进行加密通信。
session ID 是目前所有浏览器都支持的方法,但是它的缺点在于 session ID 往往只保留在一台服务器上。所以,如果客户端的请求发到另一台服务器,就无法恢复对话。session ticket 就是为了解决这个问题而诞生的,目前只有 Firefox 和 Chrome 浏览器支持。
上图中,客户端不再发送 session ID,而是发送一个服务器在上一次对话中发送过来的 session ticket。这个 session ticket 是加密的,只有服务器才能解密,其中包括本次对话的主要信息,比如对话密钥和加密方法。当服务器收到 session ticket 以后,解密后就不必重新生成对话密钥了。
# 4 CA 证书制作实战
需求: 自建 CA 颁发证书
使用自签名证书来构建安全网络,所谓自签名证书,就是自己扮演 CA 机构,自己给自己的服务器颁发证书。
# 4.1 OpenSSL
OpenSSL 是一个以 C 语言编写现了 SSL 与 TLS 协议的开源的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连线者的身份。这个包广泛被应用在互联网的网页服务器上。OpenSSL 支持 Linux、 Windows、BSD(Unix 的衍生系统)、Mac 等平台,这使得 OpenSSL 具有广泛的适用性。
OpenSSL 整个软件包大概可以分成三个主要的功能部分:
加密算法库
对称加密算法:
非对称加密算法
信息摘要算法
SSL 协议库
OpenSSL 实现了 SSL 协议的 SSLv2 和 SSLv3,支持了其中绝大部分算法协议
OpenSSL 也实现了 TLSv1.0+
应用程序
- 多功能的命令行工具,可以实现加密解密、密钥生成、密钥和证书管理、自建 CA 和签名等功能
# 4.2 过程
- CA 生成根密钥
- CA 生成根证书
- Nginx 生成私钥
- Nginx 申请证书
- CA 签发
- Nginx 安装证书,配置
# 4.3 颁发
默认情况下 Linux 操作系统已经内置安装了 OpenSSL,可以通过 openssl version 查看版本号
但是在使用前,需要注意下当前 OpenSSL 的库的版本,因为版本 1.0.1 是一个很 重要的风水岭版本,1.0.1 是第一个支持 TLS1.1 和 1.2 的版本。
(1)修改配置:
在 CA 目录下创建两个初始文件,维护序列号。通过 CA 机构签发的每个证书都有一个唯一的序列号。
cd /etc/pki/CA
touch index.txt serial
echo 01 > serial
2
3
(2)生成根密钥
表示的 CA 机构的私钥,CA 结构签发的每一个证书都要通过自己的私钥进行签名。
cd /etc/pki/CA
#生成一个2048位的密钥
openssl genrsa -out private/cakey.pem 2048
2
3
(3) 生成根证书
使用 req 命令生成自签证书
-new:表示新的申请
-x509:表示生成自签证书
-key:指定私钥文件
-out:保存证书的位置
-days:指定证书期限
openssl req -new -x509 -key private/cakey.pem -out cacert.pem
会提示输入一些内容,因为是私有的,所以可以随便输入(之前修改的 openssl.cnf 会在这里呈现),最好记住能与后面保持一致。上面的自签证书 cacert.pem 应该生成在 /etc/pki/CA 下。
(4)为我们的 Nginx 服务器生成 SSL 密钥
环境:
- 192.168.200.16 CA 机构服务器
- 192.168.200.16 Nginx 服务器
申请 SSL 证书本质上就是服务器升级支持 HTTPS,非对称加密(公钥和私钥)。
以上都是在 CA 服务器上做的操作,而且只需进行一次,现在转到 nginx 服务器上执行
安装 Nginx
#1.安装该rpm
rpm -ivh
http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
#安装该rpm后,我们就能在/etc/yum.repos.d/ 目录中看到一个名为
nginx.repo 的文件。
#2.安装完Nginx源后,就可以正式安装Nginx了。
yum install -y nginx
#3.查看所在目录
whereis nginx
2
3
4
5
6
7
8
9
cd /etc/nginx/ssl
#为我们的nginx web服务器生成ssl密钥
openssl genrsa -out nginx.key 2048
2
3
(5)为 nginx 生成证书签署请求
该过程会生成一个文件,包含了证书相关的信息,但是该文件不是证书,生成证书的请求文件。
该文件需要发送给 CA 机构,由 CA 签名后生成一个证书文件。
openssl req -new -key nginx.key -out nginx.csr
...
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:GD
Locality Name (eg, city) []:SZ
Organization Name (eg, company) [Internet Widgits Pty
Ltd]:COMPANY
Organizational Unit Name (eg, section) []:IT_SECTION
Common Name (e.g. server FQDN or YOUR name)
[]:your.domain.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
同样会提示输入一些内容,其它随便,除了 Commone Name 一定要是你要授予证书的服务器域名或主机名,challenge password 不填。
(6)私有 CA 根据请求来签署证书
接下来要把上一步生成的证书请求 csr 文件,发到 CA 服务器上,在 CA 上执行:
openssl ca -in nginx.csr -out nginx.crt
上面签发过程其实默认使用了 -cert cacert.pem -keyfile cakey.pem
,这两个文件就是前两步生成的位于 /etc/pki/CA
下的根密钥和根证书。将生成的 crt 证书发回 nginx 服务器使用。
到此我们已经拥有了建立 SSL 安全连接所需要的所有文件,并且服务器的 crt 和 key 都位于配置的目录下,剩下的是如何使用证书的问题。
# 4.4 使用 SSL 证书
(1)Nginx 使用 SSL 证书
在本地安装完成证书(在 Nginx 服务器配置)也就意味着 Java Web 应用已经完成了从 http 到 https 协议的升级
以 Nginx 为例,在 Nginx 中新建 ssl 文件夹,将生成的 crt 和 key 放入其中,配置文件中加入以下代码:
#修改Nginx的配置文件,安装SSL证书
cd /etc/nginx/conf.d
vi default.conf
listen 443 ssl http2;#https协议监听的端口号是443端口,基于http2进行工作的。
ssl_certificate /etc/nginx/ssl/nginx.crt; # 指向 ssl文件夹中的 crt 文件
ssl_certificate_key /etc/nginx/ssl/nginx.key; # 指向ssl 文件夹中的 key 文件
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #启用false start加速
ssl_ciphers
AESGCM:ALL:!DH:!EXPORT:!RC4:+HIGH:!MEDIUM:!LOW:!aNULL:!eNULL;
ssl_prefer_server_ciphers on;
2
3
4
5
6
7
8
9
10
11
(2)启动 Nginx
#切换到可执行目录
cd /usr/sbin/
./nginx
#查看启动状态
ps -ef|grep nginx
2
3
4
5
(3)访问测试
curl https://192.168.200.21
但是,我们自己签发的证书,是不受其他服务器信任的,当发起 curl 请求时, 会出现以下情况:证书无效或无法验证错误。
这时候,我们就需要将我们 CA 服务器的根证书导入到这台服务器中。
(4)添加证书:
#安装 ca-certificates package:
yum install ca-certificates
#启用dynamic CA configuration feature:
update-ca-trust force-enable
#将证书文件放到 /etc/pki/ca-trust/source/anchors/ 目录下
mv /etc/pki/CA/cacert.pem /etc/pki/ca-trust/source/anchors/
#执行更新:
update-ca-trust extract
2
3
4
5
6
7
8
(5)修改本地 host 文件
cd /etc
vi hosts
2
127.0.0.1 localhost localhost.localdomain localhost4
localhost4.localdomain4
::1 localhost localhost.localdomain localhost6
localhost6.localdomain6
192.168.200.21 yj.com
2
3
4
5
(6)访问测试
curl https://yj.com
# 5 HTTPS 升级
# 5.1 Let's Encrypt
# 5.1.1. Let's Encrypt 简介
Let's Encrypt —— 是一个由非营利性组织 互联网安全研究小组(ISRG) 提供的免费、自动化和开放的证书颁发机构(CA),简单的说,就是为网站提供免费的 SSL/TLS 证书。互联网安全研究小组(ISRG):ISRG 是美国加利福尼亚州的一家公益公司,成立于 2013 年 5 月,第一个项目是 Let's Encrypt 证书颁发机构。 Let’s Encrypt 使用 ACME 协议来验证您对给定域名的控制权并向您颁发证书。 要获得 Let’s Encrypt 证书,您需要选择一个要使用的 ACME 客户端软件。
Let’s Encrypt 不控制或审查第三方客户端,也不能保证其安全性或可靠性。官 方推荐使用 Certbot 客户端来签发证书,官网:https://certbot.eff.org/
ACME 协议:
Automatic Certificate Management Environment=ACME,自动认证管理 环境协议
ACME 协议的基本思路是:
在你服务器上生成一次性的随机特征数据(nonce)
然后通过 Let’s Encrypt 的服务器核对这个数据
核对成功发放证书
使用前提:
- 域名,它会生成指定域名的证书
- 在域名指向的服务器上能访问 https
- Linux 环境
# 5.1.2 环境准备
Certbot 的两种工作方式:
Standalone 方式:
certbot 会自己运行一个 web server 来进行验证。如果我们自己的服务器上已经有 web server 正在运行 (比如 Nginx 或 Apache ),用 standalone 方式的话需要先关掉它,以免冲突。
Web root 方式:
certbot 会利用既有的 web server,在其 web root 目录下创建隐藏文件, Let’s Encrypt 服务端会通过域名来访问这些隐藏文件,以确认你的确拥有对应域名的控制权。
(1)安装 Nginx,Nginx 位于第三方的 yum 源里面,而不在 Centos 官方 yum 源 里面
#安装RHEL
sudo yum install epel-release
#yum更新
yum update
yum install -y nginx
2
3
4
5
(2)安装 wget
yum -y install wget
(3)下载 Certbot 客户端
#下载
wget https://dl.eff.org/certbot-auto
#添加执行权限
chmod a+x ./certbot-auto
2
3
4
(4)编辑 nginx 的配置文件
server {
listen 80 default_server;
listen [::]:80 default_server;
#1.配置合法域名
server_name yuanjing.com;
#2.配置应用根目录
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 5.1.3 生成并配置证书
(1)使用 certbot-auto 命令,生成证书
#域名必须真实有效
./certbot-auto certonly --webroot --email yuanjing@lagou.com
-w /usr/share/nginx/html/ -d [填写合法域名的地址]
2
3
(2)生成的证书放在/etc/letsencrypt/live/[网站域名]下
例如:/etc/letsencrypt/live/yuanjing.com
文件名 | 内容 |
---|---|
cert.pem | 服务端证书 |
chain.pem | 浏览器需要的所有证书但不包括服务端证书,比如根证书 和中间证书 |
fullchain.pem | 包括了 cert.pem 和 chain.pem 的内容 |
privkey.pem | 证书的私钥 |
一般情况下 fullchain.pem 和 privkey.pem 就够用了
[centos@yuanjing ~]$ tree /etc/letsencrypt/
......
├── live
│ └── yuanjing.com (别名,最终,看自己域名)
│ ├── cert.pem -> ../../archive/yuanjing.com/cert1.pem
│ ├── chain.pem -> ../../archive/yuanjing.com/chain1.pem
│ ├── fullchain.pem ->
../../archive/yuanjing.com/fullchain1.pem
│ ├── privkey.pem ->
../../archive/yuanjing.com/privkey1.pem
│ └── README
......
2
3
4
5
6
7
8
9
10
11
12
(3)配置 nginx 支持 https 访问
server {
listen 443 ssl http2;
server_name yuanjing.com;
ssl_certificate "/etc/letsencrypt/live/yuanjing.com/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/yuanjing.com/privkey.pem";
include /etc/nginx/default.d/*.conf;
location / {
root /usr/share/nginx/html;
index index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(4)http 跳转到 https
在网站在访问 http 时都会将 http 请求重定向到 https,只需在 nginx 中配置下。配置如下
server {
listen 80 default_server;
server_name yuanjing.com www.yuanjing.com;
return 301 https://$server_name$request_uri;
}
2
3
4
5
(5)重启 Nginx 后生效
nginx -s reload
# 5.1.4 更新证书
默认证书有效期是 3 个月,所以需要续期。 设置每月 1 日的凌晨 3 点就会执行一次所有域名的续期操作
#创建定时任务
sudo crontab -e
#设置定时策略
#/home/ubuntu/soft/certbot-auto:certbot所在的目录
0 3 1 * * /home/ubuntu/soft/certbot-auto renew --renew-hook
"sudo nginx -s reload"
#查看一下是否存在刚才添加的定时命令
sudo crontab -l
2
3
4
5
6
7
8
5.2 阿里云 SSL 证书
# 6. HTTPS 性能优化
根据 外媒 Netmarketshare 发布的数据显示,截止到 2019 年 10 月全球使用 HTTPS 加密的 Web 流量的比例已经超过了九成。HTTPS 网站加密传输协议几乎 已经接近普及。
并且这个数据可以通过其它来源进行验证,根据 Google 透明度报告: “Chrome 中的 HTTPS 加密情况”来看,在谷歌这几年连推带吓的强制推广网站必须接入 HTTPS 协议的宣传下,到 2019 年 10 月 Chrome 加载网页中启用加密的比例已经达到了 95%,几乎等于谷歌搜索内的网站已经全部普及。
在全球范围,美国的 HTTPS 比例为 92%,俄罗斯 85%,日本 80%,印尼 74%,国内大约 60%。
当下网站接入 HTTPS 加密传输协议,在全球已经基本成为一种普及的趋势,虽然国内很多站长对更换 HTTPS 还是有些排斥,但是对于搜索引擎推出的规则也只能遵守,对于站长们而言,网站接入 HTTPS 无非是早晚的事!
# 6.1 HTTPS 对访问速度的影响
HTTPS 对速度有什么影响。影响主要来自两方面:
- 协议交互所增加的网络 RTT(round trip time)。
- 加解密相关的计算耗时。
# 6.1.1 网络耗时增加
HTTP 访问过程:
用户只需要完成 TCP 三次握手建立 TCP 连接就能够直接发送 HTTP 请求获取应用层数据,此外在整个访问过程中也没有需要消耗计算资源的地方。
HTTPS 访问过程:
而且很多用户习惯于使用 HTTP 请求你的网站,要保护用户的安全,首先要让用 户强制 302/301 到 HTTPS,这次跳转至少增加 1 个 RTT 的延时;301 跳转后要再次 TCP 建连,又要增加 1 个 RTT 的延时。
# 6.1.2 计算耗时增加
大象为什么跳不高跑不快?因为它很重。HTTPS 为什么访问比较慢为什么消耗 CPU 资源呢?同样也是因为它很重。HTTPS 的重,体现在如下几方面:
1、大量的计算。 SSL 的每一个字节都涉及到较为复杂的计算。即使是 client Hello,也需要在握手完成时做校验。
2、TLS 协议的封装和解析。 HTTPS 所有数据都是按照 TLS record 格式进行封装和解析的。
3、协议的网络交互。 从 TLS 的握手过程可以看出,即使不需要进行任何计算, TLS 的握手也需要至少 2 个 RTT(round trip time)以上的网络交互。
总体来说,HTTPS 主要有如下计算环节:
1、非对称密钥交换。 这类算法的主要作用就是根据客户端和服务端不对称的信 息,经过高强度的密钥生成算法,生成对称密钥,用于加解密后续应用消息。
2、对称加解密。 服务端使用密钥 A 对响应内容进行加密,客户端使用相同的密 钥 A 对加密内容进行解密,反之亦然。
3、消息一致性验证。 每一段加密的内容都会附加一个 MAC 消息,即消息认证 码。简单地说就是对内容进行的安全哈希计算,接收方需要校验 MAC 码。
4、证书签名校验。 这个阶段主要发生在客户端校验服务端证书身份时,需要对 证书签名进行校验,确保证书的真实性。
# 6.2 优化方案
# 6.2.1 TLS 握手过程分析
通过 Wireshark 抓包可以清楚地看到完整 TLS 握手过程所需的两个 RTT,如下 图
client_key_exchange:合法性验证通过之后,客户端计算产生随机数字 Premaster,并用证书公钥加密,发送给服务器
# 6.2.2 False start
False Start 有抢跑的意思,意味着不按规则行事。TLS False Start 是指客户端 在发送 Change Cipher Spec Finished 同时发送应用数据(如 HTTP 请求), 服务端在 TLS 握手完成时直接返回应用数据(如 HTTP 响应)。这样,应用数据的发送实际上并未等到握手全部完成,故谓之抢跑。这个过程如下图所示:
浏览器在发送 ChangeCipherSpec,并没有等待服务器端的确认就立即发送了加密应用数据,省去了一个 RT。 False Start 相当于客户端提前发送加密后的应用数据,不需要修改 TLS 协议, 目前大部分浏览器默认都会启用。
Nginx 服务器开启 False start 支持:
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
ssl_ciphers ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
#
# #......
# }
2
3
4
5
6
7
8
9
10
11
12
13
14
15
简而言之就是告诉 Nginx 在 TLS 握手时启用服务器算法优先,由服务器选择适配算法而不是客户端。
# 6.2.3 升级到 HTTP2
TTP/2 相比廉颇老矣的 HTTP/1.x,HTTP/2 在底层传输做了很大的改动和优化 包括有: 二进制分帧 首部压缩(Header Compression) 多路复用 对请求划分优先级 服务器推送流(即 Server Push 技术)
server {
#升级到https后的web应用是基于http2协议进行传输
listen 443 ssl http2;
}
2
3
4
# 6.2.4 会话恢复(Session Resumption)机制
SSL/TLS 中的 session 跟 HTTP 的 session 类似,都是用来保存客户端和服务端之 间交互的一些记录,这里的 SSL 的 session 保存的是 SSL 的握手记录。
TLS 有几个特征可以用来消除额外的来回,比如重用一个会话 session,两个标准会话重用机制是 session ID (RFC 5246) 和 session tickets (RFC 5077),使用其中一个技术,一个客户端可以重用之前创建的会话,这个会话是之前和服务器进行握手成功的,这样可以减少一次来回过程。
(1)Session ID 重用 / Session Cache:
一次 TLS 握手的结果是建立一条对称加密的数据通道,这条数据通道相关的参数都可以在内存中保存的,所以服务端就可以针对这一套参数值生成一个 ID, 叫做 Session ID,使用该 ID 就可以直接复原对称加密的通信通道。所以当客户端下一次请求(Client Hello)到达的时候,客户端如果携带了 Session ID,服务端就可以根据这个 Session ID 找到对应的 Secure context,从而复原信道了。
OpenSSL 的 Session Cache 是不能够跨进程共享的,而 Nginx 是一个多进程的业务模型,如果每一个进程一份独立的 Session Cache,就会导致同样一个 SSL 连接,上一次被一个 Worker 进程服务,下一次是被另外一个 Worker 进程服务的。使得整个 OpenSSL 在内存上造成极大的浪费,并且使得 Cache 的准确性大幅度下滑。
所以 Nginx 就另外又实现了一套自己的 Session Cache 系统,这套系统是跨进程的,使用的是共享内存,用红黑树的方式组织的 Session Cache,并且对 Session ID 的定义也重新进行了封装,最终形成了一个跨进程了 Session Cache。 Session ID 共享复用 Nginx 可以通过 ssl_session_cache 设置:
server {
# 每一个共享的缓存应该有一个唯一的名称。拥有相同名称的缓存可以被多个虚拟服务(virtual server)所使用。
ssl_session_cache shared:SSL:10m;
}
2
3
4
目前使用较多的配置是 built-in 和 shared 同时使用:
ssl_session_cache builtin:1000 shared:SSL:10m;
但是 Nginx 官方说只使用 shared,性能会更高,配置方法为:
ssl_session_cache shared:SSL:10m;
Session Identifier 机制的弊端:
- 负载均衡中,多机之间往往没有同步 session 信息,如果客户端两次请求没有落在同一台机器上就无法找到匹配的信息;
- 服务端存储 Session ID 对应的信息不好控制失效时间,太短起不到作用, 太长又占用服务端大量资源。
ssl_session_timeout 5m;
(2)Session Ticket:
Session Ticket 可以解决这些问题,Session Ticket 是用只有服务端知道的安全密钥加密过的会话信息,最终保存在浏览器端。浏览器如果在 ClientHello 时带 上了 Session Ticket,只要服务器能成功解密就可以完成快速握手。
由于 Session Ticket 的客户端存储的特性,使得服务器完全就不需要管 Session Cache 方案需要面对的资源管理问题,唯一的代价就是一个解密计算的开销。同时,天然的支持了分布式,但是前提是分布式的所有节点都需要使用同样的服务器私有密钥(Session Ticket Encryption Key (STEK)),这无疑严重增加了危险系数。所以很多公司在实现的时候都会隔一段时间统一更换 STEK。
# 开启Session Ticket,此处没有指定加密算法,openssl默认会生成随机数的key。
# 如果需要手动指定,配置:ssl_session_ticket_key encode_decode.key;
# key文件可以由openssl命令生成,例如:openssl rand 80> ticket.key
# 如果存在Nginx集群,多个集群应用使用同一份key文件,为保证安全性须每隔一定频率更换key。
ssl_session_tickets on;
2
3
4
5
在 TLS1.3 中,Session Cache 和 Session Ticket 都被完全的取消,取而代之的是 PSK(Pre Shared Key)。这个 PSK 并不是说每个客户端都要和服务端提前共享 一个密钥,而是与握手相同的首先使用非对称加密方法直接提前协商一个密钥出来(psk_dhe_ke ),或者直接从之前协商出来的密钥参数中得出一个密钥 (psk_ke)。
# 6.2.5 HSTS
一个网站接受一个 HTTP 的请求,然后跳转到 HTTPS,用户可能在开始跳转前, 通过没有加密的方式和服务器对话,比如,用户输入http://baidu.com或者直接 baidu.com,会存在两个弊端:
- 存在中间人攻击潜在威胁,跳转过程可能被恶意网站利用来直接接触用户信息,而不是原来的加密信息。
- 降低访问速度,301/302 跳转不仅需要一个 RTT,浏览器执行跳转也需要执行时间。 解决方案: HSTS(HTTP Strict Transport Security,严格传输安全协议)国际互联网工 程组织 IETF 正在推行一种新的 Web 安全协议。 采用 HSTS 协议的网站将保证浏览器始终连接到该网站的 HTTPS 加密版本,不需要用户手动在 URL 地址栏中输入加密地址。 HSTS 的作用是强制客户端(如浏览器)使用 HTTPS 与服务器创建连接,而不是 HTTP。
实现原理:
第一次通过 HTTPS 请求,服务器响应 Strict-Transport-Security 头,以后尝试访问这个网站的请求都会自动把 HTTP 替换为 HTTPS。 当 HSTS 头设置的过期时间到了,后面通过 HTTP 的访问恢复到正常模式,不会再自动跳转到 HTTPS。 每次浏览器接收到 Strict-Transport-Security 头,它都会更新这个网站的过期时间,所以网站可以刷新这些信息,防止过期发生。 Chrome、Firefox 等浏览器里,当您尝试访问该域名下的内容时,会产生一 个 307 Internal Redirect(内部跳转),自动跳转到 HTTPS 请求。
开启方法:
server {
listen 443 ssl http2;
server_name baidu.com;
#1. max-age:单位:秒。 HSTS header 过期时间,一般设置为1年,即31536000秒。
# 而每次Response Header都带上HSTS Header,则可不断刷新其过期时间。
#2. includeSubDomains:需要开启HSTS的域名/子域名。
# 在接下来的一年(即31536000秒)中,浏览器只要向xxx或其子域名发送HTTP请求时,必须采用HTTPS来发起连接。比如,用户点击超链接或在地址栏输入 http://xxx/ ,浏览器应当自动将 http 转写成 https,然后直接向 https://xxx/ 发送请求。
add_header Strict-Transport-Security "max-age=31536000;includeSubDomains" always;
location / {
}
}
2
3
4
5
6
7
8
9
10
11
# 6.2.6 硬件优化
因为 HTTPS 是属于计算密集型,应该选择计算力更强的 CPU,而且最好选择支持 AES-NI 特性的 CPU,这个特性可以在硬件级别优化 AES 对称加密算法,加快应用数据的加解密。
# 6.2.76 软件优化
果可以,把软件升级成较新的版本,比如将 Linux 内核 2.X 升级成 4.X,将 openssl 1.0.1 升级到 1.1.1,因为新版本的软件不仅会提供新的特性,而且还会修复老版本的问题。
# 6.2.8 协议优化
- 密钥交换算法应该选择 ECDHE 算法,而不用 RSA 算法,因为 ECDHE 算法具备前向安全性,而且客户端可以在第三次握手之后,就发送加密应用数据,节省了 1 RTT。
- 将 TSL1.2 升级 TSL1.3,因为 TSL1.3 的握手过程只需要 1 RTT,而且安全性更强。
# 6.2.9 证书优化
- 务器应该选用 ECDSA 证书,而非 RSA 证书,因为在相同安全级别下,ECC 的密钥长度比 RSA 短很多,这样可以提高证书传输的效率;
- 服务器应该开启 OCSP Stapling 功能,由服务器预先获得 OCSP 的响应,并把响应结果缓存起来,这样 TLS 握手的时候就不用再访问 CA 服务器,减少了网络通信的开销,提高了证书验证的效率;
# 避免中间人攻击:
在公共场所,例如免费 WIFI 的环境中,第一次访问网站会弹出 HSTS 错误:
当你通过一个无线路由器的免费 WiFi 访问你的网银时,很不幸的,这个免费 WiFi 也许就是由黑客的笔记本所提供的,他们会劫持你的原始请求,并将其重定向到克隆的网银站点,然后,你的所有的隐私数据都曝光在黑客眼下。 严格传输安全可以解决这个问题。如果你之前使用 HTTPS 访问过你的网银,而且网银的站点支持 HSTS,那么你的浏览器就知道应该只使用 HTTPS,无论你是否输入了 HTTPS,这样就防范了中间人劫持攻击。
# 参考
- 01
- idea 热部署插件 JRebel 安装及破解,不生效问题解决04-10
- 02
- spark中代码的执行位置(Driver or Executer)12-12
- 03
- 大数据技术之 SparkStreaming12-12