Files
subconverter-go/internal/generator/v2ray.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

322 lines
8.1 KiB
Go

package generator
import (
"encoding/json"
"fmt"
"github.com/subconverter-go/internal/logging"
"github.com/subconverter-go/internal/parser"
)
// V2RayGenerator V2Ray格式生成器
// 实现V2Ray代理配置的生成功能
type V2RayGenerator struct {
logger *logging.Logger
}
// NewV2RayGenerator 创建新的V2Ray生成器
// 返回初始化好的V2RayGenerator实例
func NewV2RayGenerator(logger *logging.Logger) *V2RayGenerator {
return &V2RayGenerator{
logger: logger,
}
}
// Generate 生成V2Ray配置
func (g *V2RayGenerator) Generate(configs []*parser.ProxyConfig, options *GenerationOptions) (string, error) {
g.logger.Debugf("Generating V2Ray configuration")
// 创建V2Ray配置结构
v2rayConfig := g.createV2RayConfig(configs, options)
// 转换为JSON
jsonData, err := json.MarshalIndent(v2rayConfig, "", " ")
if err != nil {
return "", fmt.Errorf("failed to marshal V2Ray configuration: %v", err)
}
return string(jsonData), nil
}
// ValidateOptions 验证V2Ray生成选项
func (g *V2RayGenerator) ValidateOptions(options *GenerationOptions) error {
g.logger.Debugf("Validating V2Ray generation options")
// 验证基本信息
if options.Name == "" {
return fmt.Errorf("configuration name is required")
}
// 验证端口
if options.MixedPort < 0 || options.MixedPort > 65535 {
return fmt.Errorf("invalid mixed port: %d", options.MixedPort)
}
return nil
}
// GetSupportedFormats 获取支持的格式
func (g *V2RayGenerator) GetSupportedFormats() []string {
return []string{"v2ray"}
}
// V2RayConfig V2Ray配置结构体
type V2RayConfig struct {
Log *V2RayLog `json:"log,omitempty"`
Inbound *V2RayInbound `json:"inbounds"`
Outbound *V2RayOutbound `json:"outbounds"`
Routing *V2RayRouting `json:"routing,omitempty"`
}
// V2RayLog 日志配置
type V2RayLog struct {
Loglevel string `json:"loglevel,omitempty"`
}
// V2RayInbound 入站配置
type V2RayInbound struct {
Protocol string `json:"protocol"`
Listen string `json:"listen"`
Port int `json:"port"`
Settings *V2RayInSettings `json:"settings,omitempty"`
Sniffing *V2RaySniffing `json:"sniffing,omitempty"`
Stream *V2RayStream `json:"streamSettings,omitempty"`
}
// V2RayInSettings 入站设置
type V2RayInSettings struct {
Auth string `json:"auth,omitempty"`
UDP bool `json:"udp,omitempty"`
UserLevel int `json:"userLevel,omitempty"`
Accounts []V2RayAccount `json:"accounts,omitempty"`
}
// V2RayAccount 账户信息
type V2RayAccount struct {
User string `json:"user"`
Pass string `json:"pass"`
}
// V2RaySniffing 流量嗅探
type V2RaySniffing struct {
Enabled bool `json:"enabled"`
DestOverride []string `json:"destOverride,omitempty"`
}
// V2RayStream 流媒体设置
type V2RayStream struct {
Network string `json:"network,omitempty"`
}
// V2RayOutbound 出站配置
type V2RayOutbound struct {
Protocol string `json:"protocol"`
Settings *V2RayOutSettings `json:"settings,omitempty"`
Stream *V2RayStream `json:"streamSettings,omitempty"`
Tag string `json:"tag,omitempty"`
}
// V2RayOutSettings 出站设置
type V2RayOutSettings struct {
VNext []V2RayVNext `json:"vnext,omitempty"`
Servers []V2RayServer `json:"servers,omitempty"`
Users []V2RayUser `json:"users,omitempty"`
}
// V2RayVNext 服务器节点
type V2RayVNext struct {
Address string `json:"address"`
Port int `json:"port"`
Users []V2RayUser `json:"users"`
}
// V2RayUser 用户信息
type V2RayUser struct {
ID string `json:"id"`
AlterID int `json:"alterId,omitempty"`
Email string `json:"email,omitempty"`
Security string `json:"security,omitempty"`
Level int `json:"level,omitempty"`
}
// V2RayServer 服务器信息
type V2RayServer struct {
Address string `json:"address"`
Port int `json:"port"`
Method string `json:"method,omitempty"`
Password string `json:"password,omitempty"`
OTA bool `json:"ota,omitempty"`
Users []V2RayUser `json:"users,omitempty"`
}
// V2RayRouting 路由配置
type V2RayRouting struct {
Rules []V2RayRule `json:"rules"`
}
// V2RayRule 路由规则
type V2RayRule struct {
Type string `json:"type"`
InboundTag []string `json:"inboundTag,omitempty"`
OutboundTag string `json:"outboundTag,omitempty"`
Domain []string `json:"domain,omitempty"`
IP []string `json:"ip,omitempty"`
}
// createV2RayConfig 创建V2Ray配置结构
func (g *V2RayGenerator) createV2RayConfig(configs []*parser.ProxyConfig, options *GenerationOptions) *V2RayConfig {
config := &V2RayConfig{
Log: &V2RayLog{
Loglevel: "info",
},
Inbound: g.createInbound(options),
Outbound: g.createOutbound(configs),
Routing: g.createRouting(),
}
return config
}
// createInbound 创建入站配置
func (g *V2RayGenerator) createInbound(options *GenerationOptions) *V2RayInbound {
port := 10808
if options.MixedPort > 0 {
port = options.MixedPort
}
return &V2RayInbound{
Protocol: "socks",
Listen: "127.0.0.1",
Port: port,
Settings: &V2RayInSettings{
Auth: "noauth",
UDP: true,
UserLevel: 0,
},
Sniffing: &V2RaySniffing{
Enabled: true,
DestOverride: []string{"http", "tls"},
},
}
}
// createOutbound 创建出站配置
func (g *V2RayGenerator) createOutbound(configs []*parser.ProxyConfig) *V2RayOutbound {
// 代理节点列表
vnext := make([]V2RayVNext, 0)
servers := make([]V2RayServer, 0)
for _, config := range configs {
switch config.Protocol {
case "vmess":
vnext = append(vnext, g.createVMessVNext(config))
case "ss":
servers = append(servers, g.createShadowsocksServer(config))
case "trojan":
servers = append(servers, g.createTrojanServer(config))
}
}
outbound := &V2RayOutbound{
Protocol: "freedom",
Tag: "direct",
}
// 如果有代理节点,创建代理出站
if len(vnext) > 0 || len(servers) > 0 {
if len(vnext) > 0 {
outbound = &V2RayOutbound{
Protocol: "vmess",
Tag: "proxy",
Settings: &V2RayOutSettings{
VNext: vnext,
},
}
} else {
outbound = &V2RayOutbound{
Protocol: "shadowsocks",
Tag: "proxy",
Settings: &V2RayOutSettings{
Servers: servers,
},
}
}
}
return outbound
}
// createVMessVNext 创建VMess节点配置
func (g *V2RayGenerator) createVMessVNext(config *parser.ProxyConfig) V2RayVNext {
uuid, _ := config.Settings["uuid"].(string)
alterId, _ := config.Settings["alterId"].(int)
if alterId == 0 {
alterId = 0
}
return V2RayVNext{
Address: config.Server,
Port: config.Port,
Users: []V2RayUser{
{
ID: uuid,
AlterID: alterId,
Security: "auto",
},
},
}
}
// createShadowsocksServer 创建Shadowsocks服务器配置
func (g *V2RayGenerator) createShadowsocksServer(config *parser.ProxyConfig) V2RayServer {
method, _ := config.Settings["method"].(string)
password, _ := config.Settings["password"].(string)
return V2RayServer{
Address: config.Server,
Port: config.Port,
Method: method,
Password: password,
OTA: false,
}
}
// createTrojanServer 创建Trojan服务器配置
func (g *V2RayGenerator) createTrojanServer(config *parser.ProxyConfig) V2RayServer {
password, _ := config.Settings["password"].(string)
return V2RayServer{
Address: config.Server,
Port: config.Port,
Method: "chacha20-ietf-poly1305",
Password: password,
OTA: false,
}
}
// createRouting 创建路由配置
func (g *V2RayGenerator) createRouting() *V2RayRouting {
return &V2RayRouting{
Rules: []V2RayRule{
{
Type: "field",
InboundTag: []string{"inbound"},
OutboundTag: "proxy",
},
{
Type: "field",
Domain: []string{"geosite:cn"},
OutboundTag: "direct",
},
{
Type: "field",
IP: []string{"geoip:cn", "geoip:private"},
OutboundTag: "direct",
},
{
Type: "field",
OutboundTag: "proxy",
},
},
}
}