我们先来看看黑客是如何盗取客户端和服务端通讯的真实报文的。
对称密钥是客户端和服务端加解密时共用的一个密钥,因为是共用密钥,必然存在一个密钥传输的过程,黑客可以通过截取报文的方式拿到这个对称密钥,对后续的密文进行解密。
非对称密钥是客户端和服务端各保有一对自己的公私钥,并将公钥发送给对方。发送方用对方的公钥加密数据,用自己的私钥签名数据,接收方收到密文后,用对方的公钥验签,用自己的私钥解密数据。
由于在双方通讯过程中不存在私钥的传输,黑客就无法轻易地直接从报文中拿到私钥。但也并非无懈可击了,黑客可以在中间通过模拟客户端和服务端,分别对双方进行欺骗,获取到真实报文:
首先,在双方交换公钥时,黑客拦截报文记录双方的公钥,并将自己的公钥替换进去;
然后,发送方用黑客传回的公钥加密数据,用自己的私钥签名数据发送出去,黑客拦截报文,用发送方的公钥验签,用自己的私钥解密获得真实报文。
为了防止黑客模拟服务端进行欺骗,这时候就需要一个有公信力的第三方介入,对服务端的真伪进行甄别,这个第三方就是CA机构(Certificate Authority),具体工作过程是这样的:
首先,客户端内置了常用CA机构的证书,其中包含CA机构公钥;
然后,CA机构颁发给网站的证书(服务器证书),包含了服务器公钥、域名信息等,以及CA机构私钥对服务器公钥、域名等一系列信息的签名;
最后,客户端接收到服务器证书时,使用CA证书包含的公钥对服务器证书的签名进行校验,校验通过才会使用服务器公钥加密传输对称密钥给服务端,后续再使用这个对称密钥加解密报文。
简单来说就是客户端用预置的CA证书对服务端发送的服务器证书进行真伪判断。
自制SSL证书需要生成两种证书:CA机构证书、服务器证书。
服务器证书是由CA机构颁发,安装在服务器上,例如nginx、tomcat等;
CA机构证书提供给各个客户端安装,常用浏览器、手机等已经内置了各大常用CA机构的证书,但我们自制证书就需要手动安装了。
mkcert 是一个用于生成本地自签名 SSL 证书的开源工具,项目基于 Golang 开发,可跨平台使用,不需要配置,支持多域名以及自动信任 CA。
下载地址:https://github.com/FiloSottile/mkcert/releases
按照操作系统类型选择合适的版本,这里使用mkcert-v1.4.4-linux-amd64版本。
#重新命名
cp mkcert-v1.4.4-linux-amd64 mkcert
#增加执行权限
chmod +x mkcert
#执行测试命令,会返回mkcert当前版本号为1.4.4
./mkcert -version
mkcert 支持自动信任 CA,需要在服务器生成CA 证书,并在客户端安装,以解决私有证书在客户端不受信任的问题。
#在服务器生成CA证书
mkcert -install
#查看证书位置
mkcert -CAROOT
可以看到目录下有两个文件:rootCA-key.pem和rootCA.pem ,把rootCA.pem拷贝到客户端,重命名为rootCA.crt,双击安装即可。
#生成服务器证书方式一:直接生成
./mkcert 域名1 域名2 域名3...
在当前目录生成xxx.pem和xxx-key.pem两个文件。
#生成服务器证书方式二:指定证书名和私钥名
./mkcert -cert-file ./server.crt -key-file ./server.key 域名1 域名2 域名3...
在当前目录生成server.crt和server.key两个文件。
查看mkcert更多用法:
./mkcert -help
Usage of mkcert:
$ mkcert -install
Install the local CA in the system trust store.
$ mkcert example.org
Generate "example.org.pem" and "example.org-key.pem".
$ mkcert example.com myapp.dev localhost 127.0.0.1 ::1
Generate "example.com+4.pem" and "example.com+4-key.pem".
$ mkcert "*.example.it"
Generate "_wildcard.example.it.pem" and "_wildcard.example.it-key.pem".
$ mkcert -uninstall
Uninstall the local CA (but do not delete it).
Advanced options:
-cert-file FILE, -key-file FILE, -p12-file FILE
Customize the output paths.
-client
Generate a certificate for client authentication.
-ecdsa
Generate a certificate with an ECDSA key.
-pkcs12
Generate a ".p12" PKCS #12 file, also know as a ".pfx" file,
containing certificate and key for legacy applications.
-csr CSR
Generate a certificate based on the supplied CSR. Conflicts with
all other flags and arguments except -install and -cert-file.
-CAROOT
Print the CA certificate and key storage location.
$CAROOT (environment variable)
Set the CA certificate and key storage location. (This allows
maintaining multiple local CAs in parallel.)
$TRUST_STORES (environment variable)
A comma-separated list of trust stores to install the local
root CA into. Options are: "system", "java" and "nss" (includes
Firefox). Autodetected by default.
由于mkcert在生成证书时命令很简单,相应的可选配置也较少,例如无法约定证书的有效期等等,所以一般用于测试使用,在正式环境中最好还是使用openssl,下面是使用openssl制作ssl证书的步骤:
#生成CA私钥文件myCA.key,需要设置CA私钥密码
openssl genrsa -des3 -out myCA.key 2048
#生成CA证书myCA.crt,需要验证CA私钥密码
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 36500 -out myCA.crt -subj "/C=CN/ST=ca-province/L=ca-city/O=ca-org/OU=ca-group/CN=ca-domin"
#查看CA证书内容
openssl x509 -in myCA.crt -noout -text
生成的CA证书可直接拷贝至客户端双击安装,与上面安装CA证书动图中的步骤一样。
#生成服务器私钥文件server.key
openssl genrsa -out server.key 2048
#生成服务器证书申请文件server.csr
openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=server-province/L=server-city/O=server-org/OU=server-group/CN=192.168.20.20/CN=192.168.20.50/CN=localhost"
#创建服务器证书配置文件cert.ext
vi cert.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.2 = 192.168.20.20
IP.3 = 192.168.20.50
#用CA证书和CA私钥文件签署服务器证书server.crt
openssl x509 -req -in server.csr -out server.crt -days 36501 -CAcreateserial -CA myCA.crt -CAkey myCA.key -CAserial serial -extfile cert.ext
docker安装nginx过程参考:
Docker安装Nginx_日华子文的博客-CSDN博客_docker nginx安装
#拷贝证书至docker挂载配置文件的目录
cp soft/ssl/server.crt docker-nginx/conf/
cp soft/ssl/server.key docker-nginx/conf/
#修改配置文件default.nginx,在文件最下方添加server
vi docker-nginx/conf/default.conf
server {
#SSL 默认访问端口号为 443
listen 443 ssl;
#请填写绑定证书的域名
#server_name cloud.tencent.com;
#请填写证书文件的相对路径或绝对路径
ssl_certificate /etc/nginx/conf.d/server.crt;
#请填写私钥文件的相对路径或绝对路径
ssl_certificate_key /etc/nginx/conf.d/server.key;
ssl_session_timeout 5m;
#请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
#网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
#例如,您的网站主页在 Nginx 服务器的 /etc/www 目录下,则请修改 root 后面的 html 为 /etc/www。
root /usr/share/nginx/html;
index index.html index.htm;
}
}
注意此处证书的路径要填写容器内配置文件目录的绝对路径,或nginx.conf的相对路径。
#重启nginx容器
docker restart nginx
#如果启动失败,可以查看容器日志排查问题
docker logs -ft --tail 100 容器名
重启浏览器访问nginx
过程参考资料:
mkcert 使用指南:如何快速创建自签名 SSL 证书_Xpitz的博客-CSDN博客_mkcert
https://gist.github.com/liuguangw/4d4b87b750be8edb700ff94c783b1dd4
SSL 证书 Nginx 服务器 SSL 证书安装部署-证书安装-文档中心-腾讯云
上面的操作中,生成的都是crt/key证书,nginx可以直接使用,但如果想要在tomcat中使用的话,就需要转换证书格式为jks,下图是各大主流中间件对应的的证书格式类型。
#crt/key转换为pfx
openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt
#pfx转换为jks
keytool -importkeystore -srckeystore server.pfx -destkeystore server.jks -srcstoretype PKCS12 -deststoretype JKS
修改server.xml
重启tomcat
更多证书格式转换参考:
https SSL主流数字证书都有哪些格式? - lhj588 - 博客园