socks.go 5.5 KB

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