SSL/TLS 证书管理

2026-06-22 · 6 阅读 · 572字
LinuxNginx安全

SSL/TLS 证书管理

概述

SSL/TLS 证书是保障网络通信安全的基础。本文介绍如何使用 Let's Encrypt 免费证书,配置 HTTPS,并实现自动化续期。

核心概念

术语 说明
SSL Secure Sockets Layer,安全套接层(已废弃)
TLS Transport Layer Security,传输层安全(SSL 的继任者)
CA 证书颁发机构
CSR 证书签名请求
SNI 服务器名称指示,支持在同一 IP 上托管多个 HTTPS 站点

Let's Encrypt 与 Certbot

Let's Encrypt 提供免费、自动化的 SSL/TLS 证书。Certbot 是官方客户端。

安装 Certbot

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

# CentOS
sudo dnf install certbot python3-certbot-nginx

# Docker
docker run --rm -v /etc/letsencrypt:/etc/letsencrypt certbot/certbot certonly

获取证书

Nginx 方式

# 自动获取并配置 Nginx
sudo certbot --nginx -d example.com -d www.example.com

# 仅获取证书,手动配置
sudo certbot certonly --nginx -d example.com

独立模式(无需 Web 服务器)

sudo certbot certonly --standalone -d example.com \
    --non-interactive \
    --agree-tos \
    -m admin@example.com

DNS 验证(通配符证书)

# 支持 *.example.com
sudo certbot certonly --manual \
    --preferred-challenges dns \
    -d example.com \
    -d "*.example.com"

证书文件结构

/etc/letsencrypt/live/example.com/
├── cert.pem        # 服务器证书
├── chain.pem       # 中间证书链
├── fullchain.pem   # cert.pem + chain.pem(通常使用这个)
├── privkey.pem     # 私钥(安全保管!)
└── README

Nginx HTTPS 配置

server {
    listen 443 ssl http2;
    server_name example.com;

    # 证书配置
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    # 安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

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

    # 其他安全头
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
}

# HTTP 跳转
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

自动续期

Certbot 自动续期

# 测试续期流程
sudo certbot renew --dry-run

# 查看续期定时任务
sudo systemctl status certbot.timer

# 手动续期
sudo certbot renew

crontab 方式

# 每天检查两次(推荐)
0 */12 * * * /usr/bin/certbot renew --quiet --no-self-upgrade

续期后重启服务

# 通过 --deploy-hook 在续期后自动重启
sudo certbot renew --deploy-hook "systemctl reload nginx"

# certbot 配置(/etc/letsencrypt/cli.ini)
deploy-hook = systemctl reload nginx

Docker 环境自动续期

# 使用 docker-compose
0 0 * * * docker exec nginx-certbot certbot renew && docker exec nginx nginx -s reload

证书监控

过期检查脚本

#!/bin/bash
# check_cert_expiry.sh

DOMAINS=("example.com" "api.example.com")
WARN_DAYS=30
CRITICAL_DAYS=7

for domain in "${DOMAINS[@]}"; do
    expiry_date=$(openssl x509 -in "/etc/letsencrypt/live/$domain/fullchain.pem" \
        -noout -enddate | cut -d= -f2)
    expiry_epoch=$(date -d "$expiry_date" +%s)
    now_epoch=$(date +%s)

    days_left=$(( (expiry_epoch - now_epoch) / 86400 ))

    if [[ $days_left -lt $CRITICAL_DAYS ]]; then
        echo "CRITICAL: $domain 证书将在 $days_left 天后过期!"
        # 发送告警
    elif [[ $days_left -lt $WARN_DAYS ]]; then
        echo "WARNING: $domain 证书将在 $days_left 天后过期"
    else
        echo "OK: $domain 证书有效期还有 $days_left 天"
    fi
done

Prometheus Exporter 监控

# prometheus.yml
scrape_configs:
  - job_name: 'ssl_expiry'
    static_configs:
      - targets: ['ssl-exporter:9219']

安全性最佳实践

1. 证书等级选择

DV (域名验证): 基础 HTTPS,适合个人网站
OV (组织验证): 验证组织身份,适合企业网站
EV (扩展验证): 最高级别,浏览器显示公司名(逐渐被淘汰)

2. 密钥管理

  • 私钥权限设置为 600,属主为 root
  • 使用硬件安全模块 (HSM) 保护关键证书
  • 定期轮换密钥对

3. 评分工具

# 测试 SSL 配置
curl https://www.ssllabs.com/ssltest/analyze.html?d=example.com

# 本地测试
openssl s_client -connect example.com:443 -tls1_3
nmap --script ssl-enum-ciphers -p 443 example.com

常见问题

证书过期导致服务中断

预防措施:

  • 监控证书过期时间
  • 配置自动续期
  • 设置多级告警(30天、14天、7天、1天)

通配符证书

# 获取通配符证书
certbot certonly --manual --preferred-challenges dns \
    -d example.com -d "*.example.com"

# DNS TXT 记录验证
_acme-challenge.example.com.  IN TXT  "..."

多域名证书 SAN

# 一个证书包含多个域名
certbot certonly --nginx \
    -d example.com \
    -d www.example.com \
    -d api.example.com \
    -d admin.example.com

总结

SSL/TLS 证书管理是现代网站运营的基础工作。使用 Let's Encrypt + Certbot 可以零成本实现证书的自动获取和续期。关键是要建立证书过期监控、自动化续期和定期安全审计的完整流程,确保 HTTPS 服务的持续可用和安全。