diff --git a/common/builder/user.go b/common/builder/user.go deleted file mode 100644 index 91a5399..0000000 --- a/common/builder/user.go +++ /dev/null @@ -1,131 +0,0 @@ -package builder - -import ( - "encoding/base64" - "fmt" - "github.com/Yuzuki616/V2bX/api/panel" - "github.com/xtls/xray-core/common/protocol" - "github.com/xtls/xray-core/common/serial" - "github.com/xtls/xray-core/infra/conf" - "github.com/xtls/xray-core/proxy/shadowsocks" - "github.com/xtls/xray-core/proxy/shadowsocks_2022" - "github.com/xtls/xray-core/proxy/trojan" - "github.com/xtls/xray-core/proxy/vless" - "strings" -) - -func BuildVmessUsers(tag string, userInfo []panel.UserInfo) (users []*protocol.User) { - users = make([]*protocol.User, len(userInfo)) - for i, user := range userInfo { - users[i] = BuildVmessUser(tag, &user) - } - return users -} - -func BuildVmessUser(tag string, userInfo *panel.UserInfo) (user *protocol.User) { - vmessAccount := &conf.VMessAccount{ - ID: userInfo.Uuid, - AlterIds: 0, - Security: "auto", - } - return &protocol.User{ - Level: 0, - Email: BuildUserTag(tag, userInfo.Uuid), // Uid: InboundTag|email - Account: serial.ToTypedMessage(vmessAccount.Build()), - } -} - -func BuildVlessUsers(tag string, userInfo []panel.UserInfo, flow string) (users []*protocol.User) { - users = make([]*protocol.User, len(userInfo)) - for i := range userInfo { - users[i] = BuildVlessUser(tag, &(userInfo)[i], flow) - } - return users -} - -func BuildVlessUser(tag string, userInfo *panel.UserInfo, flow string) (user *protocol.User) { - vlessAccount := &vless.Account{ - Id: userInfo.Uuid, - } - vlessAccount.Flow = flow - return &protocol.User{ - Level: 0, - Email: BuildUserTag(tag, userInfo.Uuid), - Account: serial.ToTypedMessage(vlessAccount), - } -} - -func BuildTrojanUsers(tag string, userInfo []panel.UserInfo) (users []*protocol.User) { - users = make([]*protocol.User, len(userInfo)) - for i := range userInfo { - users[i] = BuildTrojanUser(tag, &(userInfo)[i]) - } - return users -} - -func BuildTrojanUser(tag string, userInfo *panel.UserInfo) (user *protocol.User) { - trojanAccount := &trojan.Account{ - Password: userInfo.Uuid, - } - return &protocol.User{ - Level: 0, - Email: BuildUserTag(tag, userInfo.Uuid), - Account: serial.ToTypedMessage(trojanAccount), - } -} -func BuildSSUsers(tag string, userInfo []panel.UserInfo, cypher string, serverKey string) (users []*protocol.User) { - users = make([]*protocol.User, len(userInfo)) - for i := range userInfo { - users[i] = BuildSSUser(tag, &userInfo[i], cypher, serverKey) - } - return users -} - -func BuildSSUser(tag string, userInfo *panel.UserInfo, cypher string, serverKey string) (user *protocol.User) { - if serverKey == "" { - ssAccount := &shadowsocks.Account{ - Password: userInfo.Uuid, - CipherType: getCipherFromString(cypher), - } - return &protocol.User{ - Level: 0, - Email: BuildUserTag(tag, userInfo.Uuid), - Account: serial.ToTypedMessage(ssAccount), - } - } else { - var keyLength int - switch cypher { - case "2022-blake3-aes-128-gcm": - keyLength = 16 - case "2022-blake3-aes-256-gcm": - keyLength = 32 - } - ssAccount := &shadowsocks_2022.User{ - Key: base64.StdEncoding.EncodeToString([]byte(userInfo.Uuid[:keyLength])), - } - return &protocol.User{ - Level: 0, - Email: BuildUserTag(tag, userInfo.Uuid), - Account: serial.ToTypedMessage(ssAccount), - } - } -} - -func BuildUserTag(tag string, uuid string) string { - return fmt.Sprintf("%s|%s", tag, uuid) -} - -func getCipherFromString(c string) shadowsocks.CipherType { - switch strings.ToLower(c) { - case "aes-128-gcm", "aead_aes_128_gcm": - return shadowsocks.CipherType_AES_128_GCM - case "aes-256-gcm", "aead_aes_256_gcm": - return shadowsocks.CipherType_AES_256_GCM - case "chacha20-poly1305", "aead_chacha20_poly1305", "chacha20-ietf-poly1305": - return shadowsocks.CipherType_CHACHA20_POLY1305 - case "none", "plain": - return shadowsocks.CipherType_NONE - default: - return shadowsocks.CipherType_UNKNOWN - } -} diff --git a/common/format/user.go b/common/format/user.go new file mode 100644 index 0000000..08cb9fb --- /dev/null +++ b/common/format/user.go @@ -0,0 +1,9 @@ +package format + +import ( + "fmt" +) + +func UserTag(tag string, uuid string) string { + return fmt.Sprintf("%s|%s", tag, uuid) +} diff --git a/common/builder/inbound.go b/core/xray/inbound.go similarity index 99% rename from common/builder/inbound.go rename to core/xray/inbound.go index 21e3c9f..6198c96 100644 --- a/common/builder/inbound.go +++ b/core/xray/inbound.go @@ -1,4 +1,4 @@ -package builder +package xray import ( "crypto/rand" @@ -16,7 +16,7 @@ import ( ) // BuildInbound build Inbound config for different protocol -func BuildInbound(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, tag string) (*core.InboundHandlerConfig, error) { +func buildInbound(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, tag string) (*core.InboundHandlerConfig, error) { in := &coreConf.InboundDetourConfig{} // Set network protocol t := coreConf.TransportProtocol(nodeInfo.Network) diff --git a/core/xray/node.go b/core/xray/node.go index 8dabad1..a26204a 100644 --- a/core/xray/node.go +++ b/core/xray/node.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "github.com/Yuzuki616/V2bX/api/panel" - "github.com/Yuzuki616/V2bX/common/builder" "github.com/Yuzuki616/V2bX/conf" "github.com/xtls/xray-core/core" "github.com/xtls/xray-core/features/inbound" @@ -12,7 +11,7 @@ import ( ) func (c *Core) AddNode(tag string, info *panel.NodeInfo, config *conf.ControllerConfig) error { - inboundConfig, err := builder.BuildInbound(config, info, tag) + inboundConfig, err := buildInbound(config, info, tag) if err != nil { return fmt.Errorf("build inbound error: %s", err) } @@ -20,7 +19,7 @@ func (c *Core) AddNode(tag string, info *panel.NodeInfo, config *conf.Controller if err != nil { return fmt.Errorf("add inbound error: %s", err) } - outBoundConfig, err := builder.BuildOutbound(config, tag) + outBoundConfig, err := buildOutbound(config, tag) if err != nil { return fmt.Errorf("build outbound error: %s", err) } diff --git a/common/builder/outbound.go b/core/xray/outbound.go similarity index 93% rename from common/builder/outbound.go rename to core/xray/outbound.go index f3be9b9..ee09bab 100644 --- a/common/builder/outbound.go +++ b/core/xray/outbound.go @@ -1,4 +1,4 @@ -package builder +package xray import ( "fmt" @@ -10,7 +10,7 @@ import ( ) // BuildOutbound build freedom outbund config for addoutbound -func BuildOutbound(config *conf2.ControllerConfig, tag string) (*core.OutboundHandlerConfig, error) { +func buildOutbound(config *conf2.ControllerConfig, tag string) (*core.OutboundHandlerConfig, error) { outboundDetourConfig := &conf.OutboundDetourConfig{} outboundDetourConfig.Protocol = "freedom" outboundDetourConfig.Tag = tag diff --git a/core/xray/ss.go b/core/xray/ss.go new file mode 100644 index 0000000..299c2d7 --- /dev/null +++ b/core/xray/ss.go @@ -0,0 +1,65 @@ +package xray + +import ( + "encoding/base64" + "github.com/Yuzuki616/V2bX/api/panel" + "github.com/Yuzuki616/V2bX/common/format" + "github.com/xtls/xray-core/common/protocol" + "github.com/xtls/xray-core/common/serial" + "github.com/xtls/xray-core/proxy/shadowsocks" + "github.com/xtls/xray-core/proxy/shadowsocks_2022" + "strings" +) + +func buildSSUsers(tag string, userInfo []panel.UserInfo, cypher string, serverKey string) (users []*protocol.User) { + users = make([]*protocol.User, len(userInfo)) + for i := range userInfo { + users[i] = buildSSUser(tag, &userInfo[i], cypher, serverKey) + } + return users +} + +func buildSSUser(tag string, userInfo *panel.UserInfo, cypher string, serverKey string) (user *protocol.User) { + if serverKey == "" { + ssAccount := &shadowsocks.Account{ + Password: userInfo.Uuid, + CipherType: getCipherFromString(cypher), + } + return &protocol.User{ + Level: 0, + Email: format.UserTag(tag, userInfo.Uuid), + Account: serial.ToTypedMessage(ssAccount), + } + } else { + var keyLength int + switch cypher { + case "2022-blake3-aes-128-gcm": + keyLength = 16 + case "2022-blake3-aes-256-gcm": + keyLength = 32 + } + ssAccount := &shadowsocks_2022.User{ + Key: base64.StdEncoding.EncodeToString([]byte(userInfo.Uuid[:keyLength])), + } + return &protocol.User{ + Level: 0, + Email: format.UserTag(tag, userInfo.Uuid), + Account: serial.ToTypedMessage(ssAccount), + } + } +} + +func getCipherFromString(c string) shadowsocks.CipherType { + switch strings.ToLower(c) { + case "aes-128-gcm", "aead_aes_128_gcm": + return shadowsocks.CipherType_AES_128_GCM + case "aes-256-gcm", "aead_aes_256_gcm": + return shadowsocks.CipherType_AES_256_GCM + case "chacha20-poly1305", "aead_chacha20_poly1305", "chacha20-ietf-poly1305": + return shadowsocks.CipherType_CHACHA20_POLY1305 + case "none", "plain": + return shadowsocks.CipherType_NONE + default: + return shadowsocks.CipherType_UNKNOWN + } +} diff --git a/core/xray/trojan.go b/core/xray/trojan.go new file mode 100644 index 0000000..cea6762 --- /dev/null +++ b/core/xray/trojan.go @@ -0,0 +1,28 @@ +package xray + +import ( + "github.com/Yuzuki616/V2bX/api/panel" + "github.com/Yuzuki616/V2bX/common/format" + "github.com/xtls/xray-core/common/protocol" + "github.com/xtls/xray-core/common/serial" + "github.com/xtls/xray-core/proxy/trojan" +) + +func buildTrojanUsers(tag string, userInfo []panel.UserInfo) (users []*protocol.User) { + users = make([]*protocol.User, len(userInfo)) + for i := range userInfo { + users[i] = buildTrojanUser(tag, &(userInfo)[i]) + } + return users +} + +func buildTrojanUser(tag string, userInfo *panel.UserInfo) (user *protocol.User) { + trojanAccount := &trojan.Account{ + Password: userInfo.Uuid, + } + return &protocol.User{ + Level: 0, + Email: format.UserTag(tag, userInfo.Uuid), + Account: serial.ToTypedMessage(trojanAccount), + } +} diff --git a/core/xray/user.go b/core/xray/user.go index b2a51e4..26dc933 100644 --- a/core/xray/user.go +++ b/core/xray/user.go @@ -4,7 +4,7 @@ import ( "context" "fmt" "github.com/Yuzuki616/V2bX/api/panel" - "github.com/Yuzuki616/V2bX/common/builder" + "github.com/Yuzuki616/V2bX/common/format" vCore "github.com/Yuzuki616/V2bX/core" "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/proxy" @@ -33,7 +33,7 @@ func (c *Core) DelUsers(users []panel.UserInfo, tag string) error { } var up, down, user string for i := range users { - user = builder.BuildUserTag(tag, users[i].Uuid) + user = format.UserTag(tag, users[i].Uuid) err = userManager.RemoveUser(context.Background(), user) if err != nil { return err @@ -47,8 +47,8 @@ func (c *Core) DelUsers(users []panel.UserInfo, tag string) error { } func (c *Core) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) { - upName := "user>>>" + builder.BuildUserTag(tag, uuid) + ">>>traffic>>>uplink" - downName := "user>>>" + builder.BuildUserTag(tag, uuid) + ">>>traffic>>>downlink" + upName := "user>>>" + format.UserTag(tag, uuid) + ">>>traffic>>>uplink" + downName := "user>>>" + format.UserTag(tag, uuid) + ">>>traffic>>>downlink" upCounter := c.shm.GetCounter(upName) downCounter := c.shm.GetCounter(downName) if reset { @@ -77,22 +77,22 @@ func (c *Core) AddUsers(p *vCore.AddUsersParams) (added int, err error) { p.NodeInfo.ExtraConfig.EnableVless { if p.Config.XrayOptions.VlessFlow != "" { if p.Config.XrayOptions.VlessFlow == p.NodeInfo.ExtraConfig.VlessFlow { - users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.Config.XrayOptions.VlessFlow) + users = buildVlessUsers(p.Tag, p.UserInfo, p.Config.XrayOptions.VlessFlow) } else { - users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.NodeInfo.ExtraConfig.VlessFlow) + users = buildVlessUsers(p.Tag, p.UserInfo, p.NodeInfo.ExtraConfig.VlessFlow) } } else { - users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.NodeInfo.ExtraConfig.VlessFlow) + users = buildVlessUsers(p.Tag, p.UserInfo, p.NodeInfo.ExtraConfig.VlessFlow) } } else { - users = builder.BuildVmessUsers(p.Tag, p.UserInfo) + users = buildVmessUsers(p.Tag, p.UserInfo) } case "trojan": - users = builder.BuildTrojanUsers(p.Tag, p.UserInfo) + users = buildTrojanUsers(p.Tag, p.UserInfo) case "shadowsocks": - users = builder.BuildSSUsers(p.Tag, + users = buildSSUsers(p.Tag, p.UserInfo, p.NodeInfo.Cipher, p.NodeInfo.ServerKey) diff --git a/core/xray/vmess.go b/core/xray/vmess.go new file mode 100644 index 0000000..75f93b6 --- /dev/null +++ b/core/xray/vmess.go @@ -0,0 +1,51 @@ +package xray + +import ( + "github.com/Yuzuki616/V2bX/api/panel" + "github.com/Yuzuki616/V2bX/common/format" + "github.com/xtls/xray-core/common/protocol" + "github.com/xtls/xray-core/common/serial" + "github.com/xtls/xray-core/infra/conf" + "github.com/xtls/xray-core/proxy/vless" +) + +func buildVmessUsers(tag string, userInfo []panel.UserInfo) (users []*protocol.User) { + users = make([]*protocol.User, len(userInfo)) + for i, user := range userInfo { + users[i] = buildVmessUser(tag, &user) + } + return users +} + +func buildVmessUser(tag string, userInfo *panel.UserInfo) (user *protocol.User) { + vmessAccount := &conf.VMessAccount{ + ID: userInfo.Uuid, + AlterIds: 0, + Security: "auto", + } + return &protocol.User{ + Level: 0, + Email: format.UserTag(tag, userInfo.Uuid), // Uid: InboundTag|email + Account: serial.ToTypedMessage(vmessAccount.Build()), + } +} + +func buildVlessUsers(tag string, userInfo []panel.UserInfo, flow string) (users []*protocol.User) { + users = make([]*protocol.User, len(userInfo)) + for i := range userInfo { + users[i] = buildVlessUser(tag, &(userInfo)[i], flow) + } + return users +} + +func buildVlessUser(tag string, userInfo *panel.UserInfo, flow string) (user *protocol.User) { + vlessAccount := &vless.Account{ + Id: userInfo.Uuid, + } + vlessAccount.Flow = flow + return &protocol.User{ + Level: 0, + Email: format.UserTag(tag, userInfo.Uuid), + Account: serial.ToTypedMessage(vlessAccount), + } +} diff --git a/limiter/dynamic.go b/limiter/dynamic.go index a74599e..b68a19d 100644 --- a/limiter/dynamic.go +++ b/limiter/dynamic.go @@ -2,7 +2,7 @@ package limiter import ( "github.com/Yuzuki616/V2bX/api/panel" - "github.com/Yuzuki616/V2bX/common/builder" + "github.com/Yuzuki616/V2bX/common/format" "time" ) @@ -11,7 +11,7 @@ func (l *Limiter) AddDynamicSpeedLimit(tag string, userInfo *panel.UserInfo, lim DynamicSpeedLimit: limitNum, ExpireTime: time.Now().Add(time.Duration(expire) * time.Second).Unix(), } - l.UserLimitInfo.Store(builder.BuildUserTag(tag, userInfo.Uuid), userLimit) + l.UserLimitInfo.Store(format.UserTag(tag, userInfo.Uuid), userLimit) return nil } diff --git a/limiter/limiter.go b/limiter/limiter.go index 45c4583..149538a 100644 --- a/limiter/limiter.go +++ b/limiter/limiter.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" "github.com/Yuzuki616/V2bX/api/panel" - "github.com/Yuzuki616/V2bX/common/builder" + "github.com/Yuzuki616/V2bX/common/format" "github.com/Yuzuki616/V2bX/conf" "github.com/juju/ratelimit" log "github.com/sirupsen/logrus" @@ -61,7 +61,7 @@ func AddLimiter(tag string, l *conf.LimitConfig, users []panel.UserInfo) *Limite SpeedLimit: users[i].SpeedLimit, ExpireTime: 0, } - info.UserLimitInfo.Store(builder.BuildUserTag(tag, users[i].Uuid), userLimit) + info.UserLimitInfo.Store(format.UserTag(tag, users[i].Uuid), userLimit) } } limitLock.Lock() @@ -86,7 +86,7 @@ func UpdateLimiter(tag string, added []panel.UserInfo, deleted []panel.UserInfo) return fmt.Errorf("get limit error: %s", err) } for i := range deleted { - l.UserLimitInfo.Delete(builder.BuildUserTag(tag, deleted[i].Uuid)) + l.UserLimitInfo.Delete(format.UserTag(tag, deleted[i].Uuid)) } for i := range added { if added[i].SpeedLimit != 0 { @@ -95,7 +95,7 @@ func UpdateLimiter(tag string, added []panel.UserInfo, deleted []panel.UserInfo) SpeedLimit: added[i].SpeedLimit, ExpireTime: 0, } - l.UserLimitInfo.Store(builder.BuildUserTag(tag, added[i].Uuid), userLimit) + l.UserLimitInfo.Store(format.UserTag(tag, added[i].Uuid), userLimit) } } return nil