深入理解HTTPS:从概念到实战优化
🌟 如果你对 HTTP 协议的基础知识(如请求/响应报文、状态码等)还不熟悉,建议先阅读:《HTTP协议完全指南:从报文到状态码》
一:概述
HTTPS = HTTP + TLS/SSL
在 HTTP 的基础上,HTTPS 增加了加密和身份验证,保障数据传输的安全性。
主要作用:
- 加密通信:防止数据在传输过程中被窃取或篡改
- 身份验证:确认服务器身份,防止钓鱼或中间人攻击
- 数据完整性:确保数据在传输过程中未被修改
二:工作流程
HTTPS 基于 TLS(传输层安全协议),核心流程如下:
- 客户端发起 HTTPS 请求
- 浏览器访问
https://example.com
- 告诉服务器它支持的TLS版本和加密算法 + 一个随机数
- 浏览器访问
- 服务器返回证书
- 证书中包含公钥、域名、颁发机构等信息 + 一个随机数
- 客户端验证证书
- 检查证书是否可信(CA 签名、有效期、域名匹配)
- 生成会话密钥
- 生成一个预密钥,然后用服务器的公钥加密后发给服务器,服务器用密钥解密,然后将预密钥和两个随机数组成对称密钥
- 加密通信
- 后续所有 HTTP 请求和响应 都用对称密钥加密传输
三:创建自签名证书
.key
:私钥
.csr
:申请证书的文件,交给CA(如果指定为自签名证书-x509
则不生成)
.crt
:公钥 + 证书
.pem
:公钥 + 证书
-
一步到位
bashopenssl req -days 365 -x509 -sha256 -nodes -newkey rsa:2048 \ -keyout server.key -out server.crt
-
分两步
-
创建私钥
bashopenssl genrsa -out server.key 2048
-
根据私钥生成证书
-days
:指定证书有效时间(单位:天)-x509
:直接生成自签名证书(不用额外CSR
)-sha256
:签名算法-key
:指定已有私钥位置-out
:指定输出证书文件位置
bashopenssl req -days 365 -x509 -sha256 -key server.key -out server.crt
-
四:案例
1)案例一:HTTPS 搭建
-
创建存放
SSL
证书和私钥的目录bash[root@web01 ~]# mkdir -p /etc/nginx/ssl_keys
-
上传证书
bash[root@web01 ~]# unzip /opt/software/ssl.jackmk.cn_nginx.zip -d /etc/nginx/ssl_keys/
-
创建站点
bash# 创建站点目录 [root@web01 ~]# mkdir -p /opt/module/ssl # 创建站点 index.html [root@web01 ~]# echo "index" > /opt/module/ssl/index.html
-
创建站点配置文件
bash[root@web01 ~]# vim /etc/nginx/conf.d/ssl.conf
bashserver { listen 443 ssl; # ssl on; # 1.15.0 以后被废弃了 server_name ssl.jackmk.cn; root /opt/module/ssl/; # ssl key ssl_certificate /etc/nginx/ssl_keys/ssl.jackmk.cn.pem; ssl_certificate_key /etc/nginx/ssl_keys/ssl.jackmk.cn.key; location / { index index.html; } }
-
刷新
Nginx
bashnginx -t nginx -s reload
-
配置
hosts
bash192.168.2.104 ssl.jackmk.cn
-
访问
2)案例二:HTTP/2 搭建
bash
server {
listen 443 ssl http2; # 只要加上这个就行
server_name ssl.jackmk.cn;
root /opt/module/ssl/;
# ssl key
ssl_certificate /etc/nginx/ssl_keys/ssl.jackmk.cn.pem;
ssl_certificate_key /etc/nginx/ssl_keys/ssl.jackmk.cn.key;
location / {
index index.html;
}
}
3)案例三:HTTP 重定向 HTTPS
-
创建存放
SSL
证书和私钥的目录bash[root@web01 ~]# mkdir -p /etc/nginx/ssl_keys
-
上传证书
ssl.jackmk.cn.key
:私钥ssl.jackmk.cn.pem
:证书 + 公钥
bash[root@web01 ~]# unzip /opt/software/ssl.jackmk.cn_nginx.zip -d /etc/nginx/ssl_keys/
-
创建站点
bash# 创建站点目录 [root@web01 ~]# mkdir -p /opt/module/ssl # 创建站点 index.html [root@web01 ~]# echo "index" > /opt/module/ssl/index.html
-
创建站点配置文件
bash[root@web01 ~]# vim /etc/nginx/conf.d/ssl.conf
bashserver { listen 80; server_name ssl.jackmk.cn; return 301 https://ssl.jackmk.cn$request_uri; #rewrite ^(.*)$ https://ssl.jackmk.cn$1 permanent; } server { listen 443 ssl; # ssl on; # 1.15.0 以后被废弃了 server_name ssl.jackmk.cn; root /opt/module/ssl/; # ssl key ssl_certificate /etc/nginx/ssl_keys/ssl.jackmk.cn.pem; ssl_certificate_key /etc/nginx/ssl_keys/ssl.jackmk.cn.key; location / { index index.html; } }
-
刷新
Nginx
bash[root@web01 ~]# nginx -t [root@web01 ~]# nginx -s reload
-
配置
hosts
bash192.168.2.104 ssl.jackmk.cn
-
访问
bash此时如果请求 http://ssl.jackmk.cn 会自动跳转至 http://ssl.jackmk.cn
4)案例四:网站集群 HTTPS 配置
1)部署 web01
、web02
-
创建存放
SSL
证书和私钥的目录bashmkdir -p /etc/nginx/ssl_keys
-
创建私钥以及证书
bash# 1. 切换目录 cd /etc/nginx/ssl_keys # 2. 创建私钥 openssl genrsa -out ssl.key 2048 # 3. 创建证书 openssl req -days 365 -x509 -sha256 -key ssl.key -out ssl.crt
-
创建站点
bash# 创建站点目录 mkdir -p /opt/module/ssl # 创建站点 index.html echo "web01" > /opt/module/ssl/index.html or echo "web02" > /opt/module/ssl/index.html
-
创建站点配置文件
如果是
https -> http
那么就不需要配置ssl keys
bashvim /etc/nginx/conf.d/ssl.conf
bashserver { listen 443 ssl; server_name ssl.cn; root /opt/module/ssl/; # ssl keys ssl_certificate /etc/nginx/ssl_keys/ssl.crt; ssl_certificate_key /etc/nginx/ssl_keys/ssl.key; location / { index index.html; } }
-
刷新
Nginx
bashnginx -t nginx -s reload
2)部署 lb01
-
创建存放
SSL
证书和私钥的目录bash[root@lb01 ~]# mkdir -p /etc/nginx/ssl_keys
-
创建私钥以及证书
bash# 1. 切换目录 [root@lb01 ~]# cd /etc/nginx/ssl_keys # 2. 创建私钥 [root@lb01 ssl_keys]# openssl genrsa -out ssl.key 2048 # 3. 创建证书 [root@lb01 ssl_keys]# openssl req -days 365 -x509 -sha256 -key ssl.key -out ssl.crt
-
创建配置文件
bash[root@lb01 ~]# vim /etc/nginx/conf.d/ssl.conf
bashupstream ssl_pools { server 192.168.2.104:443; server 192.168.2.105:443; } server { listen 80; server_name ssl.cn; return 301 https://ssl.cn$request_uri; } server { listen 443 ssl; server_name ssl.cn; # ssl keys ssl_certificate /etc/nginx/ssl_keys/ssl.crt; ssl_certificate_key /etc/nginx/ssl_keys/ssl.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; } }
-
刷新
Nginx
bash[root@lb01 ~]# nginx -t [root@lb01 ~]# nginx -s reload
-
配置
hosts
bash192.168.2.102 ssl.cn
-
访问
五:优化
主要是针对 SSL/TLS 加密连接做了一些安全和性能优化。
-
listen 443 ssl
- 作用:开启 HTTPS 服务,监听 443 端口,并启用 SSL 模块。(没有这行,就算配了证书也不会启用 HTTPS)
-
keepalive_timeout 70
-
作用 :设置 长连接保持时间为 70 秒。
-
好处:
-
客户端和服务端之间如果频繁请求(比如网页加载很多小文件),可以复用连接,减少握手开销。
-
设置过短会导致频繁握手,过长又会占用资源。70s 算是折中优化。
-
-
-
ssl_protocols TLSv1 TLSv1.1 TLSv1.2
-
作用:指定允许使用的 TLS 协议版本。
-
这里启用了 TLSv1、TLSv1.1、TLSv1.2,但注意:
- TLSv1 和 TLSv1.1 已过时(安全性差),现代浏览器和安全规范(如 PCI DSS)都建议关闭。
- 最佳实践是只保留 TLSv1.2+ ,甚至启用 TLSv1.3(性能更好)
bashssl_protocols TLSv1.2 TLSv1.3;
-
-
ssl_ciphers ...
- 作用:指定允许使用的加密算法套件。
- 配置里显式排除了:
!aNULL
→ 禁止匿名算法!eNULL
→ 禁止无加密算法!EXPORT
→ 禁止出口级弱加密!DES
、!RC4
、!MD5
→ 禁止已知不安全的算法
-
ssl_certificate
/ssl_certificate_key
- 作用:指定服务器证书和私钥。
cert.pem
→ 公钥证书cert.key
→ 对应的私钥
-
ssl_session_cache shared:SSL:10m
- 作用:配置 SSL 会话缓存。Nginx 在 10MB 的共享内存里存储 SSL 会话信息。
- 好处 :
- 客户端下次访问时可以复用会话,不必重新完整握手(节省 CPU 和握手延迟)。
- 10MB 大约能缓存 4 万次会话(每个会话约 256B)。
-
ssl_session_timeout 10m
- 作用:设置 SSL 会话的过期时间(10 分钟)。
- 好处:在这段时间内,同一个客户端可以复用 TLS 会话,避免再次握手,提高性能。
bash
server {
listen 443 ssl;
keepalive_timeout 70;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5;
ssl_certificate /usr/local/nginx/conf/cert.pem;
ssl_certificate_key /usr/local/nginx/conf/cert.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
...
}
六:监控
主要针对 HTTPS 证书过期监控方案整理
1)监控思路
- 通过命令获取证书的过期日期
- 将证书过期日期与当前日期对比
- 计算剩余天数(如小于 30 天报警)
2)监控方式
-
本地证书检查
openssl x509
:调用openssl
的x509
子命令,主要用于 查看、转换、管理 X.509 证书。-in
:指定输入文件,也就是要读取的证书文件。-noout
:默认openssl x509
会把证书的所有内容(包括公钥、签发者、使用者等)都打印出来。 加了-noout
表示 不要输出证书本身的 Base64 内容,只输出你后面指定的信息。-dates
:输出证书的有效期信息:
bashopenssl x509 -in /etc/nginx/ssl_keys/ssl.crt -noout -dates
bashnotBefore=Aug 22 16:52:34 2025 GMT # 证书开始生效的时间 notAfter=Aug 22 16:52:34 2026 GMT # 证书过期的时间
-
curl
远程监控bashcurl -Lv https://www.baidu.com |& grep 'expire date'
3)监控脚本
-
检查单个指定的网站的 HTTPS 证书过期时间
bashvim check_https_cert.sh chmod 755 check_https_cert.sh
bash#!/bin/bash #============================= # 1. 基础变量 # URL: 定义指定的网站 # LANG: 临时改为英文环境,避免 date 解析报错 #============================= URL="https://www.jd.com" export LANG="en_US.UTF-8" #============================= # 2. 获取证书过期时间戳 # curl -Lv:显示详细信息并跟随重定向 # egrep 'expire date':提取证书过期时间 #============================= EXPIRE_DATE_RAW=$(curl -Lv "${URL}" -o /dev/null 2>&1 | grep -i 'expire date' | awk -F 'date:|GMT' '{print $2}') EXPIRE_SECOND=$(date -d "${EXPIRE_DATE_RAW}" +%s) #============================= # 3. 获取当前时间戳 #============================= NOW_SECOND=$(date +%s) #============================= # 4. 计算剩余天数 #============================= EXPIRE_DAYS=$(( (EXPIRE_SECOND - NOW_SECOND) / 86400 )) #============================= # 5. 输出结果 #============================= if [ "${EXPIRE_DAYS}" -le 300 ]; then echo "[警告] ${URL} 的 HTTPS 证书即将过期,还有 ${EXPIRE_DAYS} 天" else echo "[正常] ${URL} 的 HTTPS 证书还剩 ${EXPIRE_DAYS} 天" fi
-
检查多个指定网站的HTTPS 证书过期时间
bashvim check_https_cert.sh chmod 755 check_https_cert.sh
bash#!/bin/bash #============================= # 1. 基础变量 # LANG: 临时改为英文环境,避免 date 解析报错 # URLS: 定义要检测的多个网站 #============================= URLS=("https://www.jd.com" "https://www.baidu.com" "https://www.taobao.com") export LANG="en_US.UTF-8" #============================= # 2. 遍历检测每个 URL 的证书有效期 #============================= for URL in "${URLS[@]}"; do # 2.1 获取证书过期时间(原始格式) EXPIRE_DATE_RAW=$(curl -Lv "${URL}" -o /dev/null 2>&1 | grep -i 'expire date' | awk -F 'date:|GMT' '{print $2}') # 2.2 转换为时间戳 EXPIRE_SECOND=$(date -d "${EXPIRE_DATE_RAW}" +%s) # 2.3 当前时间戳 NOW_SECOND=$(date +%s) # 2.4 计算剩余天数 EXPIRE_DAYS=$(( (EXPIRE_SECOND - NOW_SECOND) / 86400 )) #============================= # 3. 输出结果 #============================= if [ "${EXPIRE_DAYS}" -le 300 ]; then echo "[警告] ${URL} 的 HTTPS 证书即将过期,还有 ${EXPIRE_DAYS} 天" else echo "[正常] ${URL} 的 HTTPS 证书还剩 ${EXPIRE_DAYS} 天" fi done
总结
本文从理论到实践,详细阐述了HTTPS如何为HTTP协议提供加密、认证和完整性保护,从而构筑现代Web安全的核心防线。我们不仅剖析了TLS握手的工作流程,动手创建了自签名证书,更通过多个渐进式的实战案例(单点HTTPS/HTTP2、重定向、集群配置)展示了如何在复杂的生产环境中应用它。
-
💎 核心价值:HTTPS已不再是可选项,而是现代网站的标配。它保护用户隐私、提升网站信誉(浏览器安全标识🔒)、同时也是使用HTTP/2等现代协议的前提条件。
-
⚙️ 实践意义:本文提供的案例和优化、监控方案,源自于真实的运维场景。正确地配置HTTPS(如选择安全的密码套件、开启HSTS、配置重定向)和建立有效的监控(如证书过期监控),是保障服务稳定性和安全性的关键。
-
🔮 未来方向:安全是一个持续的过程。TLS协议版本和推荐的加密套件也在不断更新以应对新的威胁。自动化(如使用Let's Encrypt自动续期证书)和更严格的安全策略(如预加载HSTS)是未来的发展趋势。