first commit
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

This commit is contained in:
Rogee
2025-09-28 10:05:07 +08:00
commit 7fcabe0225
481 changed files with 125127 additions and 0 deletions

266
internal/parser/trojan.go Normal file
View File

@@ -0,0 +1,266 @@
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"}
}