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