深入理解HTTPS:从概念到实战优化

深入理解HTTPS:从概念到实战优化

🌟 如果你对 HTTP 协议的基础知识(如请求/响应报文、状态码等)还不熟悉,建议先阅读:《HTTP协议完全指南:从报文到状态码》

一:概述

HTTPS = HTTP + TLS/SSL

在 HTTP 的基础上,HTTPS 增加了加密和身份验证,保障数据传输的安全性。

主要作用:

  1. 加密通信:防止数据在传输过程中被窃取或篡改
  2. 身份验证:确认服务器身份,防止钓鱼或中间人攻击
  3. 数据完整性:确保数据在传输过程中未被修改

二:工作流程

HTTPS 基于 TLS(传输层安全协议),核心流程如下:

  1. 客户端发起 HTTPS 请求
    • 浏览器访问 https://example.com
    • 告诉服务器它支持的TLS版本和加密算法 + 一个随机数
  2. 服务器返回证书
    • 证书中包含公钥、域名、颁发机构等信息 + 一个随机数
  3. 客户端验证证书
    • 检查证书是否可信(CA 签名、有效期、域名匹配)
  4. 生成会话密钥
    • 生成一个预密钥,然后用服务器的公钥加密后发给服务器,服务器用密钥解密,然后将预密钥和两个随机数组成对称密钥
  5. 加密通信
    • 后续所有 HTTP 请求和响应 都用对称密钥加密传输

三:创建自签名证书

  • .key:私钥

  • .csr:申请证书的文件,交给CA(如果指定为自签名证书 -x509 则不生成)

  • .crt:公钥 + 证书

  • .pem:公钥 + 证书

  • 一步到位

    bash 复制代码
    openssl req -days 365 -x509 -sha256 -nodes -newkey rsa:2048 \
    -keyout server.key -out server.crt
  • 分两步

    1. 创建私钥

      bash 复制代码
      openssl genrsa -out server.key 2048
    2. 根据私钥生成证书

      • -days:指定证书有效时间(单位:天)
      • -x509:直接生成自签名证书(不用额外 CSR
      • -sha256:签名算法
      • -key:指定已有私钥位置
      • -out:指定输出证书文件位置
      bash 复制代码
      openssl req -days 365 -x509 -sha256 -key server.key -out server.crt

四:案例

1)案例一:HTTPS 搭建

  1. 创建存放 SSL 证书和私钥的目录

    bash 复制代码
    [root@web01 ~]# mkdir -p /etc/nginx/ssl_keys
  2. 上传证书

    bash 复制代码
    [root@web01 ~]# unzip /opt/software/ssl.jackmk.cn_nginx.zip -d /etc/nginx/ssl_keys/
  3. 创建站点

    bash 复制代码
    # 创建站点目录
    [root@web01 ~]# mkdir -p /opt/module/ssl
    
    # 创建站点 index.html
    [root@web01 ~]# echo "index" > /opt/module/ssl/index.html
  4. 创建站点配置文件

    bash 复制代码
    [root@web01 ~]# vim /etc/nginx/conf.d/ssl.conf
    bash 复制代码
    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;
        }
    }
  5. 刷新 Nginx

    bash 复制代码
    nginx -t
    nginx -s reload
  6. 配置 hosts

    bash 复制代码
    192.168.2.104 ssl.jackmk.cn
  7. 访问


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

  1. 创建存放 SSL 证书和私钥的目录

    bash 复制代码
    [root@web01 ~]# mkdir -p /etc/nginx/ssl_keys
  2. 上传证书

    • ssl.jackmk.cn.key:私钥
    • ssl.jackmk.cn.pem:证书 + 公钥
    bash 复制代码
    [root@web01 ~]# unzip /opt/software/ssl.jackmk.cn_nginx.zip -d /etc/nginx/ssl_keys/
  3. 创建站点

    bash 复制代码
    # 创建站点目录
    [root@web01 ~]# mkdir -p /opt/module/ssl
    
    # 创建站点 index.html
    [root@web01 ~]# echo "index" > /opt/module/ssl/index.html
  4. 创建站点配置文件

    bash 复制代码
    [root@web01 ~]# vim /etc/nginx/conf.d/ssl.conf
    bash 复制代码
    server {
        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;
        }
    }
  5. 刷新 Nginx

    bash 复制代码
    [root@web01 ~]# nginx -t
    [root@web01 ~]# nginx -s reload
  6. 配置 hosts

    bash 复制代码
    192.168.2.104 ssl.jackmk.cn
  7. 访问

    bash 复制代码
    此时如果请求 http://ssl.jackmk.cn 会自动跳转至 http://ssl.jackmk.cn

