HTTPS服务是工作在SSL/TLS上的HTTP。
首先简单区分一下HTTPS,SSL ,TLS ,OpenSSL这四者的关系:
结论:SSL/TLS 是协议,OpenSSL是协议的代码实现。
可以看到浏览器上面展示的url前面会加一把绿色的锁,表示这个是安全的HTTPS url。要达到这个目标需要什么:
Node.js底层引入了OpenSSL开源库,OpenSSL是HTTPS模块的安全保障。下面来创建一个HTTPS服务器。
const https = require('https');
const fs = require('fs');
let options = {
key: fs.readFileSync('./server.key'),//私钥
cert: fs.readFileSync('./server.crt')//数字证书
};
https.createServer(options , (req , res)=>{
console.log('server got it');
res.writeHead(200);
res.end('hello https is work');
}).listen(8888);
console.log('server start');
可以发现https服务器比http服务器要多一个options
参数。options
里面包含的是https服务器的密钥和数字证书。
问题来了:
SSL/TLS是一个公钥和私钥的结构,非对称结构,每个客户端和服务器端都有自己的公钥和私钥。公钥用来加密数据,私钥用来对数据解密。
总结:解决数据加密和解密的问题。
好,现在通过命令行执行OpenSSL生成服务器私钥:
openssl genrsa -out server.key 1024
没有安装openssl命令行的需要自行安装。
数据都加密了,为什么还要数字证书啊?
公私钥的非对称加密虽然好,但是网络还是可能存在窃听的情况。典型的例子:中间人攻击。
原理和HTTP代理服务器一样。
为了确保数据安全引入了CA。CA会给上面创建的HTTPS服务器颁发数字证书。
现在有权威的CA机构的证书费用都很昂贵,有钱的可以去买,没钱的只能自签名CA证书了。
所谓的自签名证书,就是自己扮演CA机构,给自己的服务器颁发签名证书。
自己扮演CA角色,必须要准备好CA机构相关的文件。包括:私钥,CSR文件,CA证书。
1.命令行生成CA私钥:
openssl genrsa -out ca.key 1024
2.命令行生成CSR文件:
openssl req -new -key ca.key -out ca.csr
CSR是Cerificate Signing Request的英文缩写(即证书请求文件),是证书申请者向证书颁发机构(CA)申请证书时需要提供的文件。里面包含了一些申请者的基本信息,比如Common Name、 Organization等。同时也包含了申请者的公钥。
注意:存在子域名时,需要把Common Name 改为:
*.test.com
类似,表示匹配。
3.命令行生成CA自签名证书:
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
CA机构的文件准备完毕,可以准备为HTTPS服务器颁发证书咯。
HTTPS服务器的私钥(上文的:server.key
)已经生成。通过服务器私钥生成CSR文件提交给CA机构,CA机构通过自己的证书,私钥和服务器的CSR文件来给服务器颁发带CA认证的证书。
1.首先HTTPS服务器得准备CSR文件:
openssl req -new -key server.key -out server.csr
2.CA机构颁发服务器证书:
openssl x509 -req -sha256 -extfile v3.ext -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
上面指定了证书的版本号为X.509的(v3)第3个扩展版本。 上面还指定了CA机构的证书和私钥。还包括服务器的证书申请文件,以及指定的保存服务器证书的文件。
注意:存在子域名时,需要把Common Name 改为:
*.test.com
类似,表示匹配。
默认的v3.ext 文件:
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage=digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName=@alt_names
[alt_names]
DNS.1=www.test.com
注意:
DNS.1=www.test.com
这里指定了给哪个domain,与自己服务器域名要保持一致。存在子域名改为*.test.com
。
一句话概括:CA机构给服务器颁发哪个版本的证书。
准备工作都做好了,现在就来访问一下呗。
1.启动server:
node server.js
2.配置nginx
server{
listen 443;
server_name www.test.com;
client_max_body_size 128M;
index index.html index.htm;
error_log D:/Wnmp/logs/error_test.com.log;
access_log D:/Wnmp/logs/access_test.com.log combined;
ssl on;
ssl_certificate E:/node/https/server.crt;
ssl_certificate_key E:/node/https/server.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !MEDIUM";
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
location / {
proxy_pass https://127.0.0.1:8888/;
proxy_redirect default ;
}
}
3.配置host:
127.0.0.1 www.test.com
现在让我们打开chrome浏览器:https://www.test.com
靠。。。。。被忽悠了吗?什么情况??????
回想一下,漏掉了什么吗?
没错我们客户端的CA证书还没有安装啊。自己签发的证书是需要自己手动安装的。
1.找到生成好的ca.crt
证书,双击点击安装:
2.选择安装为受信任的根证书颁发机构:
好了,关闭浏览器重新访问:
ok , 大功告成!!!!!
现在回顾一下这整个颁发证书的流程:
项目目录结构: