github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/infra/conf/shadowsocks.go (about) 1 package conf 2 3 import ( 4 "strings" 5 6 "github.com/sagernet/sing-shadowsocks/shadowaead_2022" 7 C "github.com/sagernet/sing/common" 8 "github.com/xtls/xray-core/common/protocol" 9 "github.com/xtls/xray-core/common/serial" 10 "github.com/xtls/xray-core/proxy/shadowsocks" 11 "github.com/xtls/xray-core/proxy/shadowsocks_2022" 12 "google.golang.org/protobuf/proto" 13 ) 14 15 func cipherFromString(c string) shadowsocks.CipherType { 16 switch strings.ToLower(c) { 17 case "aes-128-gcm", "aead_aes_128_gcm": 18 return shadowsocks.CipherType_AES_128_GCM 19 case "aes-256-gcm", "aead_aes_256_gcm": 20 return shadowsocks.CipherType_AES_256_GCM 21 case "chacha20-poly1305", "aead_chacha20_poly1305", "chacha20-ietf-poly1305": 22 return shadowsocks.CipherType_CHACHA20_POLY1305 23 case "xchacha20-poly1305", "aead_xchacha20_poly1305", "xchacha20-ietf-poly1305": 24 return shadowsocks.CipherType_XCHACHA20_POLY1305 25 case "none", "plain": 26 return shadowsocks.CipherType_NONE 27 default: 28 return shadowsocks.CipherType_UNKNOWN 29 } 30 } 31 32 type ShadowsocksUserConfig struct { 33 Cipher string `json:"method"` 34 Password string `json:"password"` 35 Level byte `json:"level"` 36 Email string `json:"email"` 37 Address *Address `json:"address"` 38 Port uint16 `json:"port"` 39 } 40 41 type ShadowsocksServerConfig struct { 42 Cipher string `json:"method"` 43 Password string `json:"password"` 44 Level byte `json:"level"` 45 Email string `json:"email"` 46 Users []*ShadowsocksUserConfig `json:"clients"` 47 NetworkList *NetworkList `json:"network"` 48 IVCheck bool `json:"ivCheck"` 49 } 50 51 func (v *ShadowsocksServerConfig) Build() (proto.Message, error) { 52 if C.Contains(shadowaead_2022.List, v.Cipher) { 53 return buildShadowsocks2022(v) 54 } 55 56 config := new(shadowsocks.ServerConfig) 57 config.Network = v.NetworkList.Build() 58 59 if v.Users != nil { 60 for _, user := range v.Users { 61 account := &shadowsocks.Account{ 62 Password: user.Password, 63 CipherType: cipherFromString(user.Cipher), 64 IvCheck: v.IVCheck, 65 } 66 if account.Password == "" { 67 return nil, newError("Shadowsocks password is not specified.") 68 } 69 if account.CipherType < shadowsocks.CipherType_AES_128_GCM || 70 account.CipherType > shadowsocks.CipherType_XCHACHA20_POLY1305 { 71 return nil, newError("unsupported cipher method: ", user.Cipher) 72 } 73 config.Users = append(config.Users, &protocol.User{ 74 Email: user.Email, 75 Level: uint32(user.Level), 76 Account: serial.ToTypedMessage(account), 77 }) 78 } 79 } else { 80 account := &shadowsocks.Account{ 81 Password: v.Password, 82 CipherType: cipherFromString(v.Cipher), 83 IvCheck: v.IVCheck, 84 } 85 if account.Password == "" { 86 return nil, newError("Shadowsocks password is not specified.") 87 } 88 if account.CipherType == shadowsocks.CipherType_UNKNOWN { 89 return nil, newError("unknown cipher method: ", v.Cipher) 90 } 91 config.Users = append(config.Users, &protocol.User{ 92 Email: v.Email, 93 Level: uint32(v.Level), 94 Account: serial.ToTypedMessage(account), 95 }) 96 } 97 98 return config, nil 99 } 100 101 func buildShadowsocks2022(v *ShadowsocksServerConfig) (proto.Message, error) { 102 if len(v.Users) == 0 { 103 config := new(shadowsocks_2022.ServerConfig) 104 config.Method = v.Cipher 105 config.Key = v.Password 106 config.Network = v.NetworkList.Build() 107 config.Email = v.Email 108 return config, nil 109 } 110 111 if v.Cipher == "" { 112 return nil, newError("shadowsocks 2022 (multi-user): missing server method") 113 } 114 if !strings.Contains(v.Cipher, "aes") { 115 return nil, newError("shadowsocks 2022 (multi-user): only blake3-aes-*-gcm methods are supported") 116 } 117 118 if v.Users[0].Address == nil { 119 config := new(shadowsocks_2022.MultiUserServerConfig) 120 config.Method = v.Cipher 121 config.Key = v.Password 122 config.Network = v.NetworkList.Build() 123 124 for _, user := range v.Users { 125 if user.Cipher != "" { 126 return nil, newError("shadowsocks 2022 (multi-user): users must have empty method") 127 } 128 config.Users = append(config.Users, &shadowsocks_2022.User{ 129 Key: user.Password, 130 Email: user.Email, 131 }) 132 } 133 return config, nil 134 } 135 136 config := new(shadowsocks_2022.RelayServerConfig) 137 config.Method = v.Cipher 138 config.Key = v.Password 139 config.Network = v.NetworkList.Build() 140 for _, user := range v.Users { 141 if user.Cipher != "" { 142 return nil, newError("shadowsocks 2022 (relay): users must have empty method") 143 } 144 if user.Address == nil { 145 return nil, newError("shadowsocks 2022 (relay): all users must have relay address") 146 } 147 config.Destinations = append(config.Destinations, &shadowsocks_2022.RelayDestination{ 148 Key: user.Password, 149 Email: user.Email, 150 Address: user.Address.Build(), 151 Port: uint32(user.Port), 152 }) 153 } 154 return config, nil 155 } 156 157 type ShadowsocksServerTarget struct { 158 Address *Address `json:"address"` 159 Port uint16 `json:"port"` 160 Cipher string `json:"method"` 161 Password string `json:"password"` 162 Email string `json:"email"` 163 Level byte `json:"level"` 164 IVCheck bool `json:"ivCheck"` 165 UoT bool `json:"uot"` 166 UoTVersion int `json:"uotVersion"` 167 } 168 169 type ShadowsocksClientConfig struct { 170 Servers []*ShadowsocksServerTarget `json:"servers"` 171 } 172 173 func (v *ShadowsocksClientConfig) Build() (proto.Message, error) { 174 if len(v.Servers) == 0 { 175 return nil, newError("0 Shadowsocks server configured.") 176 } 177 178 if len(v.Servers) == 1 { 179 server := v.Servers[0] 180 if C.Contains(shadowaead_2022.List, server.Cipher) { 181 if server.Address == nil { 182 return nil, newError("Shadowsocks server address is not set.") 183 } 184 if server.Port == 0 { 185 return nil, newError("Invalid Shadowsocks port.") 186 } 187 if server.Password == "" { 188 return nil, newError("Shadowsocks password is not specified.") 189 } 190 191 config := new(shadowsocks_2022.ClientConfig) 192 config.Address = server.Address.Build() 193 config.Port = uint32(server.Port) 194 config.Method = server.Cipher 195 config.Key = server.Password 196 config.UdpOverTcp = server.UoT 197 config.UdpOverTcpVersion = uint32(server.UoTVersion) 198 return config, nil 199 } 200 } 201 202 config := new(shadowsocks.ClientConfig) 203 serverSpecs := make([]*protocol.ServerEndpoint, len(v.Servers)) 204 for idx, server := range v.Servers { 205 if C.Contains(shadowaead_2022.List, server.Cipher) { 206 return nil, newError("Shadowsocks 2022 accept no multi servers") 207 } 208 if server.Address == nil { 209 return nil, newError("Shadowsocks server address is not set.") 210 } 211 if server.Port == 0 { 212 return nil, newError("Invalid Shadowsocks port.") 213 } 214 if server.Password == "" { 215 return nil, newError("Shadowsocks password is not specified.") 216 } 217 account := &shadowsocks.Account{ 218 Password: server.Password, 219 } 220 account.CipherType = cipherFromString(server.Cipher) 221 if account.CipherType == shadowsocks.CipherType_UNKNOWN { 222 return nil, newError("unknown cipher method: ", server.Cipher) 223 } 224 225 account.IvCheck = server.IVCheck 226 227 ss := &protocol.ServerEndpoint{ 228 Address: server.Address.Build(), 229 Port: uint32(server.Port), 230 User: []*protocol.User{ 231 { 232 Level: uint32(server.Level), 233 Email: server.Email, 234 Account: serial.ToTypedMessage(account), 235 }, 236 }, 237 } 238 239 serverSpecs[idx] = ss 240 } 241 242 config.Server = serverSpecs 243 244 return config, nil 245 }