← 返回博客
·安全相关

HTTPS 与 SSL/TLS 原理详解:从证书到配置实战

HTTPS 是现代网站的标配。本文深入讲解 SSL/TLS 的工作原理、证书类型、Let's Encrypt 自动续期,以及 Nginx 的完整 HTTPS 配置。

#HTTPS#SSL#TLS#证书#安全

为什么需要 HTTPS

HTTP 是明文传输。在同一个 Wi-Fi 下(比如咖啡馆),别人用 Wireshark 抓个包,你发的请求、Cookie、密码全看得见。

HTTPS 就是在 HTTP 外面套了一层 TLS(以前叫 SSL),把传输内容加密了。

但大多数人配 HTTPS 都是照着教程复制粘贴,出了问题不知道怎么排查。下面把这些讲清楚。

SSL 与 TLS 的关系

SSL 是老名字,3.0 版本之后改名为 TLS。

| 协议 | 状态 |

|------|------|

| SSL 2.0 / 3.0 | 已废弃,有安全漏洞 |

| TLS 1.0 / 1.1 | 已废弃 |

| TLS 1.2 | 目前主流 |

| TLS 1.3 | 新标准,更快更安全 |

**结论**:配 Nginx 时只开 TLS 1.2 和 1.3,1.0/1.1 全部关掉。

证书是怎么工作的

核心就三步:

  • **服务器** 有一对密钥:公钥(证书里带的)和私钥(自己留着,绝不能泄露)
  • 2. **客户端**(浏览器)用内置的**根证书**验证服务器证书是否可信

    3. 验证通过后,双方协商出一个**会话密钥**,后续通信用这个对称密钥加密

    为什么不用非对称加密全程加密?因为慢。TLS 的设计是:**用非对称加密协商密钥,用对称加密传输数据**——各取所长。

    证书类型

    | 类型 | 验证内容 | 适合场景 |

    |------|---------|--------|

    | DV(Domain Validation) | 只验证域名所有权 | 个人项目、博客 |

    | OV(Organization Validation) | 验证企业身份 | 企业官网 |

    | EV(Extended Validation) | 严格验证企业身份 | 银行、金融(现在 EV 的绿色地址栏已取消,意义不大) |

    | 通配符(Wildcard) | 支持 *.example.com | 多个子域名 |

    个人项目用 Let's Encrypt 的 DV 证书就够了,免费,三个月自动续期。

    Let's Encrypt 自动续期

    用 certbot(Nginx 为例)

    # 安装 certbot

    sudo apt install certbot python3-certbot-nginx # Ubuntu/Debian

    sudo yum install certbot python3-certbot-nginx # CentOS

    # 自动配置 Nginx

    sudo certbot --nginx -d example.com -d www.example.com

    # 手动模式(如果 certbot 自动配置有问题)

    sudo certbot certonly --nginx -d example.com

    自动续期

    certbot 安装时会自动加入 cron(在 /etc/cron.d/certbot),每天检查证书是否快过期(小于 30 天),自动续期。

    手动测试续期是否正常:

    sudo certbot renew --dry-run

    如果 --dry-run 不报错,说明自动续期配置正常。

    常见坑:端口 80 必须开放

    Let's Encrypt 的 HTTP-01 验证方式需要访问你服务器的 80 端口。如果防火墙把 80 关了,续期会失败。

    # 检查 certbot 续期是否成功(看日志)

    sudo journalctl -u certbot.service --since "7 days ago"

    Nginx 配置 HTTPS

    server {

    listen 443 ssl http2;

    server_name example.com www.example.com;

    # 证书路径(certbot 默认路径)

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # TLS 版本(禁用 1.0/1.1)

    ssl_protocols TLSv1.2 TLSv1.3;

    # 加密套件(推荐 Mozilla 的配置)

    ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256";

    ssl_prefer_server_ciphers off;

    # HSTS(强制浏览器用 HTTPS 访问,防中间人降级攻击)

    add_header Strict-Transport-Security "max-age=63072000" always;

    # 根路径

    root /var/www/html;

    index index.html;

    }

    # HTTP 自动跳转 HTTPS

    server {

    listen 80;

    server_name example.com www.example.com;

    return 301 https://$server_name$request_uri;

    }

    如何排查证书问题

    用 openssl 查看证书信息

    openssl s_client -connect example.com:443 -servername example.com | openssl x509 -noout -text

    重点看:

  • `Validity`:证书有效期
  • `Subject Alternative Name`:是否包含你的域名
  • `Issuer`:签发机构(Let's Encrypt / ZeroSSL 等)
  • 用 curl 验证

    curl -vI https://example.com

    如果证书有问题,curl 会报 SSL certificate problem

    浏览器显示"不安全"的常见原因

  • 证书过期了(忘了续期)
  • 2. 证书不包含当前访问的域名(比如证书只签了 example.com,用户访问 www.example.com

    3. 混合内容(页面是 HTTPS,但里面引用了 HTTP 的资源)——这个在 DevTools 的 Console 里能看到警告

    4. 用了自签名证书(浏览器不信任)

    中间人攻击(MITM)是怎么回事

    攻击者把你和目标服务器之间的流量拦截,假装自己是服务器(对你)和客户端(对服务器)。

    HTTPS 防 MITM 的核心就是**证书验证**——如果攻击者没有目标域名的私钥,他就没法签发合法的证书,浏览器会报证书不安全。

    但有一种情况例外:**用户主动信任了攻击者的根证书**(比如公司内网的安全审计、或者手机装了恶意证书)。一旦根证书被信任,MITM 就完全可行了。

    所以:不要随便装来历不明的根证书。

    HSTS

    HSTS(HTTP Strict Transport Security)是让浏览器记住"这个域名只能用 HTTPS 访问"。

    加了 HSTS 之后,即使用户手动把地址栏的 https:// 改成 http://,浏览器也会强制用 HTTPS。

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

    max-age 单位是秒,63072000 是两年。includeSubDomains 表示子域名也适用。

    **注意**:开启 HSTS 之前,确保你的网站 HTTPS 是稳定可用的——一旦浏览器记住了 HSTS,HTTP 就再也访问不了了。


    总结

    HTTPS 不是可选项,是基线。Let's Encrypt + certbot 基本是标配了,配置一次自动续期,后面不用管。

    > **Pro Tip**: 用 SSL Labs Test(https://www.ssllabs.com/ssltest/)可以给你网站的 HTTPS 配置打分,A+ 是满分。