1、命令行创建https证书
自己创建的证书只适用于自己测试用。
步骤:
1.1 创建私钥
假设私钥名称为:server.key
[root@web01 ~]#openssl genrsa -idea -out server.key 2048
Generating RSA private key, 2048 bit long modulus
...............+++
....................+++
e is 65537 (0x10001)
Enter pass phrase for server.key: #输入密码
1.2 创建证书
根据私钥创建证书,证书名称:server.crt
[root@web01 ~]#openssl req -days 36500 -x509 -sha256 -nodes -newkey rsa:2048 -keyout server.key -out server.crt
Generating a 2048 bit RSA private key
.................+++
.............................+++
writing new private key to 'server.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN #根据实际填写
State or Province Name (full name) []:gd #根据实际填写
Locality Name (eg, city) [Default City]:gz #根据实际填写
Organization Name (eg, company) [Default Company Ltd]: #根据实际填写
Organizational Unit Name (eg, section) []:test #根据实际填写
Common Name (eg, your name or your server's hostname) []:test.com #根据实际填写
Email Address []:test@test.com #根据实际填写
[root@web01 ~]#
#生成的私钥、公钥如下:
[root@web01 ~]#ll server.*
-rw-r--r-- 1 root root 1407 Jul 7 23:36 server.crt
-rw-r--r-- 1 root root 1704 Jul 7 23:36 server.key
[root@web01 ~]#
2、集群与https
两种架构:
方案1、用户请求--http-https-->负载均衡--不加密http-->内网环境
方案2、用户请求--http-https-->负载均衡--加密https-->内网环境
示意图:

2.1 配置流程
2.1.1 全部加密
全部加密,即方案1
(1)web端配置
web01:192.168.10.7
站点配置文件:
[root@web01 ~]#vim /etc/nginx/conf.d/test.com.conf
server {
listen 443 ssl;
server_name ssl.test.com;
root /app/code/ssl;
ssl_certificate /etc/nginx/ssl_keys/server.crt;
ssl_certificate_key /etc/nginx/ssl_keys/server.key;
location / {
index index.html;
}
}
站点目录及测试页:
[root@web01 ~]#mkdir /app/code/ssl
[root@web01 ~]#echo "https test..." > /app/code/ssl/index.html
重启nginx:
[root@web01 ~]#nginx -t
[root@web01 ~]#nginx -s reload
浏览器打开:https://192.168.10.7
如下图:

由于是自建证书,所以提示不安全。
Windows本地做hosts域名解析后,打开:https://ssl.test.com,如下图:

其他web节点,参照web01的方法配置ssl即可
(2)lb端配置
负载均衡端配置
lb01配置:ip:192.168.10.5
[root@lb01 ~]#vim /etc/nginx/conf.d/ssl.test.com.conf
upstream ssl_pools {
server 192.168.10.7:443;
}
server {
listen 80;
server_name ssl.test.com;
return 301 https://ssl.test.com$request_uri;
}
server {
listen 443 ssl;
server_name ssl.test.com;
ssl_certificate /etc/nginx/ssl_keys/server.crt;
ssl_certificate_key /etc/nginx/ssl_keys/server.key;
location / {
proxy_pass https://ssl_pools;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-Ip $remote_addr;
}
}
ssl证书:把web01自建的证书发给lb01的/etc/nginx/ssl_keys目录中
[root@web01 ~]#scp -p /etc/nginx/ssl_keys/* 192.168.10.5:/etc/nginx/ssl_keys
重启nginx
浏览器打开:https://192.168.10.5
如下:

Windows本地做hosts解析(C:\Windows\System32\drivers\etc\hosts文件添加:192.168.10.5 ssl.test.com)后,浏览器打开:https://ssl.test.com
如下:

如果负载均衡做了高可用的话,其他的lb参照lb01配置ssl即可。
[root@lb01 ~]#scp /etc/nginx/ssl_keys/* 192.168.10.6:/etc/nginx/ssl_keys
[root@lb01 ~]#scp /etc/nginx/conf.d/ssl.test.com.conf 192.168.10.6:/etc/nginx/conf.d/
高可用的vip:192.168.10.3
浏览器访问:https://192.168.10.3
做本地hosts解析后,浏览器访问:https://ssl.test.com
2.2.2 部分加密
方案2:web端不加密,加密负载均衡端
web配置:
server {
listen 80;
server_name ssl.test.com;
root /app/code/ssl;
location / {
index index.html;
}
}
lb配置:
upstream ssl_pools {
server 192.168.10.7:80;
}
server {
listen 80;
server_name ssl.test.com;
return 301 https://ssl.test.com$request_uri;
}
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl_keys/server.crt;
ssl_certificate_key /etc/nginx/ssl_keys/server.key;
location / {
proxy_pass http://ssl_spools; #注意是http
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
prozy_set_header X-Real-Ip $remote_addr;
}
}
如果web端涉及php,则web端中关于php的配置要加上:fastcgi_param HTTPS on #前面部分的请求是https,例如:
location ~* \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param HTTPS on; #适用于负载均衡是https,web端是http
#HTTPS on,告诉php请求来自于负载的https请求
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_parms;
}
2.2 优化与监控
(1)优化
https == http over tls,通过tls协议对数据进行加密
TLS:Transport Layer Security
server {
listen 443 ssl;
keepalive_timeout 70;
server_name ssl.test.com;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #指定ssl加密协议的版本
ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5:!aNULL:!eNULL:!EXPORT:!DES:!RC4!MD5;#加密算法,需要排除null算法、md5算法
ssl_certificate /etc/nginx/ssl_keys/server.crt; #公钥证书
ssl_certificate_key /etc/nginx/ssl_keys/server.key; #私钥
#设置https 会话缓存 10MB大小的空间用于存储缓存
ssl_session_cache shared:SSL:10m;
#超时时间 10分钟
ssl_session_timeout 10m;
....
}
命令行抓包:
[root@lb01 ~]#tcpdump -vvv -nnn port 80 or port 443
或Wireshark抓包

