Files
subconverter-go/internal/parser/vmess.go
Rogee 7fcabe0225
Some checks failed
CI/CD Pipeline / Test (push) Failing after 22m19s
CI/CD Pipeline / Security Scan (push) Failing after 5m57s
CI/CD Pipeline / Build (amd64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (amd64, linux) (push) Has been skipped
CI/CD Pipeline / Build (amd64, windows) (push) Has been skipped
CI/CD Pipeline / Build (arm64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (arm64, linux) (push) Has been skipped
CI/CD Pipeline / Build Docker Image (push) Has been skipped
CI/CD Pipeline / Create Release (push) Has been skipped
first commit
2025-09-28 10:05:07 +08:00

315 lines
7.3 KiB
Go

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"}
}