4)案例四:网站集群 HTTPS 配置

1)部署 web01web02

  1. 创建存放 SSL 证书和私钥的目录

    bash 复制代码
    mkdir -p /etc/nginx/ssl_keys
  2. 创建私钥以及证书

    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
  3. 创建站点

    bash 复制代码
    # 创建站点目录
    mkdir -p /opt/module/ssl
    
    # 创建站点 index.html
    echo "web01" > /opt/module/ssl/index.html
    or
    echo "web02" > /opt/module/ssl/index.html
  4. 创建站点配置文件

    如果是 https -> http 那么就不需要配置 ssl keys

    bash 复制代码
    vim /etc/nginx/conf.d/ssl.conf
    bash 复制代码
    server {
        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;
        }
    }
  5. 刷新 Nginx

    bash 复制代码
    nginx -t
    nginx -s reload

2)部署 lb01

  1. 创建存放 SSL 证书和私钥的目录

    bash 复制代码
    [root@lb01 ~]# mkdir -p /etc/nginx/ssl_keys
  2. 创建私钥以及证书

    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
  3. 创建配置文件

    bash 复制代码
    [root@lb01 ~]# vim /etc/nginx/conf.d/ssl.conf
    bash 复制代码
    upstream 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;
        }
    }
  4. 刷新 Nginx

    bash 复制代码
    [root@lb01 ~]# nginx -t
    [root@lb01 ~]# nginx -s reload
  5. 配置 hosts

    bash 复制代码
    192.168.2.102 ssl.cn
  6. 访问


五:优化

主要是针对 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(性能更好)
      bash 复制代码
      ssl_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 :调用 opensslx509 子命令,主要用于 查看、转换、管理 X.509 证书
    • -in :指定输入文件,也就是要读取的证书文件。
    • -noout :默认 openssl x509 会把证书的所有内容(包括公钥、签发者、使用者等)都打印出来。 加了 -noout 表示 不要输出证书本身的 Base64 内容,只输出你后面指定的信息。
    • -dates:输出证书的有效期信息:
    bash 复制代码
    openssl x509 -in /etc/nginx/ssl_keys/ssl.crt -noout -dates
    bash 复制代码
    notBefore=Aug 22 16:52:34 2025 GMT  # 证书开始生效的时间
    notAfter=Aug 22 16:52:34 2026 GMT   # 证书过期的时间
  • curl 远程监控

    bash 复制代码
    curl -Lv https://www.baidu.com |& grep 'expire date'

3)监控脚本

  • 检查单个指定的网站的 HTTPS 证书过期时间

    bash 复制代码
    vim 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 证书过期时间

    bash 复制代码
    vim 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)是未来的发展趋势。

相关推荐
童先生3 小时前
我想把minio弄成https访问能行吗?
网络协议·http·https
眰恦ゞLYF5 小时前
TCP与HTTP协议以及爬虫
爬虫·网络协议·tcp协议·http协议
励志五个月成为嵌入式糕手9 小时前
0825 http梳理作业
网络·网络协议·http
DebugKitty11 小时前
网络编程1-基本概念、函数接口
运维·服务器·网络·网络协议·socket·tcp
2501_9212904411 小时前
嵌入式第三十六天(网络编程(TCP))
网络·网络协议·tcp/ip
青草地溪水旁14 小时前
HTTP数据之旅:一个网络请求的完整冒险
网络·网络协议·http
2501_9277730716 小时前
Linux系统操作编程——http
网络·网络协议·http
Kookoos1 天前
System.IO.Pipelines 与“零拷贝”:在 .NET 打造高吞吐二进制 RPC
网络协议·rpc·.net·零拷贝·二进制协议·pipelines
MC皮蛋侠客1 天前
使用Python实现DLT645-2007智能电表协议
python·网络协议·tcp/ip·能源