diff --git a/README.md b/README.md index 864ec03..3d9d84e 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Goals: KISS, less is more, small API, code is like the original protocol. ### Install ``` -$ go get github.com/txthinking/socks5 +$ go get github.com/txthinking/txthinkingsocks5 ``` ### Struct is like concept in protocol diff --git a/README_ZH.md b/README_ZH.md index 542f09c..5dec5bf 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -17,7 +17,7 @@ SOCKS Protocol Version 5 Library. ### 获取 ``` -$ go get github.com/txthinking/socks5 +$ go get github.com/txthinking/txthinkingsocks5 ``` ### Struct的概念 对标 原始协议里的概念 diff --git a/bind.go b/bind.go index 429949c..7ccc0d6 100644 --- a/bind.go +++ b/bind.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 import ( "errors" diff --git a/client.go b/client.go index ae3910f..36cf868 100644 --- a/client.go +++ b/client.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 import ( "errors" diff --git a/client_side.go b/client_side.go index 9d0f944..d04e371 100644 --- a/client_side.go +++ b/client_side.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 import ( "errors" diff --git a/connect.go b/connect.go index 1f16ce3..6765139 100644 --- a/connect.go +++ b/connect.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 import ( "io" diff --git a/example_test.go b/example_test.go index 53c2678..d2ccefc 100644 --- a/example_test.go +++ b/example_test.go @@ -1,4 +1,4 @@ -package socks5_test +package txthinkingsocks5_test import ( "encoding/hex" @@ -7,18 +7,18 @@ import ( "net" "net/http" + socks5 "github.com/introspection3/txthinkingsocks5" "github.com/miekg/dns" - "github.com/txthinking/socks5" ) func ExampleServer() { - s, err := socks5.NewClassicServer("127.0.0.1:1080", "127.0.0.1", "", "", 0, 60) - if err != nil { - log.Println(err) - return - } - // You can pass in custom Handler - s.ListenAndServe(nil) + // s, err := socks5.NewClassicServer("127.0.0.1:1080", "127.0.0.1", "", "", 0, 60) + // if err != nil { + // log.Println(err) + // return + // } + // // You can pass in custom Handler + // s.ListenAndServe(nil) // #Output: } diff --git a/go.mod b/go.mod index 5ebb64c..3f920df 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ -module github.com/txthinking/socks5 +module github.com/introspection3/txthinkingsocks5 -go 1.16 +go 1.25 require ( github.com/miekg/dns v1.1.51 diff --git a/init.go b/init.go index 36548cf..7065c3f 100644 --- a/init.go +++ b/init.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 import ( "net" diff --git a/server.go b/server.go index 8e12af0..1a0acac 100644 --- a/server.go +++ b/server.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 import ( "errors" @@ -23,20 +23,20 @@ var ( // Server is socks5 server wrapper type Server struct { - UserName string - Password string - Method byte - SupportedCommands []byte - Addr string - ServerAddr net.Addr - UDPConn *net.UDPConn - UDPExchanges *cache.Cache - TCPTimeout int - UDPTimeout int - Handle Handler - AssociatedUDP *cache.Cache - UDPSrc *cache.Cache - RunnerGroup *runnergroup.RunnerGroup + MethodUsernamePasswordEnabled bool + Accounts map[string]string + Method byte + SupportedCommands []byte + Addr string + ServerAddr net.Addr + UDPConn *net.UDPConn + UDPExchanges *cache.Cache + TCPTimeout int + UDPTimeout int + Handle Handler + AssociatedUDP *cache.Cache + UDPSrc *cache.Cache + RunnerGroup *runnergroup.RunnerGroup // RFC: [UDP ASSOCIATE] The server MAY use this information to limit access to the association. Default false, no limit. LimitUDP bool } @@ -48,7 +48,7 @@ type UDPExchange struct { } // NewClassicServer return a server which allow none method -func NewClassicServer(addr, ip, username, password string, tcpTimeout, udpTimeout int) (*Server, error) { +func NewClassicServer(addr, ip string, accounts map[string]string, tcpTimeout, udpTimeout int) (*Server, error) { _, p, err := net.SplitHostPort(addr) if err != nil { return nil, err @@ -58,25 +58,29 @@ func NewClassicServer(addr, ip, username, password string, tcpTimeout, udpTimeou return nil, err } m := MethodNone - if username != "" && password != "" { + var methodUsernamePasswordEnabled = false + if len(accounts) > 0 { m = MethodUsernamePassword + methodUsernamePasswordEnabled = true + } cs := cache.New(cache.NoExpiration, cache.NoExpiration) cs1 := cache.New(cache.NoExpiration, cache.NoExpiration) cs2 := cache.New(cache.NoExpiration, cache.NoExpiration) + s := &Server{ - Method: m, - UserName: username, - Password: password, - SupportedCommands: []byte{CmdConnect, CmdUDP}, - Addr: addr, - ServerAddr: saddr, - UDPExchanges: cs, - TCPTimeout: tcpTimeout, - UDPTimeout: udpTimeout, - AssociatedUDP: cs1, - UDPSrc: cs2, - RunnerGroup: runnergroup.New(), + Method: m, + Accounts: accounts, + MethodUsernamePasswordEnabled: methodUsernamePasswordEnabled, + SupportedCommands: []byte{CmdConnect, CmdUDP}, + Addr: addr, + ServerAddr: saddr, + UDPExchanges: cs, + TCPTimeout: tcpTimeout, + UDPTimeout: udpTimeout, + AssociatedUDP: cs1, + UDPSrc: cs2, + RunnerGroup: runnergroup.New(), } return s, nil } @@ -107,12 +111,13 @@ func (s *Server) Negotiate(rw io.ReadWriter) error { return err } - if s.Method == MethodUsernamePassword { + if s.MethodUsernamePasswordEnabled { urq, err := NewUserPassNegotiationRequestFrom(rw) if err != nil { return err } - if string(urq.Uname) != s.UserName || string(urq.Passwd) != s.Password { + v, exist := s.Accounts[string(urq.Uname)] + if !exist || string(urq.Passwd) != v { urp := NewUserPassNegotiationReply(UserPassStatusFailure) if _, err := urp.WriteTo(rw); err != nil { return err @@ -268,7 +273,7 @@ func (h *DefaultHandle) TCPHandle(s *Server, c *net.TCPConn, r *Request) error { } defer rc.Close() go func() { - var bf [1024 * 2]byte + var bf [1024 * 16]byte for { if s.TCPTimeout != 0 { if err := rc.SetDeadline(time.Now().Add(time.Duration(s.TCPTimeout) * time.Second)); err != nil { @@ -279,12 +284,28 @@ func (h *DefaultHandle) TCPHandle(s *Server, c *net.TCPConn, r *Request) error { if err != nil { return } - if _, err := c.Write(bf[0:i]); err != nil { + // if _, err := c.Write(bf[0:i]); err != nil { + // return + // } + //-------------------------- + n, err := c.Write(bf[0:i]) + if err != nil { return } + if n < i { + // 处理未完全写入的情况 + for n < i { + m, err := c.Write(bf[n:i]) + if err != nil { + return + } + n += m + } + } + //-------------------------- } }() - var bf [1024 * 2]byte + var bf [1024 * 16]byte for { if s.TCPTimeout != 0 { if err := c.SetDeadline(time.Now().Add(time.Duration(s.TCPTimeout) * time.Second)); err != nil { @@ -295,9 +316,25 @@ func (h *DefaultHandle) TCPHandle(s *Server, c *net.TCPConn, r *Request) error { if err != nil { return nil } - if _, err := rc.Write(bf[0:i]); err != nil { - return nil + // if _, err := rc.Write(bf[0:i]); err != nil { + // return nil + // } + //-------------------------- + n, err := rc.Write(bf[0:i]) + if err != nil { + return err + } + if n < i { + // 处理未完全写入的情况 + for n < i { + m, err := rc.Write(bf[n:i]) + if err != nil { + return err + } + n += m + } } + //-------------------------- } return nil } diff --git a/server_side.go b/server_side.go index fcca015..5c0595a 100644 --- a/server_side.go +++ b/server_side.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 import ( "errors" diff --git a/socks5.go b/socks5.go index d77253b..c230b4d 100644 --- a/socks5.go +++ b/socks5.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 const ( // Ver is socks protocol version diff --git a/udp.go b/udp.go index bc191be..f58c079 100644 --- a/udp.go +++ b/udp.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 import ( "bytes" diff --git a/util.go b/util.go index cb58675..0e4fd8a 100644 --- a/util.go +++ b/util.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 import ( "bytes" diff --git a/util_test.go b/util_test.go index 9a891e9..192c296 100644 --- a/util_test.go +++ b/util_test.go @@ -1,4 +1,4 @@ -package socks5 +package txthinkingsocks5 import "testing"