Ubuntu 上 Python 的 SSL 证书配置指南
一 准备与系统检查
- 更新系统并安装常用工具:sudo apt update && sudo apt install -y ca-certificates python3-pip python3-venv
- 确保系统根证书是最新的:sudo update-ca-certificates(Python 的 requests 等库会依赖系统的 CA 证书存储进行验证)
- 如使用云服务,确认安全组与防火墙已放行 TCP 443;本机可用 nc 检测:nc -w 3 -vz your_domain_or_ip 443
二 作为服务器在 Python 内启用 HTTPS
- 自签名证书(开发环境)
- 生成证书与密钥:
- openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt
- 在 Flask 中启用:
- from flask import Flask
app = Flask(name)
@app.route(“/”)
def home(): return “OK”
context = (“/path/server.crt”, “/path/server.key”)
app.run(host=“0.0.0.0”, port=443, ssl_context=context)
- 注意:监听 443 通常需要管理员权限;开发可用端口如 8443 替代,或 sudo 运行
- 正式证书(Let’s Encrypt)
- 安装与签发:sudo apt install certbot python3-certbot-nginx;sudo certbot --nginx -d yourdomain.com
- Certbot 会自动修改 Nginx 配置并部署证书,适合生产环境
- 原生 SSL 服务器示例(不依赖 Web 框架)
- import ssl, socket
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile=“server.crt”, keyfile=“server.key”)
with socket.create_server((‘0.0.0.0’, 443), ssl_context=context) as s:
while True:
conn, addr = s.accept()
with conn:
data = conn.recv(1024)
conn.sendall(data)
三 作为客户端发起 HTTPS 请求时配置证书验证
- 使用 requests 验证服务器证书
- 默认验证:requests.get(“https://example.com”, verify=True)
- 自定义 CA 证书包:requests.get(“https://example.com”, verify=“/path/ca-bundle.crt”)
- 不验证(仅测试):requests.get(“https://example.com”, verify=False)(生产禁用)
- 使用标准库 ssl 创建客户端上下文
- context = ssl.create_default_context(ssl.PROTOCOL_TLS_CLIENT)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_verify_locations(“/path/ca-bundle.crt”)
with socket.create_connection((“example.com”, 443)) as sock:
with context.wrap_socket(sock, server_hostname=“example.com”) as ssock:
print(ssock.version())
四 使用 Nginx 反向代理部署生产环境 HTTPS(推荐)
- 证书路径(Let’s Encrypt 常见路径)
- /etc/letsencrypt/live/yourdomain.com/fullchain.pem
- /etc/letsencrypt/live/yourdomain.com/privkey.pem
- 示例配置
- server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
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;
}
}
- 重启:sudo systemctl restart nginx
- 优势:证书集中在网关层管理,便于启用 HTTP→HTTPS 跳转、TLS 1.2/1.3、HSTS 等安全策略
五 常见问题与排查
- 证书未生效或浏览器报错
- 检查安全组/防火墙是否放行 443;证书绑定的域名是否与访问域名一致(含通配符匹配规则);证书文件与私钥是否匹配且为完整链;修改服务后是否重启;若接入 CDN/SLB/WAF,需在对应产品处安装证书
- Python 报 FileNotFoundError
- ssl_context 中证书/私钥路径错误或文件不存在,使用绝对路径并确认权限
- 客户端证书验证失败
- 更新系统 CA 证书:sudo update-ca-certificates;或在代码中显式指定 CA 包路径
- ERR_SSL_PROTOCOL_ERROR 或握手失败
- 证书链不完整、协议/套件不兼容、端口不对或服务未在该端口监听
- 自签名证书不被信任
- 开发环境可将自签名 CA 加入受信任存储,或在客户端请求时指定 verify=/path/ca.crt