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) { func (v *HTTPClientConfig) Build() (proto.Message, error) {
config := new(http.ClientConfig) config := new(http.ClientConfig)
if v.Address != nil { if v.Address != nil {
if len(v.Username) == 0 { v.Servers = []*HTTPRemoteConfig{
v.Servers = []*HTTPRemoteConfig{ {
{ Address: v.Address,
Address: v.Address, Port: v.Port,
Port: v.Port, },
},
}
} else {
v.Servers = []*HTTPRemoteConfig{
{
Address: v.Address,
Port: v.Port,
Users: []json.RawMessage{{}},
},
}
} }
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)) config.Server = make([]*protocol.ServerEndpoint, len(v.Servers))
for idx, serverConfig := range 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{ server := &protocol.ServerEndpoint{
Address: serverConfig.Address.Build(), Address: serverConfig.Address.Build(),
Port: uint32(serverConfig.Port), Port: uint32(serverConfig.Port),

View File

@ -172,16 +172,16 @@ type ShadowsocksServerTarget struct {
} }
type ShadowsocksClientConfig struct { type ShadowsocksClientConfig struct {
Address *Address `json:"address"` Address *Address `json:"address"`
Port uint16 `json:"port"` Port uint16 `json:"port"`
Level byte `json:"level"` Level byte `json:"level"`
Email string `json:"email"` Email string `json:"email"`
Cipher string `json:"method"` Cipher string `json:"method"`
Password string `json:"password"` Password string `json:"password"`
IVCheck bool `json:"ivCheck"` IVCheck bool `json:"ivCheck"`
UoT bool `json:"uot"` UoT bool `json:"uot"`
UoTVersion int `json:"uotVersion"` UoTVersion int `json:"uotVersion"`
Servers []*ShadowsocksServerTarget `json:"servers"` Servers []*ShadowsocksServerTarget `json:"servers"`
} }
func (v *ShadowsocksClientConfig) Build() (proto.Message, error) { func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
@ -200,8 +200,8 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
}, },
} }
} }
if len(v.Servers) == 0 { if len(v.Servers) != 1 {
return nil, errors.New("0 Shadowsocks server configured.") 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 { if len(v.Servers) == 1 {

View File

@ -82,25 +82,24 @@ type SocksClientConfig struct {
func (v *SocksClientConfig) Build() (proto.Message, error) { func (v *SocksClientConfig) Build() (proto.Message, error) {
config := new(socks.ClientConfig) config := new(socks.ClientConfig)
if v.Address != nil { if v.Address != nil {
if len(v.Username) == 0 { v.Servers = []*SocksRemoteConfig{
v.Servers = []*SocksRemoteConfig{ {
{ Address: v.Address,
Address: v.Address, Port: v.Port,
Port: v.Port, },
},
}
} else {
v.Servers = []*SocksRemoteConfig{
{
Address: v.Address,
Port: v.Port,
Users: []json.RawMessage{{}},
},
}
} }
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)) config.Server = make([]*protocol.ServerEndpoint, len(v.Servers))
for idx, serverConfig := range 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{ server := &protocol.ServerEndpoint{
Address: serverConfig.Address.Build(), Address: serverConfig.Address.Build(),
Port: uint32(serverConfig.Port), Port: uint32(serverConfig.Port),

View File

@ -28,13 +28,13 @@ type TrojanServerTarget struct {
// TrojanClientConfig is configuration of trojan servers // TrojanClientConfig is configuration of trojan servers
type TrojanClientConfig struct { type TrojanClientConfig struct {
Address *Address `json:"address"` Address *Address `json:"address"`
Port uint16 `json:"port"` Port uint16 `json:"port"`
Level byte `json:"level"` Level byte `json:"level"`
Email string `json:"email"` Email string `json:"email"`
Password string `json:"password"` Password string `json:"password"`
Flow string `json:"flow"` Flow string `json:"flow"`
Servers []*TrojanServerTarget `json:"servers"` Servers []*TrojanServerTarget `json:"servers"`
} }
// Build implements Buildable // Build implements Buildable
@ -51,8 +51,8 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
}, },
} }
} }
if len(c.Servers) == 0 { if len(c.Servers) != 1 {
return nil, errors.New("0 Trojan server configured.") 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{ config := &trojan.ClientConfig{

View File

@ -228,7 +228,7 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
} }
} }
if len(c.Vnext) != 1 { 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)) config.Vnext = make([]*protocol.ServerEndpoint, len(c.Vnext))
for idx, rec := range 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`) return nil, errors.New(`VLESS vnext: "address" is not set`)
} }
if len(rec.Users) != 1 { 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{ spec := &protocol.ServerEndpoint{
Address: rec.Address.Build(), Address: rec.Address.Build(),

View File

@ -139,16 +139,16 @@ func (c *VMessOutboundConfig) Build() (proto.Message, error) {
}, },
} }
} }
if len(c.Receivers) == 0 { if len(c.Receivers) != 1 {
return nil, errors.New("0 VMess receiver configured") 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)) serverSpecs := make([]*protocol.ServerEndpoint, len(c.Receivers))
for idx, rec := range c.Receivers { for idx, rec := range c.Receivers {
if len(rec.Users) == 0 { if len(rec.Users) != 1 {
return nil, errors.New("0 user configured for VMess outbound") 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 { 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{ spec := &protocol.ServerEndpoint{
Address: rec.Address.Build(), Address: rec.Address.Build(),