SSL 证书与 HTTPS:使用 Certbot 免费获取证书

📂 所属阶段:第六阶段 — 上线部署(生产篇)
🔗 相关章节:Gunicorn 与 Nginx · Docker 部署全流程


1. 为什么需要 HTTPS?

HTTP(不安全):
用户 → 发送密码 → 中间人拦截 → 明文暴露 😱

HTTPS(安全):
用户 → 发送密码 → SSL/TLS 加密 → 服务器解密 ✅

HTTPS 额外优势:
1. 防止流量劫持
2. 防止内容篡改
3. SEO 加分(Google 优先收录 HTTPS 网站)
4. 浏览器地址栏显示安全锁
5. 允许使用 HTTP/2 协议(更快)

2. Let's Encrypt 免费证书

Let's Encrypt 是非营利机构,提供永久免费的 SSL 证书(90 天有效期,可自动续期)。

2.1 安装 Certbot

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

# CentOS / RHEL
sudo yum install certbot python3-certbot-nginx

# macOS
brew install certbot

2.2 申请证书(Nginx 自动配置)

# Certbot 自动修改 Nginx 配置(最简单,推荐新手)
sudo certbot --nginx -d daomanpy.com -d www.daomanpy.com

# 按提示输入:
# 1. 邮箱地址(接收过期通知)
# 2. 同意服务条款
# 3. 是否共享邮箱
# 4. 选择是否自动跳转 HTTPS(建议选 "2" 即全部重定向)

2.3 只获取证书(手动配置)

# 只获取证书,不修改 Nginx 配置
sudo certbot certonly --nginx \
    -d daomanpy.com \
    -d www.daomanpy.com \
    --webroot -w /var/www/html

# 证书存放位置
# /etc/letsencrypt/live/daomanpy.com/
#   ├── fullchain.pem   ← Nginx ssl_certificate(包含证书链)
#   ├── privkey.pem     ← Nginx ssl_certificate_key(私钥)
#   └── README

3. Nginx HTTPS 配置

3.1 完整 HTTPS 配置

# /etc/nginx/conf.d/daoman.conf

# HTTP → HTTPS 重定向
server {
    listen 80;
    server_name daomanpy.com www.daomanpy.com;

    # 强制跳转 HTTPS
    return 301 https://$host$request_uri;
}

# HTTPS 主站
server {
    listen 443 ssl http2;
    server_name daomanpy.com www.daomanpy.com;

    # SSL 证书(Let's Encrypt)
    ssl_certificate /etc/letsencrypt/live/daomanpy.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/daomanpy.com/privkey.pem;

    # 安全 SSL 配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # SSL 会话缓存
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;

    # OCSP Stapling(加快验证)
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # 安全头
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript image/svg+xml;

    # 反向代理到 Gunicorn
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off;
        proxy_connect_timeout 60s;
        proxy_read_timeout 60s;
        client_max_body_size 20M;
    }

    # 静态文件(Nginx 直接服务,更快)
    location /static/ {
        alias /var/www/daoman/static/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # 健康检查
    location /health {
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
}

4. Certbot 自动续期

4.1 测试续期

# 先测试续期是否正常(dry-run)
sudo certbot renew --dry-run

4.2 配置定时续期

# 编辑 crontab
sudo crontab -e

# 添加:每天凌晨 3 点检查续期
0 3 * * * certbot renew --quiet --renew-hook "systemctl reload nginx"
# 或者使用 systemd timer(Ubuntu 18.04+)
sudo systemctl status certbot.timer
sudo systemctl list-timers certbot.timer

4.3 Docker 中的证书

# docker-compose.prod.yml(补充)
  certbot:
    image: certbot/certbot
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h && wait $$!; done;'"
    depends_on:
      - nginx

5. HTTPS 安全检查

# 在线检测 SSL 安全性
# https://www.ssllabs.com/ssltest/
# https://myssl.com/

# 本地测试
openssl s_client -connect daomanpy.com:443 -showcerts

# 检查证书信息
openssl x509 -in /etc/letsencrypt/live/daomanpy.com/fullchain.pem -text -noout

6. 小结

HTTPS 部署流程:

1. 安装 Certbot
2. 申请证书:certbot --nginx -d domain.com
3. 配置 Nginx HTTPS
4. 设置自动续期:certbot renew --dry-run
5. 上线后用 https://www.ssllabs.com/ssltest/ 检测

证书有效期:90 天
自动续期:certbot renew(推荐加到 crontab 或 systemd timer)

💡 记住:HTTPS 不只是证书的问题,整个网站(包括 CSS/JS/图片/表单/登录等)都应该在 HTTPS 下运行。Mixed Content(混用 HTTP/HTTPS)会导致浏览器安全警告。


🔗 扩展阅读