Break on legacy multiple endpoints/users config

pull/5144/head
𐲓𐳛𐳪𐳂𐳐 𐲀𐳢𐳦𐳫𐳢 𐲥𐳔𐳛𐳪𐳌𐳑𐳖𐳇 2025-09-13 21:47:58 +08:00 committed by GitHub
parent 8add78c02b
commit 746afef8fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 56 additions and 58 deletions

View File

@ -64,25 +64,24 @@ type HTTPClientConfig struct {
func (v *HTTPClientConfig) Build() (proto.Message, error) {
config := new(http.ClientConfig)
if v.Address != nil {
if len(v.Username) == 0 {
v.Servers = []*HTTPRemoteConfig{
{
Address: v.Address,
Port: v.Port,
},
}
} else {
v.Servers = []*HTTPRemoteConfig{
{
Address: v.Address,
Port: v.Port,
Users: []json.RawMessage{{}},
},
}
v.Servers = []*HTTPRemoteConfig{
{
Address: v.Address,
Port: v.Port,
},
}
if len(v.Username) > 0 {
v.Servers[0].Users = []json.RawMessage{{}}
}
}
if len(v.Servers) != 1 {
return nil, errors.New(`HTTP settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple HTTP outbounds and routing balancer instead`)
}
config.Server = make([]*protocol.ServerEndpoint, len(v.Servers))
for idx, serverConfig := range v.Servers {
if len(serverConfig.Users) > 1 {
return nil, errors.New(`HTTP servers: "users" should have one member at most. Multiple members in "users" should use multiple HTTP outbounds and routing balancer instead`)
}
server := &protocol.ServerEndpoint{
Address: serverConfig.Address.Build(),
Port: uint32(serverConfig.Port),

View File

@ -172,16 +172,16 @@ type ShadowsocksServerTarget struct {
}
type ShadowsocksClientConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level byte `json:"level"`
Email string `json:"email"`
Cipher string `json:"method"`
Password string `json:"password"`
IVCheck bool `json:"ivCheck"`
UoT bool `json:"uot"`
UoTVersion int `json:"uotVersion"`
Servers []*ShadowsocksServerTarget `json:"servers"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level byte `json:"level"`
Email string `json:"email"`
Cipher string `json:"method"`
Password string `json:"password"`
IVCheck bool `json:"ivCheck"`
UoT bool `json:"uot"`
UoTVersion int `json:"uotVersion"`
Servers []*ShadowsocksServerTarget `json:"servers"`
}
func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
@ -200,8 +200,8 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
},
}
}
if len(v.Servers) == 0 {
return nil, errors.New("0 Shadowsocks server configured.")
if len(v.Servers) != 1 {
return nil, errors.New(`Shadowsocks settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple Shadowsocks outbounds and routing balancer instead`)
}
if len(v.Servers) == 1 {

View File

@ -82,25 +82,24 @@ type SocksClientConfig struct {
func (v *SocksClientConfig) Build() (proto.Message, error) {
config := new(socks.ClientConfig)
if v.Address != nil {
if len(v.Username) == 0 {
v.Servers = []*SocksRemoteConfig{
{
Address: v.Address,
Port: v.Port,
},
}
} else {
v.Servers = []*SocksRemoteConfig{
{
Address: v.Address,
Port: v.Port,
Users: []json.RawMessage{{}},
},
}
v.Servers = []*SocksRemoteConfig{
{
Address: v.Address,
Port: v.Port,
},
}
if len(v.Username) > 0 {
v.Servers[0].Users = []json.RawMessage{{}}
}
}
if len(v.Servers) != 1 {
return nil, errors.New(`SOCKS settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple SOCKS outbounds and routing balancer instead`)
}
config.Server = make([]*protocol.ServerEndpoint, len(v.Servers))
for idx, serverConfig := range v.Servers {
if len(serverConfig.Users) > 1 {
return nil, errors.New(`SOCKS servers: "users" should have one member at most. Multiple members in "users" should use multiple SOCKS outbounds and routing balancer instead`)
}
server := &protocol.ServerEndpoint{
Address: serverConfig.Address.Build(),
Port: uint32(serverConfig.Port),

View File

@ -28,13 +28,13 @@ type TrojanServerTarget struct {
// TrojanClientConfig is configuration of trojan servers
type TrojanClientConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level byte `json:"level"`
Email string `json:"email"`
Password string `json:"password"`
Flow string `json:"flow"`
Servers []*TrojanServerTarget `json:"servers"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level byte `json:"level"`
Email string `json:"email"`
Password string `json:"password"`
Flow string `json:"flow"`
Servers []*TrojanServerTarget `json:"servers"`
}
// Build implements Buildable
@ -51,8 +51,8 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
},
}
}
if len(c.Servers) == 0 {
return nil, errors.New("0 Trojan server configured.")
if len(c.Servers) != 1 {
return nil, errors.New(`Trojan settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple Trojan outbounds and routing balancer instead`)
}
config := &trojan.ClientConfig{

View File

@ -228,7 +228,7 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
}
}
if len(c.Vnext) != 1 {
return nil, errors.New(`VLESS settings: "vnext" should have one and only one member`)
return nil, errors.New(`VLESS settings: "vnext" should have one and only one member. Multiple endpoints in "vnext" should use multiple VLESS outbounds and routing balancer instead`)
}
config.Vnext = make([]*protocol.ServerEndpoint, len(c.Vnext))
for idx, rec := range c.Vnext {
@ -236,7 +236,7 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
return nil, errors.New(`VLESS vnext: "address" is not set`)
}
if len(rec.Users) != 1 {
return nil, errors.New(`VLESS vnext: "users" should have one and only one member`)
return nil, errors.New(`VLESS vnext: "users" should have one and only one member. Multiple members in "users" should use multiple VLESS outbounds and routing balancer instead`)
}
spec := &protocol.ServerEndpoint{
Address: rec.Address.Build(),

View File

@ -139,16 +139,16 @@ func (c *VMessOutboundConfig) Build() (proto.Message, error) {
},
}
}
if len(c.Receivers) == 0 {
return nil, errors.New("0 VMess receiver configured")
if len(c.Receivers) != 1 {
return nil, errors.New(`VMess settings: "vnext" should have one and only one member. Multiple endpoints in "vnext" should use multiple VMess outbounds and routing balancer instead`)
}
serverSpecs := make([]*protocol.ServerEndpoint, len(c.Receivers))
for idx, rec := range c.Receivers {
if len(rec.Users) == 0 {
return nil, errors.New("0 user configured for VMess outbound")
if len(rec.Users) != 1 {
return nil, errors.New(`VMess vnext: "users" should have one and only one member. Multiple members in "users" should use multiple VMess outbounds and routing balancer instead`)
}
if rec.Address == nil {
return nil, errors.New("address is not set in VMess outbound config")
return nil, errors.New(`VMess vnext: "address" is not set`)
}
spec := &protocol.ServerEndpoint{
Address: rec.Address.Build(),