feat: 从 main 分支迁移 Claude 指纹常量和实例级隔离配置
将 main 分支的 Claude/Anthropic 相关逆向工作迁移到 codex 分支: - claude/constants.go: 添加 4 个新 Beta 常量 + 版本升级至 2.1.84/0.74.0 - config.go: 添加 InstanceSalt 和 FingerprintDefaultsConfig 配置 - identity_service: 版本升级 + instanceSalt 支持 + ApplyDefaultFingerprintOverrides - wire_gen.go: 初始化指纹覆盖 + 使用 NewIdentityServiceWithSalt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1dfd974432
commit
8eb2bbcb20
@ -12,6 +12,7 @@ import (
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
"github.com/Wei-Shaw/sub2api/internal/handler"
|
||||
"github.com/Wei-Shaw/sub2api/internal/handler/admin"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/claude"
|
||||
"github.com/Wei-Shaw/sub2api/internal/repository"
|
||||
"github.com/Wei-Shaw/sub2api/internal/server"
|
||||
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||
@ -35,6 +36,10 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 应用实例级指纹覆盖(不同 sub2api 实例可设不同的默认版本号)
|
||||
fpd := configConfig.Gateway.FingerprintDefaults
|
||||
claude.ApplyFingerprintOverrides(fpd.ClaudeCLIVersion, fpd.StainlessPackageVersion, fpd.StainlessRuntimeVersion, fpd.StainlessOS, fpd.StainlessArch)
|
||||
service.ApplyDefaultFingerprintOverrides(fpd.ClaudeCLIVersion, fpd.StainlessPackageVersion, fpd.StainlessRuntimeVersion, fpd.StainlessOS, fpd.StainlessArch)
|
||||
client, err := repository.ProvideEnt(configConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -171,7 +176,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
return nil, err
|
||||
}
|
||||
billingService := service.NewBillingService(configConfig, pricingService)
|
||||
identityService := service.NewIdentityService(identityCache)
|
||||
identityService := service.NewIdentityServiceWithSalt(identityCache, configConfig.Gateway.InstanceSalt)
|
||||
deferredService := service.ProvideDeferredService(accountRepository, timingWheelService)
|
||||
claudeTokenProvider := service.ProvideClaudeTokenProvider(accountRepository, geminiTokenCache, oAuthService, oauthRefreshAPI)
|
||||
digestSessionStore := service.NewDigestSessionStore()
|
||||
|
||||
@ -456,6 +456,18 @@ type GatewayConfig struct {
|
||||
// TLSFingerprint: TLS指纹伪装配置
|
||||
TLSFingerprint TLSFingerprintConfig `mapstructure:"tls_fingerprint"`
|
||||
|
||||
// InstanceSalt: 实例级隔离盐值
|
||||
// 用于 user_id 重写和 session hash 的种子混淆,
|
||||
// 不同 sub2api 实例设置不同的 salt,确保相同输入产生不同输出。
|
||||
// 为空时使用默认行为(无 salt),建议生产环境必须配置。
|
||||
// 生成方法: openssl rand -hex 32
|
||||
InstanceSalt string `mapstructure:"instance_salt"`
|
||||
|
||||
// FingerprintDefaults: 指纹默认值覆盖
|
||||
// 允许每个实例配置不同的 Claude CLI 版本号,与其他 sub2api 实例区分。
|
||||
// 为空时使用代码内置默认值。
|
||||
FingerprintDefaults FingerprintDefaultsConfig `mapstructure:"fingerprint_defaults"`
|
||||
|
||||
// UsageRecord: 使用量记录异步队列配置(有界队列 + 固定 worker)
|
||||
UsageRecord GatewayUsageRecordConfig `mapstructure:"usage_record"`
|
||||
|
||||
@ -685,6 +697,23 @@ type TLSProfileConfig struct {
|
||||
Extensions []uint16 `mapstructure:"extensions"`
|
||||
}
|
||||
|
||||
// FingerprintDefaultsConfig 指纹默认值配置
|
||||
// 允许每个 sub2api 实例设置不同的默认指纹值,与其他实例区分。
|
||||
// 所有字段为空时使用代码内置默认值。
|
||||
type FingerprintDefaultsConfig struct {
|
||||
// ClaudeCLIVersion: Claude CLI 版本号(如 "2.1.81"),
|
||||
// 最终 User-Agent 为 "claude-cli/{version} (external, cli)"
|
||||
ClaudeCLIVersion string `mapstructure:"claude_cli_version"`
|
||||
// StainlessPackageVersion: @anthropic-ai/sdk 版本(如 "0.80.0")
|
||||
StainlessPackageVersion string `mapstructure:"stainless_package_version"`
|
||||
// StainlessRuntimeVersion: Node.js 版本(如 "v24.13.0")
|
||||
StainlessRuntimeVersion string `mapstructure:"stainless_runtime_version"`
|
||||
// StainlessOS: 操作系统(如 "Linux", "Darwin")
|
||||
StainlessOS string `mapstructure:"stainless_os"`
|
||||
// StainlessArch: 架构(如 "arm64", "x64")
|
||||
StainlessArch string `mapstructure:"stainless_arch"`
|
||||
}
|
||||
|
||||
// GatewaySchedulingConfig accounts scheduling configuration.
|
||||
type GatewaySchedulingConfig struct {
|
||||
// 粘性会话排队配置
|
||||
|
||||
@ -12,6 +12,10 @@ const (
|
||||
BetaTokenCounting = "token-counting-2024-11-01"
|
||||
BetaContext1M = "context-1m-2025-08-07"
|
||||
BetaFastMode = "fast-mode-2026-02-01"
|
||||
BetaRedactThinking = "redact-thinking-2026-02-12"
|
||||
BetaContextManagement = "context-management-2025-06-27"
|
||||
BetaPromptCachingScope = "prompt-caching-scope-2026-01-05"
|
||||
BetaEffort = "effort-2025-11-24"
|
||||
)
|
||||
|
||||
// DroppedBetas 是转发时需要从 anthropic-beta header 中移除的 beta token 列表。
|
||||
@ -48,19 +52,43 @@ const APIKeyHaikuBetaHeader = BetaInterleavedThinking
|
||||
var DefaultHeaders = map[string]string{
|
||||
// Keep these in sync with recent Claude CLI traffic to reduce the chance
|
||||
// that Claude Code-scoped OAuth credentials are rejected as "non-CLI" usage.
|
||||
"User-Agent": "claude-cli/2.1.22 (external, cli)",
|
||||
"User-Agent": "claude-cli/2.1.84 (external, cli)",
|
||||
"X-Stainless-Lang": "js",
|
||||
"X-Stainless-Package-Version": "0.70.0",
|
||||
"X-Stainless-OS": "Linux",
|
||||
"X-Stainless-Package-Version": "0.74.0",
|
||||
"X-Stainless-OS": "MacOS",
|
||||
"X-Stainless-Arch": "arm64",
|
||||
"X-Stainless-Runtime": "node",
|
||||
"X-Stainless-Runtime-Version": "v24.13.0",
|
||||
"X-Stainless-Runtime-Version": "v24.3.0",
|
||||
"X-Stainless-Retry-Count": "0",
|
||||
"X-Stainless-Timeout": "600",
|
||||
"X-App": "cli",
|
||||
"Anthropic-Dangerous-Direct-Browser-Access": "true",
|
||||
}
|
||||
|
||||
// ApplyFingerprintOverrides 用配置覆盖默认指纹值(每个实例可设不同值)
|
||||
// cliVersion: Claude CLI 版本(如 "2.1.81")
|
||||
// pkgVersion: SDK 版本(如 "0.80.0")
|
||||
// runtimeVersion: Node.js 版本(如 "v24.13.0")
|
||||
// os_: 操作系统(如 "Linux")
|
||||
// arch: 架构(如 "arm64")
|
||||
func ApplyFingerprintOverrides(cliVersion, pkgVersion, runtimeVersion, os_, arch string) {
|
||||
if cliVersion != "" {
|
||||
DefaultHeaders["User-Agent"] = "claude-cli/" + cliVersion + " (external, cli)"
|
||||
}
|
||||
if pkgVersion != "" {
|
||||
DefaultHeaders["X-Stainless-Package-Version"] = pkgVersion
|
||||
}
|
||||
if runtimeVersion != "" {
|
||||
DefaultHeaders["X-Stainless-Runtime-Version"] = runtimeVersion
|
||||
}
|
||||
if os_ != "" {
|
||||
DefaultHeaders["X-Stainless-OS"] = os_
|
||||
}
|
||||
if arch != "" {
|
||||
DefaultHeaders["X-Stainless-Arch"] = arch
|
||||
}
|
||||
}
|
||||
|
||||
// Model 表示一个 Claude 模型
|
||||
type Model struct {
|
||||
ID string `json:"id"`
|
||||
|
||||
@ -26,13 +26,13 @@ var (
|
||||
|
||||
// 默认指纹值(当客户端未提供时使用)
|
||||
var defaultFingerprint = Fingerprint{
|
||||
UserAgent: "claude-cli/2.1.22 (external, cli)",
|
||||
UserAgent: "claude-cli/2.1.84 (external, cli)",
|
||||
StainlessLang: "js",
|
||||
StainlessPackageVersion: "0.70.0",
|
||||
StainlessOS: "Linux",
|
||||
StainlessPackageVersion: "0.74.0",
|
||||
StainlessOS: "MacOS",
|
||||
StainlessArch: "arm64",
|
||||
StainlessRuntime: "node",
|
||||
StainlessRuntimeVersion: "v24.13.0",
|
||||
StainlessRuntimeVersion: "v24.3.0",
|
||||
}
|
||||
|
||||
// Fingerprint represents account fingerprint data
|
||||
@ -63,7 +63,8 @@ type IdentityCache interface {
|
||||
|
||||
// IdentityService 管理OAuth账号的请求身份指纹
|
||||
type IdentityService struct {
|
||||
cache IdentityCache
|
||||
cache IdentityCache
|
||||
instanceSalt string // 实例级隔离盐值,不同 sub2api 实例产生不同的 hash 输出
|
||||
}
|
||||
|
||||
// NewIdentityService 创建新的IdentityService
|
||||
@ -242,8 +243,14 @@ func (s *IdentityService) RewriteUserID(body []byte, accountID int64, accountUUI
|
||||
|
||||
sessionTail := parsed.SessionID // 原始session UUID
|
||||
|
||||
// 生成新的session hash: SHA256(accountID::sessionTail) -> UUID格式
|
||||
seed := fmt.Sprintf("%d::%s", accountID, sessionTail)
|
||||
// 生成新的session hash: SHA256(salt::accountID::sessionTail) -> UUID格式
|
||||
// instanceSalt 使不同 sub2api 实例对相同输入产生不同的 hash
|
||||
var seed string
|
||||
if s.instanceSalt != "" {
|
||||
seed = fmt.Sprintf("%s::%d::%s", s.instanceSalt, accountID, sessionTail)
|
||||
} else {
|
||||
seed = fmt.Sprintf("%d::%s", accountID, sessionTail)
|
||||
}
|
||||
newSessionHash := generateUUIDFromSeed(seed)
|
||||
|
||||
// 根据客户端版本选择输出格式
|
||||
|
||||
39
backend/internal/service/identity_service_antigravity.go
Normal file
39
backend/internal/service/identity_service_antigravity.go
Normal file
@ -0,0 +1,39 @@
|
||||
package service
|
||||
|
||||
// ==============================================================
|
||||
// antigravity — identity_service 扩展
|
||||
//
|
||||
// 此文件包含 Antigravity fork 对 IdentityService 的扩展,
|
||||
// 新增了实例级隔离盐值和指纹默认值覆盖功能。
|
||||
//
|
||||
// 对上游文件 identity_service.go 的最小化改动:
|
||||
// - defaultFingerprint 版本号更新
|
||||
// - IdentityService struct 新增 instanceSalt 字段
|
||||
// ==============================================================
|
||||
|
||||
// ApplyDefaultFingerprintOverrides 用配置覆盖 identity_service 的默认指纹
|
||||
// 允许不同部署实例设置不同的 CLI/SDK 版本号,避免所有实例指纹相同
|
||||
func ApplyDefaultFingerprintOverrides(cliVersion, pkgVersion, runtimeVersion, os_, arch string) {
|
||||
if cliVersion != "" {
|
||||
defaultFingerprint.UserAgent = "claude-cli/" + cliVersion + " (external, cli)"
|
||||
}
|
||||
if pkgVersion != "" {
|
||||
defaultFingerprint.StainlessPackageVersion = pkgVersion
|
||||
}
|
||||
if runtimeVersion != "" {
|
||||
defaultFingerprint.StainlessRuntimeVersion = runtimeVersion
|
||||
}
|
||||
if os_ != "" {
|
||||
defaultFingerprint.StainlessOS = os_
|
||||
}
|
||||
if arch != "" {
|
||||
defaultFingerprint.StainlessArch = arch
|
||||
}
|
||||
}
|
||||
|
||||
// NewIdentityServiceWithSalt 创建带实例盐值的 IdentityService
|
||||
// 实例盐值用于 user_id 重写时的 session hash 混淆,
|
||||
// 使不同 sub2api 实例对相同输入产生不同的 hash 输出,增加隔离性
|
||||
func NewIdentityServiceWithSalt(cache IdentityCache, salt string) *IdentityService {
|
||||
return &IdentityService{cache: cache, instanceSalt: salt}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user