socks.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Package socks implements essential parts of SOCKS protocol.
  2. package socks
  3. import (
  4. "io"
  5. "net"
  6. "strconv"
  7. )
  8. // UDPEnabled is the toggle for UDP support
  9. var UDPEnabled = false
  10. // SOCKS request commands as defined in RFC 1928 section 4.
  11. const (
  12. CmdConnect = 1
  13. CmdBind = 2
  14. CmdUDPAssociate = 3
  15. )
  16. // SOCKS address types as defined in RFC 1928 section 5.
  17. const (
  18. AtypIPv4 = 1
  19. AtypDomainName = 3
  20. AtypIPv6 = 4
  21. )
  22. // Error represents a SOCKS error
  23. type Error byte
  24. func (err Error) Error() string {
  25. return "SOCKS error: " + strconv.Itoa(int(err))
  26. }
  27. // SOCKS errors as defined in RFC 1928 section 6.
  28. const (
  29. ErrGeneralFailure = Error(1)
  30. ErrConnectionNotAllowed = Error(2)
  31. ErrNetworkUnreachable = Error(3)
  32. ErrHostUnreachable = Error(4)
  33. ErrConnectionRefused = Error(5)
  34. ErrTTLExpired = Error(6)
  35. ErrCommandNotSupported = Error(7)
  36. ErrAddressNotSupported = Error(8)
  37. InfoUDPAssociate = Error(9)
  38. )
  39. // MaxAddrLen is the maximum size of SOCKS address in bytes.
  40. const MaxAddrLen = 1 + 1 + 255 + 2
  41. // Addr represents a SOCKS address as defined in RFC 1928 section 5.
  42. type Addr []byte
  43. // String serializes SOCKS address a to string form.
  44. func (a Addr) String() string {
  45. var host, port string
  46. switch a[0] { // address type
  47. case AtypDomainName:
  48. host = string(a[2 : 2+int(a[1])])
  49. port = strconv.Itoa((int(a[2+int(a[1])]) << 8) | int(a[2+int(a[1])+1]))
  50. case AtypIPv4:
  51. host = net.IP(a[1 : 1+net.IPv4len]).String()
  52. port = strconv.Itoa((int(a[1+net.IPv4len]) << 8) | int(a[1+net.IPv4len+1]))
  53. case AtypIPv6:
  54. host = net.IP(a[1 : 1+net.IPv6len]).String()
  55. port = strconv.Itoa((int(a[1+net.IPv6len]) << 8) | int(a[1+net.IPv6len+1]))
  56. }
  57. return net.JoinHostPort(host, port)
  58. }
  59. func readAddr(r io.Reader, b []byte) (Addr, error) {
  60. if len(b) < MaxAddrLen {
  61. return nil, io.ErrShortBuffer
  62. }
  63. _, err := io.ReadFull(r, b[:1]) // read 1st byte for address type
  64. if err != nil {
  65. return nil, err
  66. }
  67. switch b[0] {
  68. case AtypDomainName:
  69. _, err = io.ReadFull(r, b[1:2]) // read 2nd byte for domain length
  70. if err != nil {
  71. return nil, err
  72. }
  73. _, err = io.ReadFull(r, b[2:2+int(b[1])+2])
  74. return b[:1+1+int(b[1])+2], err
  75. case AtypIPv4:
  76. _, err = io.ReadFull(r, b[1:1+net.IPv4len+2])
  77. return b[:1+net.IPv4len+2], err
  78. case AtypIPv6:
  79. _, err = io.ReadFull(r, b[1:1+net.IPv6len+2])
  80. return b[:1+net.IPv6len+2], err
  81. }
  82. return nil, ErrAddressNotSupported
  83. }
  84. // ReadAddr reads just enough bytes from r to get a valid Addr.
  85. func ReadAddr(r io.Reader) (Addr, error) {
  86. return readAddr(r, make([]byte, MaxAddrLen))
  87. }
  88. // SplitAddr slices a SOCKS address from beginning of b. Returns nil if failed.
  89. func SplitAddr(b []byte) Addr {
  90. addrLen := 1
  91. if len(b) < addrLen {
  92. return nil
  93. }
  94. switch b[0] {
  95. case AtypDomainName:
  96. if len(b) < 2 {
  97. return nil
  98. }
  99. addrLen = 1 + 1 + int(b[1]) + 2
  100. case AtypIPv4:
  101. addrLen = 1 + net.IPv4len + 2
  102. case AtypIPv6:
  103. addrLen = 1 + net.IPv6len + 2
  104. default:
  105. return nil
  106. }
  107. if len(b) < addrLen {
  108. return nil
  109. }
  110. return b[:addrLen]
  111. }
  112. // ParseAddr parses the address in string s. Returns nil if failed.
  113. func ParseAddr(s string) Addr {
  114. var addr Addr
  115. host, port, err := net.SplitHostPort(s)
  116. if err != nil {
  117. return nil
  118. }
  119. if ip := net.ParseIP(host); ip != nil {
  120. if ip4 := ip.To4(); ip4 != nil {
  121. addr = make([]byte, 1+net.IPv4len+2)
  122. addr[0] = AtypIPv4
  123. copy(addr[1:], ip4)
  124. } else {
  125. addr = make([]byte, 1+net.IPv6len+2)
  126. addr[0] = AtypIPv6
  127. copy(addr[1:], ip)
  128. }
  129. } else {
  130. if len(host) > 255 {
  131. return nil
  132. }
  133. addr = make([]byte, 1+1+len(host)+2)
  134. addr[0] = AtypDomainName
  135. addr[1] = byte(len(host))
  136. copy(addr[2:], host)
  137. }
  138. portnum, err := strconv.ParseUint(port, 10, 16)
  139. if err != nil {
  140. return nil
  141. }
  142. addr[len(addr)-2], addr[len(addr)-1] = byte(portnum>>8), byte(portnum)
  143. return addr
  144. }
  145. // Handshake fast-tracks SOCKS initialization to get target address to connect.
  146. func Handshake(rw io.ReadWriter) (Addr, error) {
  147. // Read RFC 1928 for request and reply structure and sizes.
  148. buf := make([]byte, MaxAddrLen)
  149. // read VER, NMETHODS, METHODS
  150. if _, err := io.ReadFull(rw, buf[:2]); err != nil {
  151. return nil, err
  152. }
  153. nmethods := buf[1]
  154. if _, err := io.ReadFull(rw, buf[:nmethods]); err != nil {
  155. return nil, err
  156. }
  157. // write VER METHOD
  158. if _, err := rw.Write([]byte{5, 0}); err != nil {
  159. return nil, err
  160. }
  161. // read VER CMD RSV ATYP DST.ADDR DST.PORT
  162. if _, err := io.ReadFull(rw, buf[:3]); err != nil {
  163. return nil, err
  164. }
  165. cmd := buf[1]
  166. addr, err := readAddr(rw, buf)
  167. if err != nil {
  168. return nil, err
  169. }
  170. switch cmd {
  171. case CmdConnect:
  172. _, err = rw.Write([]byte{5, 0, 0, 1, 0, 0, 0, 0, 0, 0}) // SOCKS v5, reply succeeded
  173. case CmdUDPAssociate:
  174. if !UDPEnabled {
  175. return nil, ErrCommandNotSupported
  176. }
  177. listenAddr := ParseAddr(rw.(net.Conn).LocalAddr().String())
  178. _, err = rw.Write(append([]byte{5, 0, 0}, listenAddr...)) // SOCKS v5, reply succeeded
  179. if err != nil {
  180. return nil, ErrCommandNotSupported
  181. }
  182. err = InfoUDPAssociate
  183. default:
  184. return nil, ErrCommandNotSupported
  185. }
  186. return addr, err // skip VER, CMD, RSV fields
  187. }