github.com/xmplusdev/xray-core@v1.8.10/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/xmplusdev/xray-core/common/protocol"
     9  	"github.com/xmplusdev/xray-core/common/serial"
    10  	"github.com/xmplusdev/xray-core/proxy/shadowsocks"
    11  	"github.com/xmplusdev/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  }