package parser import ( "encoding/base64" "encoding/json" "fmt" "strconv" "strings" "github.com/subconverter-go/internal/logging" ) // VMessParser VMess协议解析器 // 实现VMess代理配置的解析功能 type VMessParser struct { logger *logging.Logger } // NewVMessParser 创建新的VMess解析器 // 返回初始化好的VMessParser实例 func NewVMessParser(logger *logging.Logger) *VMessParser { return &VMessParser{ logger: logger, } } // VMessConfig VMess配置结构 type VMessConfig struct { V string `json:"v"` // 版本 PS string `json:"ps"` // 备注 Add string `json:"add"` // 服务器地址 Port string `json:"port"` // 服务器端口 ID string `json:"id"` // 用户ID Aid string `json:"aid"` // 额外ID (alterId) Net string `json:"net"` // 传输协议 Type string `json:"type"` // 伪装类型 Host string `json:"host"` // 主机名/域名 Path string `json:"path"` // 路径 TLS string `json:"tls"` // TLS加密 } // Parse 解析VMess配置 // 支持标准Base64编码格式 func (p *VMessParser) Parse(input string) (*ProxyConfig, error) { p.logger.Debugf("Parsing VMess configuration") lower := strings.ToLower(input) if strings.HasPrefix(lower, "vmess1://") { input = "vmess://" + input[len("vmess1://"):] } // 去除前缀 input = strings.TrimPrefix(input, "vmess://") // 解码Base64 decoded, err := base64.StdEncoding.DecodeString(input) if err != nil { // 尝试URL安全的Base64解码 decoded, err = base64.URLEncoding.DecodeString(input) if err != nil { return nil, fmt.Errorf("failed to decode VMess configuration: %v", err) } } // 解析JSON配置 var vmessConfig VMessConfig if err := json.Unmarshal(decoded, &vmessConfig); err != nil { return nil, fmt.Errorf("failed to parse VMess JSON configuration: %v", err) } // 验证必要字段 if vmessConfig.Add == "" || vmessConfig.Port == "" || vmessConfig.ID == "" { return nil, fmt.Errorf("invalid VMess configuration: missing required fields") } config := &ProxyConfig{ Type: "vmess", Protocol: "vmess", Server: vmessConfig.Add, } // 解析端口 port, err := strconv.Atoi(vmessConfig.Port) if err != nil { return nil, fmt.Errorf("invalid port number: %v", err) } config.Port = port // 设置备注 if vmessConfig.PS != "" { config.Name = vmessConfig.PS } else { config.Name = fmt.Sprintf("vmess-%s:%d", config.Server, config.Port) } // 创建设置映射 settings := map[string]interface{}{ "uuid": vmessConfig.ID, "alterId": p.parseAlterId(vmessConfig.Aid), "network": p.parseNetwork(vmessConfig.Net), "tls": p.parseTLS(vmessConfig.TLS), "udp": true, } // 添加网络特定配置 switch vmessConfig.Net { case "ws": settings["wsSettings"] = map[string]interface{}{ "path": p.parsePath(vmessConfig.Path), "headers": map[string]string{ "Host": p.parseHost(vmessConfig.Host), }, } case "http": settings["httpSettings"] = map[string]interface{}{ "path": p.parsePath(vmessConfig.Path), "host": []string{p.parseHost(vmessConfig.Host)}, } case "quic": settings["quicSettings"] = map[string]interface{}{ "security": p.parseType(vmessConfig.Type), "key": p.parseHost(vmessConfig.Host), "header": map[string]string{ "type": p.parseType(vmessConfig.Type), }, } case "grpc": settings["grpcSettings"] = map[string]interface{}{ "serviceName": p.parsePath(vmessConfig.Path), "multiMode": false, } } config.Settings = settings config.UDP = true p.logger.Infof("Successfully parsed VMess configuration for server: %s:%d", config.Server, config.Port) return config, nil } // parseAlterId 解析额外ID func (p *VMessParser) parseAlterId(aid string) int { if aid == "" { return 0 } alterId, err := strconv.Atoi(aid) if err != nil { p.logger.Warnf("Invalid alterId: %s, using default 0", aid) return 0 } return alterId } // parseNetwork 解析网络协议 func (p *VMessParser) parseNetwork(net string) string { switch net { case "tcp", "kcp", "ws", "http", "quic", "grpc": return net default: p.logger.Warnf("Unknown network type: %s, using tcp", net) return "tcp" } } // parseTLS 解析TLS配置 func (p *VMessParser) parseTLS(tls string) string { switch tls { case "tls", "1", "true": return "tls" default: return "none" } } // parseType 解析伪装类型 func (p *VMessParser) parseType(typ string) string { if typ == "" { return "none" } return typ } // parseHost 解析主机名 func (p *VMessParser) parseHost(host string) string { if host == "" { return "" } return host } // parsePath 解析路径 func (p *VMessParser) parsePath(path string) string { if path == "" { return "/" } return path } // Validate 验证VMess配置 func (p *VMessParser) Validate(config *ProxyConfig) error { p.logger.Debugf("Validating VMess configuration") // 检查必要字段 if config.Server == "" { return fmt.Errorf("server address is required") } if config.Port <= 0 || config.Port > 65535 { return fmt.Errorf("invalid port number: %d", config.Port) } uuid := p.getUUID(config) if uuid == "" { return fmt.Errorf("UUID is required") } // 验证UUID格式 if err := p.validateUUID(uuid); err != nil { return err } // 验证网络协议 network := p.getNetwork(config) if err := p.validateNetwork(network); err != nil { return err } // 验证额外ID alterId := p.getAlterId(config) if err := p.validateAlterId(alterId); err != nil { return err } p.logger.Debug("VMess configuration validation passed") return nil } // validateUUID 验证UUID格式 func (p *VMessParser) validateUUID(uuid string) error { // 简单的UUID格式验证 if len(uuid) != 36 { return fmt.Errorf("invalid UUID length: %d", len(uuid)) } if strings.Count(uuid, "-") != 4 { return fmt.Errorf("invalid UUID format: incorrect hyphen count") } return nil } // validateNetwork 验证网络协议 func (p *VMessParser) validateNetwork(network string) error { supportedNetworks := []string{"tcp", "kcp", "ws", "http", "quic", "grpc"} for _, supported := range supportedNetworks { if network == supported { return nil } } return fmt.Errorf("unsupported network type: %s", network) } // validateAlterId 验证额外ID func (p *VMessParser) validateAlterId(alterId int) error { if alterId < 0 { return fmt.Errorf("alterId cannot be negative: %d", alterId) } if alterId > 65535 { return fmt.Errorf("alterId too large: %d", alterId) } return nil } // getUUID 从配置中获取UUID func (p *VMessParser) getUUID(config *ProxyConfig) string { if uuid, exists := config.Settings["uuid"]; exists { if uuidStr, ok := uuid.(string); ok { return uuidStr } } return "" } // getNetwork 从配置中获取网络协议 func (p *VMessParser) getNetwork(config *ProxyConfig) string { if network, exists := config.Settings["network"]; exists { if networkStr, ok := network.(string); ok { return networkStr } } return "tcp" } // getAlterId 从配置中获取额外ID func (p *VMessParser) getAlterId(config *ProxyConfig) int { if alterId, exists := config.Settings["alterId"]; exists { if alterIdInt, ok := alterId.(int); ok { return alterIdInt } if alterIdFloat, ok := alterId.(float64); ok { return int(alterIdFloat) } } return 0 } // GetSupportedProtocols 获取支持的协议 func (p *VMessParser) GetSupportedProtocols() []string { return []string{"vmess"} }