feat(tls-fingerprint): 新增 TLS 指纹 Profile 数据库管理及代码质量优化

新增功能:
- 新增 TLS 指纹 Profile CRUD 管理(Ent schema + 迁移 + Admin API + 前端管理界面)
- 支持账号绑定数据库中的自定义 TLS Profile,或随机选择(profile_id=-1)
- HTTPUpstream.DoWithTLS 接口从 bool 改为 *tlsfingerprint.Profile,支持按账号指定 Profile
- AccountUsageService 注入 TLSFingerprintProfileService,统一 usage 场景与网关的 Profile 解析逻辑

代码优化:
- 删除已被 TLSFingerprintProfileService 完全取代的 registry.go 死代码(418 行)
- 提取 3 个 dialer 的重复 TLS 握手逻辑为 performTLSHandshake() 共用函数
- 修复 GetTLSFingerprintProfileID 缺少 json.Number 处理的 bug
- gateway_service.Forward 中 ResolveTLSProfile 从重试循环内重复调用改为预解析局部变量
- 删除冗余的 buildClientHelloSpec() 单行 wrapper 和 int64(e.ID) 无效转换
- tls_fingerprint_profile_cache.go 日志从 log.Printf 改为 slog 结构化日志
- dialer_capture_test.go 添加 //go:build integration 标签,防止 CI 失败
- 去重 TestProfileExpectation 类型至共享 test_types_test.go
- 修复 9 个测试文件缺少 tlsfingerprint import 的编译错误
- 修复 error_policy_integration_test.go 中 handleError 回调签名被错误替换的问题
This commit is contained in:
shaw
2026-03-27 14:23:28 +08:00
parent ef5c8e6839
commit 1854050df3
70 changed files with 8095 additions and 1037 deletions

View File

@@ -24,6 +24,7 @@ import dataManagementAPI from './dataManagement'
import apiKeysAPI from './apiKeys'
import scheduledTestsAPI from './scheduledTests'
import backupAPI from './backup'
import tlsFingerprintProfileAPI from './tlsFingerprintProfile'
/**
* Unified admin API object for convenient access
@@ -49,7 +50,8 @@ export const adminAPI = {
dataManagement: dataManagementAPI,
apiKeys: apiKeysAPI,
scheduledTests: scheduledTestsAPI,
backup: backupAPI
backup: backupAPI,
tlsFingerprintProfiles: tlsFingerprintProfileAPI
}
export {
@@ -73,7 +75,8 @@ export {
dataManagementAPI,
apiKeysAPI,
scheduledTestsAPI,
backupAPI
backupAPI,
tlsFingerprintProfileAPI
}
export default adminAPI
@@ -82,3 +85,4 @@ export default adminAPI
export type { BalanceHistoryItem } from './users'
export type { ErrorPassthroughRule, CreateRuleRequest, UpdateRuleRequest } from './errorPassthrough'
export type { BackupAgentHealth, DataManagementConfig } from './dataManagement'
export type { TLSFingerprintProfile, CreateProfileRequest, UpdateProfileRequest } from './tlsFingerprintProfile'

View File

@@ -0,0 +1,98 @@
/**
* Admin TLS Fingerprint Profile API endpoints
* Handles TLS fingerprint profile CRUD for administrators
*/
import { apiClient } from '../client'
/**
* TLS fingerprint profile interface
*/
export interface TLSFingerprintProfile {
id: number
name: string
description: string | null
enable_grease: boolean
cipher_suites: number[]
curves: number[]
point_formats: number[]
signature_algorithms: number[]
alpn_protocols: string[]
supported_versions: number[]
key_share_groups: number[]
psk_modes: number[]
extensions: number[]
created_at: string
updated_at: string
}
/**
* Create profile request
*/
export interface CreateProfileRequest {
name: string
description?: string | null
enable_grease?: boolean
cipher_suites?: number[]
curves?: number[]
point_formats?: number[]
signature_algorithms?: number[]
alpn_protocols?: string[]
supported_versions?: number[]
key_share_groups?: number[]
psk_modes?: number[]
extensions?: number[]
}
/**
* Update profile request
*/
export interface UpdateProfileRequest {
name?: string
description?: string | null
enable_grease?: boolean
cipher_suites?: number[]
curves?: number[]
point_formats?: number[]
signature_algorithms?: number[]
alpn_protocols?: string[]
supported_versions?: number[]
key_share_groups?: number[]
psk_modes?: number[]
extensions?: number[]
}
export async function list(): Promise<TLSFingerprintProfile[]> {
const { data } = await apiClient.get<TLSFingerprintProfile[]>('/admin/tls-fingerprint-profiles')
return data
}
export async function getById(id: number): Promise<TLSFingerprintProfile> {
const { data } = await apiClient.get<TLSFingerprintProfile>(`/admin/tls-fingerprint-profiles/${id}`)
return data
}
export async function create(profileData: CreateProfileRequest): Promise<TLSFingerprintProfile> {
const { data } = await apiClient.post<TLSFingerprintProfile>('/admin/tls-fingerprint-profiles', profileData)
return data
}
export async function update(id: number, updates: UpdateProfileRequest): Promise<TLSFingerprintProfile> {
const { data } = await apiClient.put<TLSFingerprintProfile>(`/admin/tls-fingerprint-profiles/${id}`, updates)
return data
}
export async function deleteProfile(id: number): Promise<{ message: string }> {
const { data } = await apiClient.delete<{ message: string }>(`/admin/tls-fingerprint-profiles/${id}`)
return data
}
export const tlsFingerprintProfileAPI = {
list,
getById,
create,
update,
delete: deleteProfile
}
export default tlsFingerprintProfileAPI