socks.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package socks
  2. import (
  3. _ "bufio"
  4. "errors"
  5. "io"
  6. "net"
  7. "strconv"
  8. "sync"
  9. "time"
  10. "github.com/v2ray/v2ray-core"
  11. "github.com/v2ray/v2ray-core/common/log"
  12. v2net "github.com/v2ray/v2ray-core/common/net"
  13. protocol "github.com/v2ray/v2ray-core/proxy/socks/protocol"
  14. )
  15. var (
  16. ErrorAuthenticationFailed = errors.New("None of the authentication methods is allowed.")
  17. ErrorCommandNotSupported = errors.New("Client requested an unsupported command.")
  18. ErrorInvalidUser = errors.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. if tcpConn, ok := connection.(*net.TCPConn); ok {
  54. tcpConn.SetKeepAlive(true)
  55. tcpConn.SetKeepAlivePeriod(4 * time.Second)
  56. }
  57. go server.HandleConnection(connection)
  58. }
  59. }
  60. func (server *SocksServer) HandleConnection(connection net.Conn) error {
  61. defer connection.Close()
  62. reader := v2net.NewTimeOutReader(4, connection)
  63. auth, auth4, err := protocol.ReadAuthentication(reader)
  64. if err != nil && err != protocol.ErrorSocksVersion4 {
  65. log.Error("Error on reading authentication: %v", err)
  66. return err
  67. }
  68. var dest v2net.Destination
  69. // TODO refactor this part
  70. if err == protocol.ErrorSocksVersion4 {
  71. result := protocol.Socks4RequestGranted
  72. if auth4.Command == protocol.CmdBind {
  73. result = protocol.Socks4RequestRejected
  74. }
  75. socks4Response := protocol.NewSocks4AuthenticationResponse(result, auth4.Port, auth4.IP[:])
  76. protocol.WriteSocks4AuthenticationResponse(connection, socks4Response)
  77. if result == protocol.Socks4RequestRejected {
  78. return ErrorCommandNotSupported
  79. }
  80. dest = v2net.NewTCPDestination(v2net.IPAddress(auth4.IP[:], auth4.Port))
  81. } else {
  82. expectedAuthMethod := protocol.AuthNotRequired
  83. if server.config.AuthMethod == JsonAuthMethodUserPass {
  84. expectedAuthMethod = protocol.AuthUserPass
  85. }
  86. if !auth.HasAuthMethod(expectedAuthMethod) {
  87. authResponse := protocol.NewAuthenticationResponse(protocol.AuthNoMatchingMethod)
  88. err = protocol.WriteAuthentication(connection, authResponse)
  89. if err != nil {
  90. log.Error("Error on socksio write authentication: %v", err)
  91. return err
  92. }
  93. log.Warning("Client doesn't support allowed any auth methods.")
  94. return ErrorAuthenticationFailed
  95. }
  96. authResponse := protocol.NewAuthenticationResponse(expectedAuthMethod)
  97. err = protocol.WriteAuthentication(connection, authResponse)
  98. if err != nil {
  99. log.Error("Error on socksio write authentication: %v", err)
  100. return err
  101. }
  102. if server.config.AuthMethod == JsonAuthMethodUserPass {
  103. upRequest, err := protocol.ReadUserPassRequest(reader)
  104. if err != nil {
  105. log.Error("Failed to read username and password: %v", err)
  106. return err
  107. }
  108. status := byte(0)
  109. if !upRequest.IsValid(server.config.Username, server.config.Password) {
  110. status = byte(0xFF)
  111. }
  112. upResponse := protocol.NewSocks5UserPassResponse(status)
  113. err = protocol.WriteUserPassResponse(connection, upResponse)
  114. if err != nil {
  115. log.Error("Error on socksio write user pass response: %v", err)
  116. return err
  117. }
  118. if status != byte(0) {
  119. return ErrorInvalidUser
  120. }
  121. }
  122. request, err := protocol.ReadRequest(reader)
  123. if err != nil {
  124. log.Error("Error on reading socks request: %v", err)
  125. return err
  126. }
  127. response := protocol.NewSocks5Response()
  128. if request.Command == protocol.CmdBind || request.Command == protocol.CmdUdpAssociate {
  129. response := protocol.NewSocks5Response()
  130. response.Error = protocol.ErrorCommandNotSupported
  131. err = protocol.WriteResponse(connection, response)
  132. if err != nil {
  133. log.Error("Error on socksio write response: %v", err)
  134. return err
  135. }
  136. log.Warning("Unsupported socks command %d", request.Command)
  137. return ErrorCommandNotSupported
  138. }
  139. response.Error = protocol.ErrorSuccess
  140. response.Port = request.Port
  141. response.AddrType = request.AddrType
  142. switch response.AddrType {
  143. case protocol.AddrTypeIPv4:
  144. copy(response.IPv4[:], request.IPv4[:])
  145. case protocol.AddrTypeIPv6:
  146. copy(response.IPv6[:], request.IPv6[:])
  147. case protocol.AddrTypeDomain:
  148. response.Domain = request.Domain
  149. }
  150. err = protocol.WriteResponse(connection, response)
  151. if err != nil {
  152. log.Error("Error on socksio write response: %v", err)
  153. return err
  154. }
  155. dest = request.Destination()
  156. }
  157. ray := server.vPoint.DispatchToOutbound(v2net.NewTCPPacket(dest))
  158. input := ray.InboundInput()
  159. output := ray.InboundOutput()
  160. var readFinish, writeFinish sync.Mutex
  161. readFinish.Lock()
  162. writeFinish.Lock()
  163. go dumpInput(reader, input, &readFinish)
  164. go dumpOutput(connection, output, &writeFinish)
  165. writeFinish.Lock()
  166. return nil
  167. }
  168. func dumpInput(reader io.Reader, input chan<- []byte, finish *sync.Mutex) {
  169. v2net.ReaderToChan(input, reader)
  170. finish.Unlock()
  171. close(input)
  172. }
  173. func dumpOutput(writer io.Writer, output <-chan []byte, finish *sync.Mutex) {
  174. v2net.ChanToWriter(writer, output)
  175. finish.Unlock()
  176. }