feat: aether-proxy TLS 双栈支持与自签名证书自动生成

- aether-proxy 新增 TLS 模块:自签名证书生成、TLS acceptor 构建、证书 SHA-256 指纹计算
- 代理服务器支持 HTTP+TLS 双栈模式,通过 peek 首字节区分 TLS ClientHello 与普通 HTTP
- 注册与心跳上报 tls_enabled 和 tls_cert_fingerprint 字段
- Python 侧 httpx 代理适配:TLS 代理使用 httpx.Proxy + CERT_NONE ssl_context
- ProxyNode 模型新增 tls_enabled/tls_cert_fingerprint 字段及对应迁移
This commit is contained in:
fawney19
2026-02-07 23:18:58 +08:00
parent 10bd14c223
commit 5384ffd403
17 changed files with 588 additions and 79 deletions

View File

@@ -50,6 +50,8 @@ def _node_to_dict(node: ProxyNode) -> dict[str, Any]:
"active_connections": node.active_connections,
"total_requests": node.total_requests,
"avg_latency_ms": node.avg_latency_ms,
"tls_enabled": bool(node.tls_enabled),
"tls_cert_fingerprint": node.tls_cert_fingerprint,
"remote_config": node.remote_config,
"config_version": node.config_version,
"created_at": node.created_at,
@@ -75,6 +77,12 @@ class ProxyNodeRegisterRequest(BaseModel):
total_requests: int | None = Field(None, ge=0, description="累计请求数")
avg_latency_ms: float | None = Field(None, ge=0, description="平均延迟(毫秒)")
# TLS
tls_enabled: bool = Field(False, description="是否启用 TLS 加密")
tls_cert_fingerprint: str | None = Field(
None, max_length=128, description="TLS 证书 SHA-256 指纹"
)
@field_validator("ip")
@classmethod
def validate_ip(cls, v: str) -> str:
@@ -275,6 +283,8 @@ class AdminRegisterProxyNodeAdapter(AdminApiAdapter):
node.status = ProxyNodeStatus.ONLINE
node.last_heartbeat_at = now
node.heartbeat_interval = req.heartbeat_interval
node.tls_enabled = req.tls_enabled
node.tls_cert_fingerprint = req.tls_cert_fingerprint
if req.active_connections is not None:
node.active_connections = req.active_connections
if req.total_requests is not None:
@@ -295,6 +305,8 @@ class AdminRegisterProxyNodeAdapter(AdminApiAdapter):
active_connections=req.active_connections or 0,
total_requests=req.total_requests or 0,
avg_latency_ms=req.avg_latency_ms,
tls_enabled=req.tls_enabled,
tls_cert_fingerprint=req.tls_cert_fingerprint,
created_at=now,
updated_at=now,
)
@@ -496,7 +508,9 @@ def _build_test_proxy_url(node: ProxyNode) -> str:
# aether-proxy: 使用 HMAC 认证构建代理 URL
from src.clients.http_client import _build_hmac_proxy_url
return _build_hmac_proxy_url(node.ip, node.port, node.id)
return _build_hmac_proxy_url(
node.ip, node.port, node.id, tls_enabled=bool(node.tls_enabled)
)
@dataclass
@@ -634,9 +648,14 @@ class AdminTestProxyNodeAdapter(AdminApiAdapter):
test_url = "https://1.1.1.1/cdn-cgi/trace"
start = _time.monotonic()
# TLS 代理需要 proxy_ssl_context
from src.clients.http_client import _make_proxy_param
proxy_param = _make_proxy_param(proxy_url)
try:
async with httpx.AsyncClient(
proxy=proxy_url,
proxy=proxy_param,
timeout=httpx.Timeout(15.0, connect=10.0),
) as client:
response = await client.get(test_url)