SSL 安全协议
SSL/TLS 通过分层设计、混合加密体系和完备的握手协议,在 TCP 之上构建了一个安全通道:
- 加密层次:记录层加密 + 握手层协商
- 密码学基础:非对称加密(身份认证+密钥交换)+ 对称加密(数据加密)
- 前向安全:基于临时的会话密钥
- 性能优化:会话复用、False Start、TLS 1.3
- 演进方向:更快的握手、更强的安全、更好的隐私保护
SSL/TLS 位于应用层和传输层之间,对上层应用透明,应用协议无需修改。为 TCP 提供端到端的加密通道
code
┌─────────────────────────────────────────────────┐
│ 应用层 │
│ HTTP, FTP, SMTP, IMAP, DNS over TLS, etc. │
├─────────────────────────────────────────────────┤
│ SSL/TLS │ ← 安全层
├─────────────────────────────────────────────────┤
│ TCP │
├─────────────────────────────────────────────────┤
│ IP │
├─────────────────────────────────────────────────┤
│ 链路层 │
└─────────────────────────────────────────────────┘SSL/TLS 核心安全目标
机密性(Confidentiality)
完整性(Integrity)
- 防篡改:通过**消息认证码(MAC)**确保数据完整
- 防重放:通过序列号防止重放攻击
身份认证(Authentication)
- 服务器身份验证(必选)
- 客户端身份验证(可选)
- 双向认证(mTLS)
图表渲染中…
图表渲染中…
密码学原理解析
1. 非对称加密(密钥交换)
python
# RSA 密钥交换原理
# 客户端生成预主密钥,用服务器公钥加密
pre_master_secret = generate_random(48)
encrypted_pre_master = RSA_encrypt(
server_public_key,
pre_master_secret
)
# 服务器用私钥解密
pre_master_secret = RSA_decrypt(
server_private_key,
encrypted_pre_master
)2. 对称加密(数据加密)
code
应用数据加密流程:
1. 主密钥 → 生成6个密钥
- 客户端写MAC密钥
- 服务器写MAC密钥
- 客户端写加密密钥
- 服务器写加密密钥
- 客户端写IV
- 服务器写IV
2. 数据加密 = 加密算法(对称密钥, 应用数据 + MAC)3. Diffie-Hellman 密钥交换
python
# DH 密钥交换数学原理
# 公共参数: 大素数p, 生成元g
# 客户端
client_private_key = random_int(1, p-1)
client_public_key = (g^client_private_key) mod p
# 服务器
server_private_key = random_int(1, p-1)
server_public_key = (g^server_private_key) mod p
# 交换公钥后,双方计算共享密钥
client_shared_secret = (server_public_key^client_private_key) mod p
server_shared_secret = (client_public_key^server_private_key) mod p
# client_shared_secret == server_shared_secret记录层协议(Record Protocol)
数据封装格式:
code
┌─────────────────────────────────────────┐
│ TLS Record Layer (应用数据) │
├──────────┬──────────┬────────┬─────────┤
│ 类型 │ 版本 │ 长度 │ 数据 │
│ 1字节 │ 2字节 │ 2字节 │ 长度可变 │
├──────────┼──────────┼────────┼─────────┤
│ 0x16 │ 0x0303 │ 0x00A0 │ ... │ ← 握手记录
│ 0x17 │ 0x0303 │ 0x1000 │ ... │ ← 应用数据记录
│ 0x15 │ 0x0303 │ 0x0002 │ ... │ ← 警报记录
└──────────┴──────────┴────────┴─────────┘数据分片与加密:
图表渲染中…
SSL/TLS 的 Nginx 安全配置示例
nginx
server {
listen 443 ssl http2;
# 证书配置
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# 协议版本
ssl_protocols TLSv1.2 TLSv1.3;
# 密码套件(TLS 1.2+1.3)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
# 前向安全
ssl_ecdh_curve X25519:secp384r1;
# 会话复用
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets on;
# 安全头部
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/ca-bundle.crt;
}python2-certbot-nginx 自动配置 SSL
Certbot 是个免费、开源的工具,用于自动化在网站上启用和管理 HTTPS 证书的过程,由 Electronic Frontier Foundation (EFF) 开发。python2-certbot-nginx 是 Certbot 的 Nginx 插件,可以自动配置 Nginx 并管理 SSL 证书
nginx
server {
server_name nginx.zhangzhengyang.com
listen 9099
location / {
alias /var/www/html/index.html;
}
}在 CentOS 7.9 上安装 Certbot
bash
# 安装 EPEL 仓库
sudo yum install -y epel-release
# 安装 Certbot 和 Nginx 插件
sudo yum install -y certbot python2-certbot-nginx
# 验证安装
certbot --version获取和管理证书
自动获取和配置证书
bash
# 自动获取证书并配置 Nginx,如果要选择,可以选择 1
sudo certbot --nginx -d example.com -d www.example.com
# 交互式模式
sudo certbot --nginx
# 保存配置时选择重定向 HTTP 到 HTTPS可以指定 nginx 配置文件的目录:
--nginx-server-root:指定 Nginx 主配置目录(通常是 /etc/nginx)--nginx-vhost-root:指定虚拟主机配置文件目录(通常是 /etc/nginx/sites-available)
bash
sudo certbot --nginx \
--nginx-server-root /etc/nginx \
--nginx-vhost-root /etc/nginx/sites-available \
-d example.com \
-d www.example.com证书续期
手动续期
bash
# 测试续期(不会实际续期)
sudo certbot renew --dry-run
# 手动续期所有证书
sudo certbot renew
# 续期特定证书
sudo certbot renew --cert-name example.com自动续期
bash
# 创建 cron 任务
echo "0 0,12 * * * root /usr/bin/certbot renew --quiet" | sudo tee /etc/cron.d/certbot-renew
# 或者使用 systemd timer
sudo systemctl enable certbot-renew.timer
sudo systemctl start certbot-renew.timerCertbot 生成的 Nginx 配置示例
当使用 certbot --nginx 命令时,Certbot 会自动修改 Nginx 配置,添加以下内容:
nginx
server {
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
# 以下是 Certbot 添加的内容
# HTTPS 重定向配置
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
# HTTP 到 HTTPS 重定向
if ($host = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
}
server {
if ($host = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}SSL 参数配置
Certbot 使用 /etc/letsencrypt/options-ssl-nginx.conf 文件来配置 SSL 参数。这个文件的内容通常如下:
nginx
# SSL 协议版本
ssl_protocols TLSv1.2 TLSv1.3;
# 密码套件
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-S384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# 会话缓存
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
# 前向安全
ssl_ecdh_curve X25519:secp256k1:secp384r1;
# 安全头部
resolver 8.8.8.8 8.8.4.4;证书文件位置
Let's Encrypt 证书通常存储在以下位置:
bash
# 证书目录结构
/etc/letsencrypt/live/example.com/
├── cert.pem # 服务器证书
├── chain.pem # 中间证书
├── fullchain.pem # 证书链(cert.pem + chain.pem)
└── privkey.pem # 私钥
# 实际文件存储在 archive 目录,live 目录中有符号链接
/etc/letsencrypt/archive/example.com/常用 Certbot 命令
bash
# 列出所有证书
sudo certbot certificates
# 删除证书
sudo certbot delete --cert-name example.com
# 撤销证书
sudo certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pem
# 设置默认续期选项
sudo certbot register --email admin@example.com --agree-tos --no-eff-email
# 测试 Nginx 配置
sudo certbot --nginx --dry-run -d example.com
# 指定不同的证书存储目录
sudo certbot --nginx --config-dir /opt/certbot -d example.com高级配置
使用 DNS 验证(通配符证书)
bash
# 安装 DNS 插件(以 Cloudflare 为例)
sudo yum install -y python2-certbot-dns-cloudflare
# 创建 Cloudflare API 凭据文件
sudo mkdir -p /etc/letsencrypt
sudo tee /etc/letsencrypt/cloudflare.ini << 'EOF'
dns_cloudflare_api_token = your_api_token_here
EOF
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
# 获取通配符证书
sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d example.com -d "*.example.com"自定义 SSL 参数
bash
# 编辑 Certbot 的 SSL 参数文件
sudo nano /etc/letsencrypt/options-ssl-nginx.conf
# 添加自定义参数
ssl_dhparam /etc/letsencrypt/dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;多域名证书
bash
# 为多个域名获取单个证书
sudo certbot --nginx -d example.com -d www.example.com -d blog.example.com -d shop.example.com故障排除
证书获取失败
bash
# 检查 DNS 解析
dig +short example.com
# 检查防火墙设置
sudo firewall-cmd --list-all
# 检查端口 80 是否开放
sudo netstat -tlnp | grep :80
# 暂时停止 Nginx 并尝试获取证书
sudo systemctl stop nginx
sudo certbot certonly --standalone -d example.com
sudo systemctl start nginxNginx 配置错误
bash
# 测试 Nginx 配置
sudo nginx -t
# 检查 Nginx 日志
sudo tail -f /var/log/nginx/error.log
# 恢复备份的 Nginx 配置
sudo cp /etc/nginx/nginx.conf.backup /etc/nginx/nginx.conf
sudo nginx -s reload证书续期失败
bash
# 查看续期日志
sudo journalctl -u certbot
sudo cat /var/log/letsencrypt/letsencrypt.log
# 强制续期
sudo certbot renew --force-renewal
# 重新获取证书
sudo certbot delete --cert-name example.com
sudo certbot --nginx -d example.com与现有 Nginx 配置集成
如果你已有 Nginx 配置,可以这样集成 Certbot:
bash
# 1. 备份现有配置
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
sudo cp -r /etc/nginx/conf.d /etc/nginx/conf.d.backup
# 2. 获取证书(不修改配置)
sudo certbot certonly --nginx -d example.com
# 3. 手动修改 Nginx 配置
sudo nano /etc/nginx/conf.d/example.conf
# 4. 添加 SSL 配置
server {
listen 80;
server_name example.com;
# 重定向到 HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
root /var/www/example.com;
index index.html;
# SSL 配置
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# 其他配置...
}自动化部署脚本
创建自动化部署脚本 deploy-ssl.sh:
bash
#!/bin/bash
# 自动 SSL 部署脚本
DOMAIN=$1
EMAIL=$2
WEBROOT="/var/www/${DOMAIN}"
# 检查参数
if [ -z "$DOMAIN" ] || [ -z "$EMAIL" ]; then
echo "用法: $0 域名 邮箱"
exit 1
fi
# 创建网站目录
sudo mkdir -p $WEBROOT
sudo chown -R nginx:nginx $WEBROOT
sudo chmod -R 755 $WEBROOT
# 创建默认页面
echo "<html><body><h1>It works!</h1><p>SSL 自动配置成功</p></body></html>" | sudo tee $WEBROOT/index.html
# 获取证书
echo "获取 SSL 证书..."
sudo certbot --nginx -d $DOMAIN -d www.$DOMAIN --email $EMAIL --agree-tos --no-eff-email --redirect
# 设置自动续期
echo "0 0,12 * * * root /usr/bin/certbot renew --quiet" | sudo tee /etc/cron.d/certbot-renew
echo "SSL 配置完成!"
echo "网站: https://$DOMAIN"
echo "证书位置: /etc/letsencrypt/live/$DOMAIN/"使用脚本:
bash
chmod +x deploy-ssl.sh
sudo ./deploy-ssl.sh example.com admin@example.com