package controller import ( "encoding/base64" "fmt" "strings" "github.com/sagernet/sing-shadowsocks/shadowaead_2022" C "github.com/sagernet/sing/common" "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" "github.com/XrayR-project/XrayR/api" ) var AEADMethod = map[shadowsocks.CipherType]uint8{ shadowsocks.CipherType_AES_128_GCM: 0, shadowsocks.CipherType_AES_256_GCM: 0, shadowsocks.CipherType_CHACHA20_POLY1305: 0, shadowsocks.CipherType_XCHACHA20_POLY1305: 0, } func (c *Controller) buildVmessUser(userInfo *[]api.UserInfo, serverAlterID uint16) (users []*protocol.User) { users = make([]*protocol.User, len(*userInfo)) for i, user := range *userInfo { vmessAccount := &conf.VMessAccount{ ID: user.UUID, AlterIds: serverAlterID, Security: "auto", } users[i] = &protocol.User{ Level: 0, Email: c.buildUserTag(&user), // Email: InboundTag|email|uid Account: serial.ToTypedMessage(vmessAccount.Build()), } } return users } func (c *Controller) buildVlessUser(userInfo *[]api.UserInfo) (users []*protocol.User) { users = make([]*protocol.User, len(*userInfo)) for i, user := range *userInfo { vlessAccount := &vless.Account{ Id: user.UUID, Flow: "xtls-rprx-direct", } users[i] = &protocol.User{ Level: 0, Email: c.buildUserTag(&user), Account: serial.ToTypedMessage(vlessAccount), } } return users } func (c *Controller) buildTrojanUser(userInfo *[]api.UserInfo) (users []*protocol.User) { users = make([]*protocol.User, len(*userInfo)) for i, user := range *userInfo { trojanAccount := &trojan.Account{ Password: user.UUID, Flow: "xtls-rprx-direct", } users[i] = &protocol.User{ Level: 0, Email: c.buildUserTag(&user), Account: serial.ToTypedMessage(trojanAccount), } } return users } func (c *Controller) buildSSUser(userInfo *[]api.UserInfo, method string) (users []*protocol.User) { users = make([]*protocol.User, len(*userInfo)) for i, user := range *userInfo { // // shadowsocks2022 Key = "openssl rand -base64 32" and multi users needn't cipher method if C.Contains(shadowaead_2022.List, strings.ToLower(method)) { e := c.buildUserTag(&user) if len(user.Passwd) < 16 { newError("shadowsocks2022 key's length must be greater than 16").AtError().WriteToLog() return } userKey := user.Passwd[:16] if strings.Contains(method, "256") { if len(user.Passwd) < 32 { newError("shadowsocks2022 key's length must be greater than 32").AtError().WriteToLog() return } userKey = userKey[:32] } users[i] = &protocol.User{ Level: 0, Email: e, Account: serial.ToTypedMessage(&shadowsocks_2022.User{ Key: base64.StdEncoding.EncodeToString([]byte(userKey)), Email: e, Level: 0, }), } } else { users[i] = &protocol.User{ Level: 0, Email: c.buildUserTag(&user), Account: serial.ToTypedMessage(&shadowsocks.Account{ Password: user.Passwd, CipherType: cipherFromString(method), }), } } } return users } func (c *Controller) buildSSPluginUser(userInfo *[]api.UserInfo) (users []*protocol.User) { users = make([]*protocol.User, len(*userInfo)) for i, user := range *userInfo { // shadowsocks2022 Key = openssl rand -base64 32 and multi users needn't cipher method if C.Contains(shadowaead_2022.List, strings.ToLower(user.Method)) { e := c.buildUserTag(&user) users[i] = &protocol.User{ Level: 0, Email: e, Account: serial.ToTypedMessage(&shadowsocks_2022.User{ Key: base64.StdEncoding.EncodeToString([]byte(user.Passwd)), Email: e, Level: 0, }), } } else { // Check if the cypher method is AEAD cypherMethod := cipherFromString(user.Method) if _, ok := AEADMethod[cypherMethod]; ok { users[i] = &protocol.User{ Level: 0, Email: c.buildUserTag(&user), Account: serial.ToTypedMessage(&shadowsocks.Account{ Password: user.Passwd, CipherType: cypherMethod, }), } } } } return users } func cipherFromString(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 } } func (c *Controller) buildUserTag(user *api.UserInfo) string { return fmt.Sprintf("%s|%s|%d", c.Tag, user.Email, user.UID) }