socks.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package socks
  2. import (
  3. _ "bufio"
  4. e2 "errors"
  5. "io"
  6. "net"
  7. "strconv"
  8. "sync"
  9. "github.com/v2ray/v2ray-core"
  10. "github.com/v2ray/v2ray-core/common/errors"
  11. "github.com/v2ray/v2ray-core/common/log"
  12. v2net "github.com/v2ray/v2ray-core/common/net"
  13. "github.com/v2ray/v2ray-core/proxy/socks/protocol"
  14. )
  15. var (
  16. ErrorAuthenticationFailed = e2.New("None of the authentication methods is allowed.")
  17. ErrorCommandNotSupported = e2.New("Client requested an unsupported command.")
  18. ErrorInvalidUser = e2.New("Invalid username or password.")
  19. )
  20. // SocksServer is a SOCKS 5 proxy server
  21. type SocksServer struct {
  22. accepting bool
  23. vPoint *core.Point
  24. config SocksConfig
  25. }
  26. func NewSocksServer(vp *core.Point, rawConfig []byte) *SocksServer {
  27. config, err := loadConfig(rawConfig)
  28. if err != nil {
  29. panic(log.Error("Unable to load socks config: %v", err))
  30. }
  31. return &SocksServer{
  32. vPoint: vp,
  33. config: config,
  34. }
  35. }
  36. func (server *SocksServer) Listen(port uint16) error {
  37. listener, err := net.Listen("tcp", ":"+strconv.Itoa(int(port)))
  38. if err != nil {
  39. log.Error("Error on listening port %d: %v", port, err)
  40. return err
  41. }
  42. log.Debug("Working on tcp:%d", port)
  43. server.accepting = true
  44. go server.AcceptConnections(listener)
  45. return nil
  46. }
  47. func (server *SocksServer) AcceptConnections(listener net.Listener) {
  48. for server.accepting {
  49. connection, err := listener.Accept()
  50. if err != nil {
  51. log.Error("Error on accepting socks connection: %v", err)
  52. }
  53. go server.HandleConnection(connection)
  54. }
  55. }
  56. func (server *SocksServer) HandleConnection(connection net.Conn) error {
  57. defer connection.Close()
  58. reader := v2net.NewTimeOutReader(4, connection)
  59. auth, auth4, err := protocol.ReadAuthentication(reader)
  60. if err != nil && !errors.HasCode(err, 1000) {
  61. log.Error("Error on reading authentication: %v", err)
  62. return err
  63. }
  64. var dest v2net.Destination
  65. // TODO refactor this part
  66. if errors.HasCode(err, 1000) {
  67. result := protocol.Socks4RequestGranted
  68. if auth4.Command == protocol.CmdBind {
  69. result = protocol.Socks4RequestRejected
  70. }
  71. socks4Response := protocol.NewSocks4AuthenticationResponse(result, auth4.Port, auth4.IP[:])
  72. protocol.WriteSocks4AuthenticationResponse(connection, socks4Response)
  73. if result == protocol.Socks4RequestRejected {
  74. return ErrorCommandNotSupported
  75. }
  76. dest = v2net.NewTCPDestination(v2net.IPAddress(auth4.IP[:], auth4.Port))
  77. } else {
  78. expectedAuthMethod := protocol.AuthNotRequired
  79. if server.config.AuthMethod == JsonAuthMethodUserPass {
  80. expectedAuthMethod = protocol.AuthUserPass
  81. }
  82. if !auth.HasAuthMethod(expectedAuthMethod) {
  83. authResponse := protocol.NewAuthenticationResponse(protocol.AuthNoMatchingMethod)
  84. err = protocol.WriteAuthentication(connection, authResponse)
  85. if err != nil {
  86. log.Error("Error on socksio write authentication: %v", err)
  87. return err
  88. }
  89. log.Warning("Client doesn't support allowed any auth methods.")
  90. return ErrorAuthenticationFailed
  91. }
  92. authResponse := protocol.NewAuthenticationResponse(expectedAuthMethod)
  93. err = protocol.WriteAuthentication(connection, authResponse)
  94. if err != nil {
  95. log.Error("Error on socksio write authentication: %v", err)
  96. return err
  97. }
  98. if server.config.AuthMethod == JsonAuthMethodUserPass {
  99. upRequest, err := protocol.ReadUserPassRequest(reader)
  100. if err != nil {
  101. log.Error("Failed to read username and password: %v", err)
  102. return err
  103. }
  104. status := byte(0)
  105. if !upRequest.IsValid(server.config.Username, server.config.Password) {
  106. status = byte(0xFF)
  107. }
  108. upResponse := protocol.NewSocks5UserPassResponse(status)
  109. err = protocol.WriteUserPassResponse(connection, upResponse)
  110. if err != nil {
  111. log.Error("Error on socksio write user pass response: %v", err)
  112. return err
  113. }
  114. if status != byte(0) {
  115. return ErrorInvalidUser
  116. }
  117. }
  118. request, err := protocol.ReadRequest(reader)
  119. if err != nil {
  120. log.Error("Error on reading socks request: %v", err)
  121. return err
  122. }
  123. response := protocol.NewSocks5Response()
  124. if request.Command == protocol.CmdBind || request.Command == protocol.CmdUdpAssociate {
  125. response := protocol.NewSocks5Response()
  126. response.Error = protocol.ErrorCommandNotSupported
  127. err = protocol.WriteResponse(connection, response)
  128. if err != nil {
  129. log.Error("Error on socksio write response: %v", err)
  130. return err
  131. }
  132. log.Warning("Unsupported socks command %d", request.Command)
  133. return ErrorCommandNotSupported
  134. }
  135. response.Error = protocol.ErrorSuccess
  136. response.Port = request.Port
  137. response.AddrType = request.AddrType
  138. switch response.AddrType {
  139. case protocol.AddrTypeIPv4:
  140. copy(response.IPv4[:], request.IPv4[:])
  141. case protocol.AddrTypeIPv6:
  142. copy(response.IPv6[:], request.IPv6[:])
  143. case protocol.AddrTypeDomain:
  144. response.Domain = request.Domain
  145. }
  146. err = protocol.WriteResponse(connection, response)
  147. if err != nil {
  148. log.Error("Error on socksio write response: %v", err)
  149. return err
  150. }
  151. dest = request.Destination()
  152. }
  153. ray := server.vPoint.DispatchToOutbound(v2net.NewTCPPacket(dest))
  154. input := ray.InboundInput()
  155. output := ray.InboundOutput()
  156. var readFinish, writeFinish sync.Mutex
  157. readFinish.Lock()
  158. writeFinish.Lock()
  159. go dumpInput(reader, input, &readFinish)
  160. go dumpOutput(connection, output, &writeFinish)
  161. writeFinish.Lock()
  162. return nil
  163. }
  164. func dumpInput(reader io.Reader, input chan<- []byte, finish *sync.Mutex) {
  165. v2net.ReaderToChan(input, reader)
  166. finish.Unlock()
  167. close(input)
  168. }
  169. func dumpOutput(writer io.Writer, output <-chan []byte, finish *sync.Mutex) {
  170. v2net.ChanToWriter(writer, output)
  171. finish.Unlock()
  172. }