diff --git a/proxy/socks/config/json/config.go b/proxy/socks/config/json/config.go index 2772fbcf..69713847 100644 --- a/proxy/socks/config/json/config.go +++ b/proxy/socks/config/json/config.go @@ -10,21 +10,41 @@ const ( AuthMethodUserPass = "password" ) -type SocksConfig struct { - AuthMethod string `json:"auth"` - Username string `json:"user"` - Password string `json:"pass"` - UDPEnabled bool `json:"udp"` +type SocksAccount struct { + Username string `json:"user"` + Password string `json:"pass"` } -func (config SocksConfig) IsNoAuth() bool { +type SocksConfig struct { + AuthMethod string `json:"auth"` + Accounts []SocksAccount `json:"accounts"` + UDPEnabled bool `json:"udp"` + + accountMap map[string]string +} + +func (config *SocksConfig) Initialize() { + config.accountMap = make(map[string]string) + for _, account := range config.Accounts { + config.accountMap[account.Username] = account.Password + } +} + +func (config *SocksConfig) IsNoAuth() bool { return config.AuthMethod == AuthMethodNoAuth } -func (config SocksConfig) IsPassword() bool { +func (config *SocksConfig) IsPassword() bool { return config.AuthMethod == AuthMethodUserPass } +func (config *SocksConfig) HasAccount(user, pass string) bool { + if actualPass, found := config.accountMap[user]; found { + return actualPass == pass + } + return false +} + func init() { json.RegisterConfigType("socks", config.TypeInbound, func() interface{} { return new(SocksConfig) diff --git a/proxy/socks/protocol/socks.go b/proxy/socks/protocol/socks.go index c39e4b3e..d6a34b06 100644 --- a/proxy/socks/protocol/socks.go +++ b/proxy/socks/protocol/socks.go @@ -107,8 +107,12 @@ type Socks5UserPassRequest struct { password string } -func (request Socks5UserPassRequest) IsValid(username string, password string) bool { - return request.username == username && request.password == password +func (request Socks5UserPassRequest) Username() string { + return request.username +} + +func (request Socks5UserPassRequest) Password() string { + return request.password } func (request Socks5UserPassRequest) AuthDetail() string { diff --git a/proxy/socks/socks.go b/proxy/socks/socks.go index c16ede8e..f632d48c 100644 --- a/proxy/socks/socks.go +++ b/proxy/socks/socks.go @@ -103,7 +103,7 @@ func (server *SocksServer) handleSocks5(reader *v2net.TimeOutReader, writer io.W return err } status := byte(0) - if !upRequest.IsValid(server.config.Username, server.config.Password) { + if server.config.HasAccount(upRequest.Username(), upRequest.Password()) { status = byte(0xFF) } upResponse := protocol.NewSocks5UserPassResponse(status) diff --git a/proxy/socks/socks_test.go b/proxy/socks/socks_test.go index 2cd45375..200770d3 100644 --- a/proxy/socks/socks_test.go +++ b/proxy/socks/socks_test.go @@ -84,8 +84,12 @@ func TestSocksTcpConnectWithUserPass(t *testing.T) { ProtocolValue: "socks", SettingsValue: &json.SocksConfig{ AuthMethod: "noauth", - Username: "userx", - Password: "passy", + Accounts: []json.SocksAccount{ + json.SocksAccount{ + Username: "userx", + Password: "passy", + }, + }, }, }, OutboundConfigValue: &mocks.ConnectionConfig{ diff --git a/proxy/socks/socksfactory.go b/proxy/socks/socksfactory.go index ec44ba76..d3dbaffc 100644 --- a/proxy/socks/socksfactory.go +++ b/proxy/socks/socksfactory.go @@ -8,8 +8,10 @@ import ( type SocksServerFactory struct { } -func (factory SocksServerFactory) Create(vp *core.Point, config interface{}) (core.InboundConnectionHandler, error) { - return NewSocksServer(vp, config.(*json.SocksConfig)), nil +func (factory SocksServerFactory) Create(vp *core.Point, rawConfig interface{}) (core.InboundConnectionHandler, error) { + config := rawConfig.(*json.SocksConfig) + config.Initialize() + return NewSocksServer(vp, config), nil } func init() {