request.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package socks
  2. import (
  3. "fmt"
  4. "io"
  5. "net"
  6. "strconv"
  7. )
  8. const (
  9. // version
  10. socks5Version = uint8(5)
  11. // commands https://tools.ietf.org/html/rfc1928#section-4
  12. connectCommand = uint8(1)
  13. bindCommand = uint8(2)
  14. associateCommand = uint8(3)
  15. // address types
  16. ipv4Address = uint8(1)
  17. fqdnAddress = uint8(3)
  18. ipv6Address = uint8(4)
  19. )
  20. // https://tools.ietf.org/html/rfc1928#section-6
  21. const (
  22. successReply uint8 = iota
  23. serverFailure
  24. ruleFailure
  25. networkUnreachable
  26. hostUnreachable
  27. connectionRefused
  28. ttlExpired
  29. commandNotSupported
  30. addrTypeNotSupported
  31. )
  32. // AddrSpec is used to return the target IPv4, IPv6, or a FQDN
  33. type AddrSpec struct {
  34. FQDN string
  35. IP net.IP
  36. Port int
  37. }
  38. // String gives a host version of the Address
  39. func (a *AddrSpec) String() string {
  40. if a.FQDN != "" {
  41. return fmt.Sprintf("%s (%s):%d", a.FQDN, a.IP, a.Port)
  42. }
  43. return fmt.Sprintf("%s:%d", a.IP, a.Port)
  44. }
  45. // Address returns a string suitable to dial; prefer returning IP-based
  46. // address, fallback to FQDN
  47. func (a AddrSpec) Address() string {
  48. if len(a.IP) != 0 {
  49. return net.JoinHostPort(a.IP.String(), strconv.Itoa(a.Port))
  50. }
  51. return net.JoinHostPort(a.FQDN, strconv.Itoa(a.Port))
  52. }
  53. // Request is a SOCKS5 command with supporting field of the connection
  54. type Request struct {
  55. // Protocol version
  56. Version uint8
  57. // Requested command
  58. Command uint8
  59. // AddrSpec of the destination
  60. DestAddr *AddrSpec
  61. // reading from the connection
  62. bufConn io.Reader
  63. }
  64. // NewRequest creates a new request from the connection data stream
  65. func NewRequest(bufConn io.Reader) (*Request, error) {
  66. // Read the version byte
  67. header := []byte{0, 0, 0}
  68. if _, err := io.ReadAtLeast(bufConn, header, 3); err != nil {
  69. return nil, fmt.Errorf("Failed to get command version: %v", err)
  70. }
  71. // ensure compatibility
  72. if header[0] != socks5Version {
  73. return nil, fmt.Errorf("Unsupported command version: %v", header[0])
  74. }
  75. // Read in the destination address
  76. dest, err := readAddrSpec(bufConn)
  77. if err != nil {
  78. return nil, err
  79. }
  80. return &Request{
  81. Version: socks5Version,
  82. Command: header[1],
  83. DestAddr: dest,
  84. bufConn: bufConn,
  85. }, nil
  86. }
  87. func sendReply(w io.Writer, resp uint8, addr *AddrSpec) error {
  88. var addrType uint8
  89. var addrBody []byte
  90. var addrPort uint16
  91. switch {
  92. case addr == nil:
  93. addrType = ipv4Address
  94. addrBody = []byte{0, 0, 0, 0}
  95. addrPort = 0
  96. case addr.FQDN != "":
  97. addrType = fqdnAddress
  98. addrBody = append([]byte{byte(len(addr.FQDN))}, addr.FQDN...)
  99. addrPort = uint16(addr.Port)
  100. case addr.IP.To4() != nil:
  101. addrType = ipv4Address
  102. addrBody = []byte(addr.IP.To4())
  103. addrPort = uint16(addr.Port)
  104. case addr.IP.To16() != nil:
  105. addrType = ipv6Address
  106. addrBody = []byte(addr.IP.To16())
  107. addrPort = uint16(addr.Port)
  108. default:
  109. return fmt.Errorf("Failed to format address: %v", addr)
  110. }
  111. // Format the message
  112. msg := make([]byte, 6+len(addrBody))
  113. msg[0] = socks5Version
  114. msg[1] = resp
  115. msg[2] = 0 // Reserved
  116. msg[3] = addrType
  117. copy(msg[4:], addrBody)
  118. msg[4+len(addrBody)] = byte(addrPort >> 8)
  119. msg[4+len(addrBody)+1] = byte(addrPort & 0xff)
  120. // Send the message
  121. _, err := w.Write(msg)
  122. return err
  123. }
  124. // readAddrSpec is used to read AddrSpec.
  125. // Expects an address type byte, followed by the address and port
  126. func readAddrSpec(r io.Reader) (*AddrSpec, error) {
  127. d := &AddrSpec{}
  128. // Get the address type
  129. addrType := []byte{0}
  130. if _, err := r.Read(addrType); err != nil {
  131. return nil, err
  132. }
  133. // Handle on a per type basis
  134. switch addrType[0] {
  135. case ipv4Address:
  136. addr := make([]byte, 4)
  137. if _, err := io.ReadAtLeast(r, addr, len(addr)); err != nil {
  138. return nil, err
  139. }
  140. d.IP = net.IP(addr)
  141. case ipv6Address:
  142. addr := make([]byte, 16)
  143. if _, err := io.ReadAtLeast(r, addr, len(addr)); err != nil {
  144. return nil, err
  145. }
  146. d.IP = net.IP(addr)
  147. case fqdnAddress:
  148. if _, err := r.Read(addrType); err != nil {
  149. return nil, err
  150. }
  151. addrLen := int(addrType[0])
  152. fqdn := make([]byte, addrLen)
  153. if _, err := io.ReadAtLeast(r, fqdn, addrLen); err != nil {
  154. return nil, err
  155. }
  156. d.FQDN = string(fqdn)
  157. default:
  158. return nil, fmt.Errorf("Unrecognized address type")
  159. }
  160. // Read the port
  161. port := []byte{0, 0}
  162. if _, err := io.ReadAtLeast(r, port, 2); err != nil {
  163. return nil, err
  164. }
  165. d.Port = (int(port[0]) << 8) | int(port[1])
  166. return d, nil
  167. }