socks5.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package process
  2. import (
  3. "ehang.io/nps/core/action"
  4. "ehang.io/nps/lib/common"
  5. "ehang.io/nps/lib/enet"
  6. "ehang.io/nps/lib/logger"
  7. "encoding/binary"
  8. "github.com/pkg/errors"
  9. "github.com/robfig/go-cache"
  10. "go.uber.org/zap"
  11. "io"
  12. "net"
  13. "strconv"
  14. "time"
  15. )
  16. type Socks5Process struct {
  17. DefaultProcess
  18. Accounts map[string]string `json:"accounts" placeholder:"username1 password1\nusername2 password2" zh_name:"授权账号密码"`
  19. ServerIp string `json:"server_ip" placeholder:"123.123.123.123" zh_name:"udp连接地址"`
  20. ipStore *cache.Cache
  21. }
  22. const (
  23. ipV4 = 1
  24. domainName = 3
  25. ipV6 = 4
  26. connectMethod = 1
  27. bindMethod = 2
  28. associateMethod = 3
  29. // The maximum packet size of any udp Associate packet, based on ethernet's max size,
  30. // minus the IP and UDP headers5. IPv4 has a 20 byte header, UDP adds an
  31. // additional 4 bytes5. This is a total overhead of 24 bytes5. Ethernet's
  32. // max packet size is 1500 bytes, 1500 - 24 = 1476.
  33. maxUDPPacketSize = 1476
  34. )
  35. const (
  36. succeeded uint8 = iota
  37. serverFailure
  38. notAllowed
  39. networkUnreachable
  40. hostUnreachable
  41. connectionRefused
  42. ttlExpired
  43. commandNotSupported
  44. addrTypeNotSupported
  45. )
  46. const (
  47. UserPassAuth = uint8(2)
  48. userAuthVersion = uint8(1)
  49. authSuccess = uint8(0)
  50. authFailure = uint8(1)
  51. )
  52. func (s5 *Socks5Process) GetName() string {
  53. return "socks5"
  54. }
  55. func (s5 *Socks5Process) GetZhName() string {
  56. return "socks5代理"
  57. }
  58. func (s5 *Socks5Process) Init(ac action.Action) error {
  59. s5.ipStore = cache.New(time.Minute, time.Minute*2)
  60. return s5.DefaultProcess.Init(ac)
  61. }
  62. func (s5 *Socks5Process) ProcessConn(c enet.Conn) (bool, error) {
  63. return true, s5.handleConn(c)
  64. }
  65. func (s5 *Socks5Process) ProcessPacketConn(pc enet.PacketConn) (bool, error) {
  66. ip, _, _ := net.SplitHostPort(pc.LocalAddr().String())
  67. if _, ok := s5.ipStore.Get(ip); !ok {
  68. return false, nil
  69. }
  70. _, addr, err := pc.FirstPacket()
  71. if err != nil {
  72. return false, errors.New("addr not found")
  73. }
  74. return true, s5.ac.RunPacketConn(enet.NewS5PacketConn(pc, addr))
  75. }
  76. func (s5 *Socks5Process) handleConn(c enet.Conn) error {
  77. buf := make([]byte, 2)
  78. if _, err := io.ReadFull(c, buf); err != nil {
  79. return err
  80. }
  81. if version := buf[0]; version != 5 {
  82. return errors.New("only support socks5")
  83. }
  84. nMethods := buf[1]
  85. methods := make([]byte, nMethods)
  86. if l, err := c.Read(methods); l != int(nMethods) || err != nil {
  87. return errors.New("wrong method")
  88. }
  89. if len(s5.Accounts) > 0 {
  90. buf[1] = UserPassAuth
  91. _, err := c.Write(buf)
  92. if err != nil {
  93. return err
  94. }
  95. if err := s5.Auth(c); err != nil {
  96. return errors.Wrap(err, "auth failed")
  97. }
  98. } else {
  99. buf[1] = 0
  100. _, _ = c.Write(buf)
  101. }
  102. return s5.handleRequest(c)
  103. }
  104. func (s5 *Socks5Process) Auth(c enet.Conn) error {
  105. header := []byte{0, 0}
  106. if _, err := io.ReadAtLeast(c, header, 2); err != nil {
  107. return err
  108. }
  109. if header[0] != userAuthVersion {
  110. return errors.New("auth type not support")
  111. }
  112. userLen := int(header[1])
  113. user := make([]byte, userLen)
  114. if _, err := io.ReadAtLeast(c, user, userLen); err != nil {
  115. return err
  116. }
  117. if _, err := c.Read(header[:1]); err != nil {
  118. return errors.New("the length of password is incorrect")
  119. }
  120. passLen := int(header[0])
  121. pass := make([]byte, passLen)
  122. if _, err := io.ReadAtLeast(c, pass, passLen); err != nil {
  123. return err
  124. }
  125. p := s5.Accounts[string(user)]
  126. if p == "" || string(pass) != p {
  127. _, _ = c.Write([]byte{userAuthVersion, authFailure})
  128. return errors.New("auth failure")
  129. }
  130. if _, err := c.Write([]byte{userAuthVersion, authSuccess}); err != nil {
  131. return errors.Wrap(err, "write auth success")
  132. }
  133. return nil
  134. }
  135. func (s5 *Socks5Process) handleRequest(c enet.Conn) error {
  136. header := make([]byte, 3)
  137. _, err := io.ReadFull(c, header)
  138. if err != nil {
  139. return err
  140. }
  141. switch header[1] {
  142. case connectMethod:
  143. s5.handleConnect(c)
  144. case associateMethod:
  145. s5.handleUDP(c)
  146. default:
  147. s5.sendReply(c, commandNotSupported)
  148. c.Close()
  149. }
  150. return nil
  151. }
  152. //enet
  153. func (s5 *Socks5Process) handleConnect(c enet.Conn) {
  154. addr, err := common.ReadAddr(c)
  155. if err != nil {
  156. s5.sendReply(c, addrTypeNotSupported)
  157. logger.Warn("read socks addr error", zap.Error(err))
  158. return
  159. }
  160. s5.sendReply(c, succeeded)
  161. _ = s5.ac.RunConnWithAddr(c, addr.String())
  162. return
  163. }
  164. func (s5 *Socks5Process) handleUDP(c net.Conn) {
  165. _, err := common.ReadAddr(c)
  166. if err != nil {
  167. s5.sendReply(c, addrTypeNotSupported)
  168. logger.Warn("read socks addr error", zap.Error(err))
  169. return
  170. }
  171. ip, _, _ := net.SplitHostPort(c.RemoteAddr().String())
  172. s5.ipStore.Set(ip, true, time.Minute)
  173. s5.sendReply(c, succeeded)
  174. }
  175. func (s5 *Socks5Process) sendReply(c net.Conn, rep uint8) {
  176. reply := []byte{
  177. 5,
  178. rep,
  179. 0,
  180. 1,
  181. }
  182. localHost, localPort, _ := net.SplitHostPort(c.LocalAddr().String())
  183. if s5.ServerIp != "" {
  184. localHost = s5.ServerIp
  185. }
  186. ipBytes := net.ParseIP(localHost).To4()
  187. nPort, _ := strconv.Atoi(localPort)
  188. reply = append(reply, ipBytes...)
  189. portBytes := make([]byte, 2)
  190. binary.BigEndian.PutUint16(portBytes, uint16(nPort))
  191. reply = append(reply, portBytes...)
  192. _, _ = c.Write(reply)
  193. }