(2)监控
证书信息如下:

监控证书过期时间:
1、通过命令获取证书的过期日期
2、与当前时间对比(30天之前)
3、获得剩余的时间
1、获取证书的过期日期
查询已建立的网站证书是否过期(优先使用),例如:
curl -vL https://www.baidu.com | grep 'expire date'
#有一些命令的输出,并非标准输出,而是作为标准错误输出
[root@lb01 ~]#curl -vL https://www.baidu.com |& grep 'expire date'
* expire date: Aug 06 05:16:01 2023 GMT
[root@lb01 ~]#
或者:
curl -vL https://www.baidu.com 2>/dev/stdout |& grep 'expire date'
|&:表示把管道前面标准输出(正确)和标准错误输出都传递给后面的命令
如果不加,默认传递标准输出(正确)
查看本地证书文件的方式,查看证书是否过期:
[root@lb01 ~]#openssl x509 -in /etc/nginx/ssl_keys/server.crt -noout -dates
notBefore=Jul 7 15:36:43 2023 GMT
notAfter=Jun 13 15:36:43 2123 GMT
[root@lb01 ~]#
/etc/nginx/ssl_keys/server.crt:自建的证书
notAfter:过期时间
2、与当前时间对比
日期时间转换为秒,然后对比。
当前系统时间转换为秒:
[root@lb01 ~]#date +%s
1688780211
[root@lb01 ~]#
过期日期转换为秒:
获取到的过期日期:例如:
expire date: Aug 06 05:16:01 2023 GMT
如果系统是中文的,则为:
expire date: 8月 06 05:16:01 2023 GMT
需要临时把系统改为英文:export LANG=en_US.UTF-8
然后再获取日期
转为秒:
[root@lb01 ~]#date -d 'Aug 06 05:16:01 2023 GMT' +%s
1691298961
[root@lb01 ~]#
具体流程:
#1、当前系统的时间转为秒:
[root@lb01 ~]#date +%s
1688780454
[root@lb01 ~]#
#临时把系统改为英文(如果本身是英文,则不需要改):
export LANG=en_US.UTF-8
#2、获取证书的过期日期
[root@lb01 ~]#curl -Lv https://www.baidu.com -o /dev/null |& grep 'expire date' | awk -F 'date:|GMT' '{print $2}'
Aug 06 05:16:01 2023
[root@lb01 ~]#
#3、把过期日期转为秒
[root@lb01 ~]#date -d "Aug 06 05:16:01 2023" +%s
1691270161
[root@lb01 ~]#
#4、进行相减
[root@lb01 ~]#echo "1691270161 - 1688780454" | bc
2489707
[root@lb01 ~]#
#还有2489707秒就过期。
date +%s:显示时间为秒
date -d :根据描述显示日期或时间
写成脚本:
[root@lb01 ~]#vim /server/script/check_https.sh
#!/bin/bash
#author: xzm
#desc:检查指定ssl证书是否过期
#version: v1.0
#1、临时设置系统为英文环境
#如果系统不是英文环境,则临时修改为英文环境
[ $LANG != en_US.UTF-8 ] && export LANG=en_US.UTF-8
#2、var
urls="https://www.baidu.com https://www.logmm.org"
for url in $urls
do
#过期日期,原始格式
date_expire=`curl -vL $url |& grep 'expire date' | awk -F 'date:|GMT' '{print $2}'`
#当前系统时间(秒)
date_now_sec=`date +%s`
#3、过期日期转为秒
date_expire_sec=`date +%s -d "$date_expire"`
#4、两个秒数相减
date_guoqi=`echo "($date_expire_sec - $date_now_sec)/60/60/24" | bc`
#bc -l结果保留小数
#5、if判断不支持小数
if [ $date_guoqi -le 100 ]
then
echo "$url的https证书即将过期,还有$date_guoqi天"
fi
done
执行脚本:
[root@lb01 ~]#sh /server/script/check_https.sh
https://www.baidu.com的https证书即将过期,还有28天
https://www.logmm.org的https证书即将过期,还有86天
[root@lb01 ~]#
配置邮件服务,发出通知:
[root@lb01 ~]#vim /etc/mail.rc
set from=xxx@163.com #发件人
set smtp=smtp.163.com #配置使用163邮箱发生邮件
#如果邮件服务端口被营运商屏蔽了,则
#set smtp=smtps://smtp.163.com:465
#set ssl-verify=ignore
#set nss-config=/etc/pki
set smtp-auth-user=xxxx@163.com #用户名:邮箱名字、真实的邮箱地址
set smtp-auth-password=xxxx #邮箱授权码
set smtp-auth=login #认证形式:login
发送邮件:
[root@lb01 ~]#sh /server/script/check_https.sh | mail -s "https证书过期信息" 1282923129@qq.com
收到的邮件通知:

2.3 http2.0
默认情况下http是1.0版本,修改为2.0版本
所有机器都把listen 443 ssl ; 改成:listen 443 ssl http2;即可

红色框标记的就是http2.0的标记,它没有直接显示http2.0