socks.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package socks
  2. import (
  3. "errors"
  4. "io"
  5. "net"
  6. "github.com/v2ray/v2ray-core"
  7. socksio "github.com/v2ray/v2ray-core/io/socks"
  8. )
  9. var (
  10. ErrorAuthenticationFailed = errors.New("None of the authentication methods is allowed.")
  11. ErrorCommandNotSupported = errors.New("Client requested an unsupported command.")
  12. )
  13. // SocksServer is a SOCKS 5 proxy server
  14. type SocksServer struct {
  15. accepting bool
  16. vPoint *core.VPoint
  17. }
  18. func NewSocksServer(vp *core.VPoint) *SocksServer {
  19. server := new(SocksServer)
  20. server.vPoint = vp
  21. return server
  22. }
  23. func (server *SocksServer) Listen(port uint8) error {
  24. listener, err := net.Listen("tcp", ":"+string(port))
  25. if err != nil {
  26. return err
  27. }
  28. server.accepting = true
  29. go server.AcceptConnections(listener)
  30. return nil
  31. }
  32. func (server *SocksServer) AcceptConnections(listener net.Listener) error {
  33. for server.accepting {
  34. connection, err := listener.Accept()
  35. if err != nil {
  36. return err
  37. }
  38. go server.HandleConnection(connection)
  39. }
  40. return nil
  41. }
  42. func (server *SocksServer) HandleConnection(connection net.Conn) error {
  43. defer connection.Close()
  44. auth, err := socksio.ReadAuthentication(connection)
  45. if err != nil {
  46. return err
  47. }
  48. if auth.HasAuthMethod(socksio.AuthNotRequired) {
  49. return ErrorAuthenticationFailed
  50. }
  51. authResponse := socksio.NewAuthenticationResponse(socksio.AuthNotRequired)
  52. socksio.WriteAuthentication(connection, authResponse)
  53. request, err := socksio.ReadRequest(connection)
  54. if err != nil {
  55. return err
  56. }
  57. if request.Command == socksio.CmdBind || request.Command == socksio.CmdUdpAssociate {
  58. response := socksio.NewSocks5Response()
  59. response.Error = socksio.ErrorCommandNotSupported
  60. socksio.WriteResponse(connection, response)
  61. return ErrorCommandNotSupported
  62. }
  63. ray := server.vPoint.NewInboundConnectionAccepted(request.Destination())
  64. input := ray.InboundInput()
  65. output := ray.InboundOutput()
  66. finish := make(chan bool, 2)
  67. go server.dumpInput(connection, input, finish)
  68. go server.dumpOutput(connection, output, finish)
  69. server.waitForFinish(finish)
  70. return nil
  71. }
  72. func (server *SocksServer) dumpInput(conn net.Conn, input chan<- []byte, finish chan<- bool) {
  73. for {
  74. buffer := make([]byte, 256)
  75. nBytes, err := conn.Read(buffer)
  76. if err == io.EOF {
  77. finish <- true
  78. break
  79. }
  80. input <- buffer[:nBytes]
  81. }
  82. }
  83. func (server *SocksServer) dumpOutput(conn net.Conn, output <-chan []byte, finish chan<- bool) {
  84. for {
  85. buffer, open := <-output
  86. if !open {
  87. finish <- true
  88. break
  89. }
  90. conn.Write(buffer)
  91. }
  92. }
  93. func (server *SocksServer) waitForFinish(finish <-chan bool) {
  94. for i := 0; i < 2; i++ {
  95. <-finish
  96. }
  97. }