request_handler.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package socks
  2. import (
  3. "fmt"
  4. "io"
  5. "net"
  6. "strings"
  7. "github.com/cloudflare/cloudflared/ipaccess"
  8. "github.com/rs/zerolog"
  9. )
  10. // RequestHandler is the functions needed to handle a SOCKS5 command
  11. type RequestHandler interface {
  12. Handle(*Request, io.ReadWriter) error
  13. }
  14. // StandardRequestHandler implements the base socks5 command processing
  15. type StandardRequestHandler struct {
  16. dialer Dialer
  17. accessPolicy *ipaccess.Policy
  18. }
  19. // NewRequestHandler creates a standard SOCKS5 request handler
  20. // This handles the SOCKS5 commands and proxies them to their destination
  21. func NewRequestHandler(dialer Dialer, accessPolicy *ipaccess.Policy) RequestHandler {
  22. return &StandardRequestHandler{
  23. dialer: dialer,
  24. accessPolicy: accessPolicy,
  25. }
  26. }
  27. // Handle processes and responds to socks5 commands
  28. func (h *StandardRequestHandler) Handle(req *Request, conn io.ReadWriter) error {
  29. switch req.Command {
  30. case connectCommand:
  31. return h.handleConnect(conn, req)
  32. case bindCommand:
  33. return h.handleBind(conn, req)
  34. case associateCommand:
  35. return h.handleAssociate(conn, req)
  36. default:
  37. if err := sendReply(conn, commandNotSupported, nil); err != nil {
  38. return fmt.Errorf("Failed to send reply: %v", err)
  39. }
  40. return fmt.Errorf("Unsupported command: %v", req.Command)
  41. }
  42. }
  43. // handleConnect is used to handle a connect command
  44. func (h *StandardRequestHandler) handleConnect(conn io.ReadWriter, req *Request) error {
  45. if h.accessPolicy != nil {
  46. if req.DestAddr.IP == nil {
  47. addr, err := net.ResolveIPAddr("ip", req.DestAddr.FQDN)
  48. if err != nil {
  49. _ = sendReply(conn, ruleFailure, req.DestAddr)
  50. return fmt.Errorf("unable to resolve host to confirm acceess")
  51. }
  52. req.DestAddr.IP = addr.IP
  53. }
  54. if allowed, rule := h.accessPolicy.Allowed(req.DestAddr.IP, req.DestAddr.Port); !allowed {
  55. _ = sendReply(conn, ruleFailure, req.DestAddr)
  56. if rule != nil {
  57. return fmt.Errorf("Connect to %v denied due to iprule: %s", req.DestAddr, rule.String())
  58. }
  59. return fmt.Errorf("Connect to %v denied", req.DestAddr)
  60. }
  61. }
  62. target, localAddr, err := h.dialer.Dial(req.DestAddr.Address())
  63. if err != nil {
  64. msg := err.Error()
  65. resp := hostUnreachable
  66. if strings.Contains(msg, "refused") {
  67. resp = connectionRefused
  68. } else if strings.Contains(msg, "network is unreachable") {
  69. resp = networkUnreachable
  70. }
  71. if err := sendReply(conn, resp, nil); err != nil {
  72. return fmt.Errorf("Failed to send reply: %v", err)
  73. }
  74. return fmt.Errorf("Connect to %v failed: %v", req.DestAddr, err)
  75. }
  76. defer target.Close()
  77. // Send success
  78. if err := sendReply(conn, successReply, localAddr); err != nil {
  79. return fmt.Errorf("Failed to send reply: %v", err)
  80. }
  81. // Start proxying
  82. proxyDone := make(chan error, 2)
  83. go func() {
  84. _, e := io.Copy(target, req.bufConn)
  85. proxyDone <- e
  86. }()
  87. go func() {
  88. _, e := io.Copy(conn, target)
  89. proxyDone <- e
  90. }()
  91. // Wait for both
  92. for i := 0; i < 2; i++ {
  93. e := <-proxyDone
  94. if e != nil {
  95. return e
  96. }
  97. }
  98. return nil
  99. }
  100. // handleBind is used to handle a bind command
  101. // TODO: Support bind command
  102. func (h *StandardRequestHandler) handleBind(conn io.ReadWriter, req *Request) error {
  103. if err := sendReply(conn, commandNotSupported, nil); err != nil {
  104. return fmt.Errorf("Failed to send reply: %v", err)
  105. }
  106. return nil
  107. }
  108. // handleAssociate is used to handle a connect command
  109. // TODO: Support associate command
  110. func (h *StandardRequestHandler) handleAssociate(conn io.ReadWriter, req *Request) error {
  111. if err := sendReply(conn, commandNotSupported, nil); err != nil {
  112. return fmt.Errorf("Failed to send reply: %v", err)
  113. }
  114. return nil
  115. }
  116. func StreamHandler(tunnelConn io.ReadWriter, originConn net.Conn, log *zerolog.Logger) {
  117. dialer := NewConnDialer(originConn)
  118. requestHandler := NewRequestHandler(dialer, nil)
  119. socksServer := NewConnectionHandler(requestHandler)
  120. if err := socksServer.Serve(tunnelConn); err != nil {
  121. log.Debug().Err(err).Msg("Socks stream handler error")
  122. }
  123. }
  124. func StreamNetHandler(tunnelConn io.ReadWriter, accessPolicy *ipaccess.Policy, log *zerolog.Logger) {
  125. dialer := NewNetDialer()
  126. requestHandler := NewRequestHandler(dialer, accessPolicy)
  127. socksServer := NewConnectionHandler(requestHandler)
  128. if err := socksServer.Serve(tunnelConn); err != nil {
  129. log.Debug().Err(err).Msg("Socks stream handler error")
  130. }
  131. }