package parser import ( "encoding/base64" "fmt" "strconv" "strings" "github.com/subconverter-go/internal/logging" ) // ShadowsocksRParser ShadowsocksR协议解析器 // 实现ShadowsocksR代理配置的解析功能 type ShadowsocksRParser struct { logger *logging.Logger } // NewShadowsocksRParser 创建新的ShadowsocksR解析器 // 返回初始化好的ShadowsocksRParser实例 func NewShadowsocksRParser(logger *logging.Logger) *ShadowsocksRParser { return &ShadowsocksRParser{ logger: logger, } } // Parse 解析ShadowsocksR配置 // 支持标准格式和Base64编码格式 func (p *ShadowsocksRParser) Parse(input string) (*ProxyConfig, error) { p.logger.Debugf("Parsing ShadowsocksR configuration") // 去除前缀 input = strings.TrimPrefix(input, "ssr://") // 解码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 ShadowsocksR configuration: %v", err) } } // 解析配置字符串: server:port:protocol:method:obfs:password_base64/remarks_base64/group_base64/obfsparam_base64/protocolparam_base64 parts := strings.Split(string(decoded), "/") if len(parts) < 1 { return nil, fmt.Errorf("invalid ShadowsocksR configuration format") } // 解析主要配置 mainParts := strings.Split(parts[0], ":") if len(mainParts) < 6 { return nil, fmt.Errorf("invalid ShadowsocksR main configuration format") } config := &ProxyConfig{ Type: "ssr", Protocol: "ssr", } // 解析服务器和端口 config.Server = mainParts[0] port, err := strconv.Atoi(mainParts[1]) if err != nil { return nil, fmt.Errorf("invalid port number: %v", err) } config.Port = port // 解码密码 password, err := base64.StdEncoding.DecodeString(mainParts[5]) if err != nil { return nil, fmt.Errorf("failed to decode password: %v", err) } // 创建设置映射 settings := map[string]interface{}{ "protocol": mainParts[2], "method": mainParts[3], "obfs": mainParts[4], "password": string(password), "udp": true, "protocolParam": "", "obfsParam": "", } // 解析可选参数 if len(parts) > 1 { // 解析备注 remarks, err := base64.StdEncoding.DecodeString(parts[1]) if err == nil { config.Name = string(remarks) } // 解析分组 if len(parts) > 2 { group, err := base64.StdEncoding.DecodeString(parts[2]) if err == nil { config.Group = string(group) } } // 解析obfs参数 if len(parts) > 3 { obfsParam, err := base64.StdEncoding.DecodeString(parts[3]) if err == nil { settings["obfsParam"] = string(obfsParam) } } // 解析protocol参数 if len(parts) > 4 { protocolParam, err := base64.StdEncoding.DecodeString(parts[4]) if err == nil { settings["protocolParam"] = string(protocolParam) } } } // 设置默认名称 if config.Name == "" { config.Name = fmt.Sprintf("ssr-%s:%d", config.Server, config.Port) } config.UDP = true config.Settings = settings p.logger.Infof("Successfully parsed ShadowsocksR configuration for server: %s:%d", config.Server, config.Port) return config, nil } // Validate 验证ShadowsocksR配置 func (p *ShadowsocksRParser) Validate(config *ProxyConfig) error { p.logger.Debugf("Validating ShadowsocksR 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) } method := p.getMethod(config) if method == "" { return fmt.Errorf("encryption method is required") } password := p.getPassword(config) if password == "" { return fmt.Errorf("password is required") } protocol := p.getProtocol(config) if protocol == "" { return fmt.Errorf("protocol is required") } obfs := p.getObfs(config) if obfs == "" { return fmt.Errorf("obfs is required") } // 验证加密方法 if err := p.validateMethod(method); err != nil { return err } // 验证协议 if err := p.validateProtocol(protocol); err != nil { return err } // 验证混淆 if err := p.validateObfs(obfs); err != nil { return err } p.logger.Debug("ShadowsocksR configuration validation passed") return nil } // validateMethod 验证加密方法 func (p *ShadowsocksRParser) validateMethod(method string) error { supportedMethods := []string{ "none", "table", "rc4", "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", "cast5-cfb", "des-cfb", "idea-cfb", "rc2-cfb", "seed-cfb", "salsa20", "chacha20", "chacha20-ietf", } for _, supported := range supportedMethods { if method == supported { return nil } } p.logger.Warnf("Unsupported encryption method: %s", method) return nil } // validateProtocol 验证协议 func (p *ShadowsocksRParser) validateProtocol(protocol string) error { supportedProtocols := []string{ "origin", "verify_deflate", "auth_sha1_v4", "auth_aes128_md5", "auth_aes128_sha1", "auth_chain_a", "auth_chain_b", } for _, supported := range supportedProtocols { if protocol == supported { return nil } } p.logger.Warnf("Unsupported protocol: %s", protocol) return nil } // validateObfs 验证混淆 func (p *ShadowsocksRParser) validateObfs(obfs string) error { supportedObfs := []string{ "plain", "http_simple", "http_post", "random_head", "tls1.2_ticket_auth", } for _, supported := range supportedObfs { if obfs == supported { return nil } } p.logger.Warnf("Unsupported obfs: %s", obfs) return nil } // getMethod 从配置中获取加密方法 func (p *ShadowsocksRParser) getMethod(config *ProxyConfig) string { if method, exists := config.Settings["method"]; exists { if methodStr, ok := method.(string); ok { return methodStr } } return "" } // getPassword 从配置中获取密码 func (p *ShadowsocksRParser) getPassword(config *ProxyConfig) string { if password, exists := config.Settings["password"]; exists { if passwordStr, ok := password.(string); ok { return passwordStr } } return "" } // getProtocol 从配置中获取协议 func (p *ShadowsocksRParser) getProtocol(config *ProxyConfig) string { if protocol, exists := config.Settings["protocol"]; exists { if protocolStr, ok := protocol.(string); ok { return protocolStr } } return "" } // getObfs 从配置中获取混淆 func (p *ShadowsocksRParser) getObfs(config *ProxyConfig) string { if obfs, exists := config.Settings["obfs"]; exists { if obfsStr, ok := obfs.(string); ok { return obfsStr } } return "" } // GetSupportedProtocols 获取支持的协议 func (p *ShadowsocksRParser) GetSupportedProtocols() []string { return []string{"ssr"} }