Files
Aether/_deprecated_py_src/utils/ssl_utils.py
fawney19 1d9c77522a refactor: 移除 Python 后端源码,全面迁移至 Rust gateway 架构
- 删除全部 Python 源码 (src/) 及 Alembic 迁移脚本,归档至 _deprecated_py_src/
- 重构 Rust gateway ai_pipeline: 拆分 planner/finalize 模块,新增 contracts/adaptation 层
- 重组 handlers 模块为 admin/public/proxy/internal/shared 子模块结构
- 新增 executor 模块,引入 Rust 原生数据库迁移 (aether-data/migrations)
- 简化 CI/Docker 构建流程,移除 base image 二级构建,统一为单一 app image
- 移除 Python 相关基础设施文件 (entrypoint.sh, gunicorn_conf.py, Dockerfile.base)
2026-04-03 16:26:16 +08:00

118 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
SSL 工具函数
提供统一的 SSL 上下文创建功能
"""
import ssl
from loguru import logger
def _create_default_ssl_context() -> ssl.SSLContext:
try:
import certifi
return ssl.create_default_context(cafile=certifi.where())
except ImportError:
return ssl.create_default_context()
try:
_SSL_CONTEXT = _create_default_ssl_context()
except Exception:
_SSL_CONTEXT = ssl.create_default_context()
_PROXY_SSL_CONTEXT: ssl.SSLContext | None = None
_PROFILE_SSL_CONTEXTS: dict[str, ssl.SSLContext] = {}
def get_ssl_context() -> ssl.SSLContext:
"""
获取 SSL 上下文
优先使用 certifi 证书包,如果未安装则使用系统默认证书。
返回模块级缓存的 SSL 上下文实例。
Returns:
ssl.SSLContext: SSL 上下文
"""
return _SSL_CONTEXT
def get_proxy_ssl_context(expected_fingerprint: str | None = None) -> ssl.SSLContext:
"""
获取用于代理连接的 SSL 上下文(连接 aether-proxy TLS 端口)
当前使用 CERT_NONE不验证证书因为 aether-proxy 使用自签名证书。
expected_fingerprint 参数预留供未来实现指纹校验。
Args:
expected_fingerprint: 预期的证书 SHA-256 指纹hex预留参数
Returns:
ssl.SSLContext: 代理专用 SSL 上下文
"""
global _PROXY_SSL_CONTEXT
if expected_fingerprint:
logger.warning("TLS 证书指纹校验尚未实现, fingerprint={} 被忽略", expected_fingerprint)
if _PROXY_SSL_CONTEXT is None:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
_PROXY_SSL_CONTEXT = ctx
# TODO: 实现基于 expected_fingerprint 的证书指纹校验
return _PROXY_SSL_CONTEXT
def _build_claude_code_ssl_context() -> ssl.SSLContext:
"""构建 Claude Code best-effort TLS 配置。
说明Python/OpenSSL 无法完整模拟 Node.js ClientHello。
这里仅做可控项的尽力对齐ALPN/TLS 版本/常见 cipher 偏好)。
"""
ctx = _create_default_ssl_context()
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
try:
ctx.maximum_version = ssl.TLSVersion.TLSv1_3
except Exception:
pass
try:
ctx.set_alpn_protocols(["h2", "http/1.1"])
except Exception:
pass
try:
ctx.set_ciphers(
"ECDHE-ECDSA-AES128-GCM-SHA256:"
"ECDHE-RSA-AES128-GCM-SHA256:"
"ECDHE-ECDSA-AES256-GCM-SHA384:"
"ECDHE-RSA-AES256-GCM-SHA384:"
"ECDHE-ECDSA-CHACHA20-POLY1305:"
"ECDHE-RSA-CHACHA20-POLY1305"
)
except Exception:
pass
return ctx
def get_ssl_context_for_profile(tls_profile: str | None = None) -> ssl.SSLContext:
"""按 profile 返回 SSL 上下文。"""
profile = str(tls_profile or "").strip().lower()
if not profile:
return get_ssl_context()
if profile in _PROFILE_SSL_CONTEXTS:
logger.debug("复用 TLS profile SSL context: {}", profile)
return _PROFILE_SSL_CONTEXTS[profile]
if profile == "claude_code_nodejs":
logger.info("启用 TLS profile: {}best-effort", profile)
ctx = _build_claude_code_ssl_context()
else:
logger.warning("未知 TLS profile: {},回退默认 SSL context", profile)
ctx = get_ssl_context()
_PROFILE_SSL_CONTEXTS[profile] = ctx
return ctx