diff --git a/README.md b/README.md index 1dd7f77..f46d48a 100644 --- a/README.md +++ b/README.md @@ -538,11 +538,13 @@ vkey=123 [socks5] mode=socks5 server_port=9004 +multi_account=multi_account.conf ``` 项 | 含义 ---|--- mode | socks5 server_port | 在服务端的代理端口 +multi_account | socks5多账号配置文件(可选) ##### 私密代理模式 ```ini diff --git a/bridge/bridge.go b/bridge/bridge.go index 3f2c3a8..e372908 100755 --- a/bridge/bridge.go +++ b/bridge/bridge.go @@ -488,6 +488,7 @@ loop: tl.Password = t.Password tl.LocalPath = t.LocalPath tl.StripPre = t.StripPre + tl.MultiAccount = t.MultiAccount if !client.HasTunnel(tl) { if err := file.GetDb().NewTask(tl); err != nil { logs.Notice("Add task error ", err.Error()) diff --git a/conf/multi_account.conf b/conf/multi_account.conf new file mode 100644 index 0000000..e3cd792 --- /dev/null +++ b/conf/multi_account.conf @@ -0,0 +1,2 @@ +# key -> user | value -> pwd +npc=npc.pwd \ No newline at end of file diff --git a/conf/npc.conf b/conf/npc.conf index d4a31a8..b3dccdb 100644 --- a/conf/npc.conf +++ b/conf/npc.conf @@ -40,6 +40,7 @@ server_port=10000 [socks5] mode=socks5 server_port=19009 +multi_account=multi_account.conf [file] mode=file diff --git a/go.sum b/go.sum index 29de132..d57b283 100644 --- a/go.sum +++ b/go.sum @@ -79,4 +79,4 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= \ No newline at end of file diff --git a/lib/config/config.go b/lib/config/config.go index c35afb7..89a6bfd 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -239,12 +239,37 @@ func dealTunnel(s string) *file.Tunnel { t.LocalPath = item[1] case "strip_pre": t.StripPre = item[1] + case "multi_account": + t.MultiAccount = &file.MultiAccount{} + if b, err := common.ReadAllFromFile(item[1]); err != nil { + panic(err) + } else { + if content, err := common.ParseStr(string(b)); err != nil { + panic(err) + } else { + t.MultiAccount.AccountMap = dealMultiUser(content) + } + } } } return t } +func dealMultiUser(s string) map[string]string { + multiUserMap := make(map[string]string) + for _, v := range splitStr(s) { + item := strings.Split(v, "=") + if len(item) == 0 { + continue + } else if len(item) == 1 { + item = append(item, "") + } + multiUserMap[strings.TrimSpace(item[0])] = item[1] + } + return multiUserMap +} + func delLocalService(s string) *LocalServer { l := new(LocalServer) for _, v := range splitStr(s) { diff --git a/lib/file/obj.go b/lib/file/obj.go index d3a1fbe..15dea37 100644 --- a/lib/file/obj.go +++ b/lib/file/obj.go @@ -124,22 +124,23 @@ func (s *Client) HasHost(h *Host) bool { } type Tunnel struct { - Id int - Port int - ServerIp string - Mode string - Status bool - RunStatus bool - Client *Client - Ports string - Flow *Flow - Password string - Remark string - TargetAddr string - NoStore bool - LocalPath string - StripPre string - Target *Target + Id int + Port int + ServerIp string + Mode string + Status bool + RunStatus bool + Client *Client + Ports string + Flow *Flow + Password string + Remark string + TargetAddr string + NoStore bool + LocalPath string + StripPre string + Target *Target + MultiAccount *MultiAccount Health sync.RWMutex } @@ -184,6 +185,10 @@ type Target struct { sync.RWMutex } +type MultiAccount struct { + AccountMap map[string]string // multi account and pwd +} + func (s *Target) GetRandomTarget() (string, error) { if s.TargetArr == nil { s.TargetArr = strings.Split(s.TargetStr, "\n") diff --git a/server/proxy/socks5.go b/server/proxy/socks5.go index 2fe72c1..d79be72 100755 --- a/server/proxy/socks5.go +++ b/server/proxy/socks5.go @@ -199,7 +199,7 @@ func (s *Sock5ModeServer) handleConn(c net.Conn) { c.Close() return } - if s.task.Client.Cnf.U != "" && s.task.Client.Cnf.P != "" { + if (s.task.Client.Cnf.U != "" && s.task.Client.Cnf.P != "") || (s.task.MultiAccount != nil && len(s.task.MultiAccount.AccountMap) > 0) { buf[1] = UserPassAuth c.Write(buf) if err := s.Auth(c); err != nil { @@ -236,7 +236,22 @@ func (s *Sock5ModeServer) Auth(c net.Conn) error { if _, err := io.ReadAtLeast(c, pass, passLen); err != nil { return err } - if string(user) == s.task.Client.Cnf.U && string(pass) == s.task.Client.Cnf.P { + + var U, P string + if s.task.MultiAccount != nil { + // enable multi user auth + U = string(user) + var ok bool + P, ok = s.task.MultiAccount.AccountMap[U] + if !ok { + return errors.New("验证不通过") + } + } else { + U = s.task.Client.Cnf.U + P = s.task.Client.Cnf.P + } + + if string(user) == U && string(pass) == P { if _, err := c.Write([]byte{userAuthVersion, authSuccess}); err != nil { return err }