什么是OpenSSL
OpenSSL是一个功能强大的安全套接字层密码库,诞生于1998年——那时候Google还在车库里,而OpenSSL已经在默默守护互联网安全了。
它能干啥:
| 功能模块 | 作用 | 人话翻译 |
|---|---|---|
| 密码算法库 | RSA、AES、SHA等加密算法 | 把数据变成乱码 |
| SSL/TLS协议库 | 实现安全通信协议 | 让数据传输不裸奔 |
| 命令行工具 | 各种证书、密钥操作 | 运维人员的瑞士军刀 |
OpenSSL的江湖地位:
全球90%以上的HTTPS网站 ──使用──▶ OpenSSL没错,你每天访问的淘宝、微信、银行网站,背后大概率都有OpenSSL在保驾护航。它就像互联网的空气——平时感觉不到,但没有它你会窒息。
核心概念速通
在开始敲命令之前,先搞清楚几个概念,不然后面会一脸懵:
┌─────────────────────────────────────────────────────────────┐
│ 证书信任链 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ │ 根证书CA │ ◀── 浏览器/系统内置信任 │
│ │ (Root CA) │ │
│ └──────┬───────┘ │
│ │ 签发 │
│ ▼ │
│ ┌──────────────┐ │
│ │ 中间证书CA │ ◀── 由根CA签发 │
│ │(Intermediate)│ │
│ └──────┬───────┘ │
│ │ 签发 │
│ ▼ │
│ ┌──────────────┐ │
│ │ 服务器证书 │ ◀── 你的网站用的就是这个 │
│ │ (Server Cert)│ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘关键术语:
| 术语 | 英文 | 一句话解释 |
|---|---|---|
| 私钥 | Private Key | 绝对不能泄露的钥匙,用来解密和签名 |
| 公钥 | Public Key | 可以公开的钥匙,用来加密和验签 |
| 证书 | Certificate | 公钥 + 身份信息 + CA签名,相当于"数字身份证" |
| CSR | Certificate Signing Request | 证书签名请求,找CA申请证书用的 |
| CA | Certificate Authority | 证书颁发机构,负责"发身份证"的权威部门 |
| PEM | Privacy Enhanced Mail | 一种证书编码格式,Base64文本,以-----BEGIN开头 |
| DER | Distinguished Encoding Rules | 二进制证书格式 |
| PKCS#12/PFX | - | 把证书和私钥打包在一起的格式,常见于Windows |
第一章:生成密钥对
生成RSA私钥
# 方式1:生成2048位RSA私钥(推荐)
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
# 方式2:老命令,效果一样
openssl genrsa -out private_key.pem 2048
# 方式3:生成带密码保护的私钥(更安全)
openssl genpkey -algorithm RSA -out private_key.pem -aes256 -pkeyopt rsa_keygen_bits:2048
# 会提示你输入密码,以后每次使用私钥都要输入💡 2048 vs 4096:2048位目前够用,4096更安全但更慢。就像门锁,普通防盗门够用了,没必要装银行金库的门。
从私钥提取公钥
openssl rsa -pubout -in private_key.pem -out public_key.pem查看密钥信息
# 查看私钥详情(会显示模数、指数等数学参数)
openssl rsa -in private_key.pem -text -noout
# 查看公钥详情
openssl rsa -pubin -in public_key.pem -text -noout生成ECC密钥(更现代的选择)
# ECC比RSA更短更快,256位ECC ≈ 3072位RSA的安全性
openssl ecparam -genkey -name prime256v1 -out ec_private.pem
# 提取公钥
openssl ec -in ec_private.pem -pubout -out ec_public.pem第二章:创建自签名证书
自签名证书就是"自己给自己发身份证",浏览器不信任,但开发测试够用了。
一步到位生成证书
# 生成私钥 + 自签名证书,一条命令搞定
openssl req -x509 -newkey rsa:2048 -keyout private_key.pem -out cert.pem -days 365 -nodes
# 参数解释:
# -x509 : 生成自签名证书(不是CSR)
# -newkey : 同时生成新私钥
# -keyout : 私钥输出文件
# -out : 证书输出文件
# -days 365 : 有效期365天
# -nodes : 私钥不加密(No DES),生产环境别用这个交互式填写证书信息
运行上面的命令后,会让你填一堆信息:
Country Name (2 letter code) [AU]: CN
State or Province Name (full name) [Some-State]: Guangdong
Locality Name (eg, city) []: Shenzhen
Organization Name (eg, company) []: My Company
Organizational Unit Name (eg, section) []: IT Department
Common Name (e.g. server FQDN or YOUR name) []: localhost
Email Address []: admin@example.com⚠️ Common Name很重要:这个要填你的域名,比如www.example.com,填错了浏览器会报证书不匹配。非交互式生成(脚本党福音)
openssl req -x509 -newkey rsa:2048 \
-keyout private_key.pem \
-out cert.pem \
-days 365 \
-nodes \
-subj "/C=CN/ST=Guangdong/L=Shenzhen/O=MyCompany/CN=localhost"生成带SAN的证书(支持多域名)
现代浏览器要求证书必须有SAN(Subject Alternative Name),不然会报错:
# 创建配置文件
cat > san.cnf << EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[dn]
C = CN
ST = Guangdong
L = Shenzhen
O = MyCompany
CN = localhost
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = *.localhost
DNS.3 = myapp.local
IP.1 = 127.0.0.1
IP.2 = 192.168.1.100
EOF
# 生成证书
openssl req -x509 -newkey rsa:2048 \
-keyout private_key.pem \
-out cert.pem \
-days 365 \
-nodes \
-config san.cnf \
-extensions req_ext第三章:证书的日常操作
查看证书信息
# 查看证书详情(最常用)
openssl x509 -in cert.pem -text -noout
# 只看有效期
openssl x509 -in cert.pem -dates -noout
# 只看主题和颁发者
openssl x509 -in cert.pem -subject -issuer -noout
# 查看证书指纹
openssl x509 -in cert.pem -fingerprint -sha256 -noout验证证书
# 验证证书链
openssl verify -CAfile ca_bundle.pem cert.pem
# 检查证书和私钥是否匹配
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in private_key.pem | openssl md5
# 两个MD5值相同说明匹配格式转换大全
证书格式转换是运维的日常噩梦,这里整理一份速查表:
# PEM → DER
openssl x509 -in cert.pem -outform DER -out cert.der
# DER → PEM
openssl x509 -in cert.der -inform DER -outform PEM -out cert.pem
# PEM → PKCS#12(把证书和私钥打包,常用于导入Windows/Java)
openssl pkcs12 -export -out cert.pfx -inkey private_key.pem -in cert.pem -certfile ca_bundle.pem
# PKCS#12 → PEM(从pfx中提取)
openssl pkcs12 -in cert.pfx -out cert.pem -nodes
# 提取证书链中的各个证书
openssl crl2pkcs7 -nocrl -certfile chain.pem | openssl pkcs7 -print_certs -out all_certs.pem检查远程服务器证书
# 查看网站证书(神器命令!)
echo | openssl s_client -connect www.baidu.com:443 -servername www.baidu.com 2>/dev/null | openssl x509 -text -noout
# 只看证书有效期
echo | openssl s_client -connect www.baidu.com:443 2>/dev/null | openssl x509 -dates -noout
# 检查证书链完整性
openssl s_client -connect www.baidu.com:443 -showcerts第四章:SSL/TLS通信测试
启动测试服务器
# 启动HTTPS服务器(监听4433端口)
openssl s_server -cert cert.pem -key private_key.pem -port 4433 -www
# -www参数会返回一个简单的HTTP响应,可以用浏览器访问 https://localhost:4433测试客户端连接
# 连接服务器
openssl s_client -connect localhost:4433
# 连接时指定SNI(Server Name Indication)
openssl s_client -connect localhost:4433 -servername mysite.com
# 测试特定TLS版本
openssl s_client -connect localhost:4433 -tls1_2
openssl s_client -connect localhost:4433 -tls1_3
# 查看支持的加密套件
openssl s_client -connect localhost:4433 -cipher 'ALL' 2>/dev/null | grep -E 'Cipher|Protocol'压测SSL性能
# 测试RSA签名性能
openssl speed rsa2048
# 测试AES加密性能
openssl speed aes-256-gcm
# 测试完整握手性能
openssl s_time -connect localhost:4433 -new -time 10第五章:Let's Encrypt —— 免费证书的救星
"以前SSL证书要花几千块,现在Let's Encrypt让它白菜价。" —— 全球站长
Let's Encrypt是什么
Let's Encrypt是一个免费、自动化、开放的证书颁发机构(CA),由互联网安全研究小组(ISRG)运营。
优点:
- 🆓 完全免费
- 🤖 自动化续期
- ⚡ 签发速度快(几秒钟)
- 🌍 被所有主流浏览器信任
限制:
- 证书有效期只有90天(必须自动续期)
- 只支持域名验证(DV),不支持企业验证(OV/EV)
- 每个域名每周最多签发50张证书
证书申请流程
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.安装Certbot │────▶│ 2.验证域名所有权│────▶│ 3.获取证书 │
└─────────────┘ └─────────────┘ └─────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
HTTP-01验证 DNS-01验证 TLS-ALPN-01验证
(放文件到网站) (添加DNS记录) (TLS握手验证)安装Certbot
# Ubuntu/Debian
sudo apt update
sudo apt install certbot
# CentOS/RHEL
sudo yum install epel-release
sudo yum install certbot
# macOS
brew install certbot
# 或者用pip(通用)
pip install certbot方式一:Standalone模式(最简单)
适合没有Web服务器或者可以临时停掉的情况:
# 申请证书(会临时启动一个Web服务器在80端口)
sudo certbot certonly --standalone -d example.com -d www.example.com
# 证书会保存在:
# /etc/letsencrypt/live/example.com/fullchain.pem (证书链)
# /etc/letsencrypt/live/example.com/privkey.pem (私钥)方式二:Webroot模式(不停服务)
如果Web服务器正在运行,不想停:
# 指定网站根目录,Certbot会在里面放验证文件
sudo certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com需要确保Web服务器能响应 http://example.com/.well-known/acme-challenge/ 路径。
方式三:DNS验证(支持通配符)
申请通配符证书(*.example.com)必须用DNS验证:
sudo certbot certonly --manual --preferred-challenges dns -d "*.example.com" -d example.com运行后会提示你添加一条TXT记录:
Please deploy a DNS TXT record under the name:
_acme-challenge.example.com
with the following value:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx去域名DNS管理后台添加这条记录,然后继续。
方式四:配合Nginx自动配置
# 自动配置Nginx(最省心)
sudo certbot --nginx -d example.com -d www.example.com
# Certbot会自动:
# 1. 申请证书
# 2. 修改Nginx配置
# 3. 配置自动跳转HTTPS方式五:配合Apache
sudo certbot --apache -d example.com -d www.example.com自动续期
Let's Encrypt证书90天过期,必须设置自动续期:
# 测试续期(不会真的续)
sudo certbot renew --dry-run
# 手动续期
sudo certbot renew
# 设置定时任务自动续期
# 方式1:Certbot自带的timer(推荐)
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
# 方式2:crontab
# 每天凌晨3点检查并续期
echo "0 3 * * * root certbot renew --quiet --post-hook 'systemctl reload nginx'" | sudo tee /etc/cron.d/certbot-renewNginx配置示例
server {
listen 80;
server_name example.com www.example.com;
# 强制跳转HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# Let's Encrypt证书
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.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:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS(可选,开启后浏览器会强制HTTPS)
add_header Strict-Transport-Security "max-age=63072000" always;
# ... 其他配置
}acme.sh —— 更轻量的替代品
如果觉得Certbot太重,可以用acme.sh:
# 安装
curl https://get.acme.sh | sh
# 申请证书(DNS API方式,以Cloudflare为例)
export CF_Key="你的Cloudflare API Key"
export CF_Email="你的邮箱"
acme.sh --issue --dns dns_cf -d example.com -d "*.example.com"
# 安装证书到Nginx
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/example.com.key \
--fullchain-file /etc/nginx/ssl/example.com.pem \
--reloadcmd "systemctl reload nginx"第六章:常见踩坑与排错
坑1:证书链不完整
症状:浏览器报"证书不受信任",但证书明明是正规CA签发的。
原因:服务器只配了服务器证书,没配中间证书。
解决:
# 把中间证书和服务器证书合并
cat server.pem intermediate.pem > fullchain.pem
# Nginx配置使用fullchain
ssl_certificate /path/to/fullchain.pem;坑2:私钥和证书不匹配
症状:Nginx启动报错 SSL_CTX_use_PrivateKey_file failed
诊断:
# 检查MD5是否一致
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in key.pem | openssl md5解决:找到正确配对的私钥和证书。
坑3:证书过期
预防:
# 写个脚本检查证书有效期
#!/bin/bash
DOMAIN=$1
EXPIRY=$(echo | openssl s_client -connect $DOMAIN:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
echo "$DOMAIN 证书还有 $DAYS_LEFT 天过期"
if [ $DAYS_LEFT -lt 30 ]; then
echo "⚠️ 警告:即将过期!"
fi坑4:SNI问题
症状:同一IP部署多个HTTPS站点,访问时返回错误的证书。
原因:客户端不支持SNI,或者服务器SNI配置错误。
检查:
# 指定SNI访问
openssl s_client -connect IP:443 -servername www.example.com坑5:TLS版本过低
症状:旧浏览器能访问,新浏览器不行(或反过来)。
诊断:
# 测试支持的TLS版本
for v in ssl3 tls1 tls1_1 tls1_2 tls1_3; do
echo -n "$v: "
timeout 2 openssl s_client -connect localhost:443 -$v 2>/dev/null | grep -q "Cipher" && echo "支持" || echo "不支持"
done建议配置:
# 只启用TLS 1.2和1.3(2024年的最佳实践)
ssl_protocols TLSv1.2 TLSv1.3;常用命令速查表
| 场景 | 命令 |
|---|---|
| 生成RSA私钥 | openssl genrsa -out key.pem 2048 |
| 生成自签名证书 | openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes |
| 查看证书信息 | openssl x509 -in cert.pem -text -noout |
| 查看证书有效期 | openssl x509 -in cert.pem -dates -noout |
| 验证证书链 | openssl verify -CAfile ca.pem cert.pem |
| 检查远程证书 | openssl s_client -connect host:443 -servername host |
| PEM转PFX | openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem |
| PFX转PEM | openssl pkcs12 -in cert.pfx -out cert.pem -nodes |
| 生成CSR | openssl req -new -key key.pem -out csr.pem |
| 测试SSL服务器 | openssl s_server -cert cert.pem -key key.pem -port 4433 |
| 申请Let's Encrypt | certbot certonly --standalone -d example.com |
| 续期Let's Encrypt | certbot renew |
总结
OpenSSL知识图谱
│
├── 密钥管理
│ ├── RSA密钥对生成
│ ├── ECC密钥对生成
│ └── 密钥格式转换
│
├── 证书操作
│ ├── 自签名证书
│ ├── CSR生成
│ ├── 证书查看/验证
│ └── 格式转换(PEM/DER/PFX)
│
├── SSL/TLS测试
│ ├── s_server/s_client
│ ├── 远程证书检查
│ └── 性能测试
│
└── Let's Encrypt
├── Certbot安装
├── 多种验证方式
├── 自动续期
└── Web服务器集成从入门到放弃?不,是从入门到真香!
掌握OpenSSL,你就掌握了互联网安全的基础。虽然命令多、参数杂、格式乱,但一旦熟练了,你就是团队里那个"证书有问题找他准没错"的人。
参考资料
- 🔗 OpenSSL官方文档
- 🔗 Let's Encrypt官网
- 🔗 Certbot文档
- 🔗 SSL Labs测试工具(测试你的HTTPS配置评分)
- 🔗 Mozilla SSL配置生成器(自动生成最佳SSL配置)
- 📖 《图解密码技术》
- 📖 《HTTPS权威指南》
HTTP是在互联网上裸奔,HTTPS是穿了衣服。OpenSSL就是那个裁缝。 👔