Files
subconverter-go/internal/parser/trojan.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

266 lines
5.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package parser
import (
"fmt"
"net/url"
"strconv"
"strings"
"github.com/subconverter-go/internal/logging"
)
// TrojanParser Trojan协议解析器
// 实现Trojan代理配置的解析功能
type TrojanParser struct {
logger *logging.Logger
}
// NewTrojanParser 创建新的Trojan解析器
// 返回初始化好的TrojanParser实例
func NewTrojanParser(logger *logging.Logger) *TrojanParser {
return &TrojanParser{
logger: logger,
}
}
// Parse 解析Trojan配置
// 支持标准URL格式
func (p *TrojanParser) Parse(input string) (*ProxyConfig, error) {
p.logger.Debugf("Parsing Trojan configuration")
// 去除前缀
input = strings.TrimPrefix(input, "trojan://")
// 解析URL
parsedURL, err := url.Parse("trojan://" + input)
if err != nil {
return nil, fmt.Errorf("failed to parse Trojan URL: %v", err)
}
// 获取密码
password := parsedURL.User.String()
if password == "" {
return nil, fmt.Errorf("password is required")
}
config := &ProxyConfig{
Type: "trojan",
Protocol: "trojan",
Server: parsedURL.Hostname(),
}
// 解析端口
port, err := strconv.Atoi(parsedURL.Port())
if err != nil {
return nil, fmt.Errorf("invalid port number: %v", err)
}
config.Port = port
// 解析备注
if parsedURL.Fragment != "" {
config.Name = parsedURL.Fragment
} else {
config.Name = fmt.Sprintf("trojan-%s:%d", config.Server, config.Port)
}
// 创建设置映射
settings := map[string]interface{}{
"password": password,
"udp": true,
}
// 解析查询参数
query := parsedURL.Query()
// 解析allowInsecure
if allowInsecure := query.Get("allowInsecure"); allowInsecure != "" {
settings["allowInsecure"] = p.parseBool(allowInsecure)
}
// 解析sni
if sni := query.Get("sni"); sni != "" {
settings["sni"] = sni
}
// 解析peer
if peer := query.Get("peer"); peer != "" {
settings["peer"] = peer
}
// 解析network类型
network := query.Get("type")
if network == "" {
network = "tcp"
}
// 添加网络特定配置
switch network {
case "ws":
settings["network"] = "ws"
wsSettings := map[string]interface{}{
"path": "/",
}
if host := query.Get("host"); host != "" {
wsSettings["headers"] = map[string]string{
"Host": host,
}
}
if path := query.Get("path"); path != "" {
wsSettings["path"] = path
}
settings["wsSettings"] = wsSettings
case "grpc":
settings["network"] = "grpc"
grpcSettings := map[string]interface{}{
"serviceName": query.Get("serviceName"),
"multiMode": false,
}
if service := query.Get("serviceName"); service != "" {
grpcSettings["serviceName"] = service
}
settings["grpcSettings"] = grpcSettings
case "kcp":
settings["network"] = "kcp"
kcpSettings := map[string]interface{}{
"header": map[string]string{
"type": query.Get("headerType"),
},
}
if headerType := query.Get("headerType"); headerType != "" {
kcpSettings["header"].(map[string]string)["type"] = headerType
}
settings["kcpSettings"] = kcpSettings
default:
settings["network"] = "tcp"
}
// 解析TLS配置
if network != "tcp" || query.Get("security") == "tls" {
settings["security"] = "tls"
}
config.Settings = settings
config.UDP = true
p.logger.Infof("Successfully parsed Trojan configuration for server: %s:%d", config.Server, config.Port)
return config, nil
}
// parseBool 解析布尔值
func (p *TrojanParser) parseBool(value string) bool {
switch strings.ToLower(value) {
case "1", "true", "yes", "on":
return true
default:
return false
}
}
// Validate 验证Trojan配置
func (p *TrojanParser) Validate(config *ProxyConfig) error {
p.logger.Debugf("Validating Trojan 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)
}
password := p.getPassword(config)
if password == "" {
return fmt.Errorf("password is required")
}
// 验证密码格式应该是一个44字符的Base64编码字符串
if len(password) != 44 {
p.logger.Warnf("Trojan password length is not 44 characters: %d", len(password))
}
// 验证网络协议
network := p.getNetwork(config)
if err := p.validateNetwork(network); err != nil {
return err
}
// 验证SNI如果启用TLS
if p.getSecurity(config) == "tls" {
sni := p.getSNI(config)
if sni == "" {
p.logger.Debug("SNI not specified, using server address")
}
}
p.logger.Debug("Trojan configuration validation passed")
return nil
}
// validateNetwork 验证网络协议
func (p *TrojanParser) validateNetwork(network string) error {
supportedNetworks := []string{"tcp", "ws", "grpc", "kcp"}
for _, supported := range supportedNetworks {
if network == supported {
return nil
}
}
return fmt.Errorf("unsupported network type: %s", network)
}
// getPassword 从配置中获取密码
func (p *TrojanParser) getPassword(config *ProxyConfig) string {
if password, exists := config.Settings["password"]; exists {
if passwordStr, ok := password.(string); ok {
return passwordStr
}
}
return ""
}
// getNetwork 从配置中获取网络协议
func (p *TrojanParser) getNetwork(config *ProxyConfig) string {
if network, exists := config.Settings["network"]; exists {
if networkStr, ok := network.(string); ok {
return networkStr
}
}
return "tcp"
}
// getSecurity 从配置中获取安全设置
func (p *TrojanParser) getSecurity(config *ProxyConfig) string {
if security, exists := config.Settings["security"]; exists {
if securityStr, ok := security.(string); ok {
return securityStr
}
}
return "none"
}
// getSNI 从配置中获取SNI
func (p *TrojanParser) getSNI(config *ProxyConfig) string {
if sni, exists := config.Settings["sni"]; exists {
if sniStr, ok := sni.(string); ok {
return sniStr
}
}
return ""
}
// GetSupportedProtocols 获取支持的协议
func (p *TrojanParser) GetSupportedProtocols() []string {
return []string{"trojan"}
}