tcp.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package services
  2. import (
  3. "fmt"
  4. "io"
  5. "log"
  6. "net"
  7. "github.com/snail007/goproxy/utils"
  8. "runtime/debug"
  9. "time"
  10. "strconv"
  11. )
  12. type TCP struct {
  13. outPool utils.OutPool
  14. cfg TCPArgs
  15. }
  16. func NewTCP() Service {
  17. return &TCP{
  18. outPool: utils.OutPool{},
  19. cfg: TCPArgs{},
  20. }
  21. }
  22. func (s *TCP) InitService() {
  23. s.InitOutConnPool()
  24. }
  25. func (s *TCP) StopService() {
  26. if s.outPool.Pool != nil {
  27. s.outPool.Pool.ReleaseAll()
  28. }
  29. }
  30. func (s *TCP) Start(args interface{}) (err error) {
  31. s.cfg = args.(TCPArgs)
  32. if *s.cfg.Parent != "" {
  33. log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
  34. } else {
  35. log.Fatalf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local)
  36. }
  37. s.InitService()
  38. host, port, _ := net.SplitHostPort(*s.cfg.Local)
  39. p, _ := strconv.Atoi(port)
  40. sc := utils.NewServerChannel(host, p)
  41. if !*s.cfg.IsTLS {
  42. err = sc.ListenTCP(s.callback)
  43. } else {
  44. err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.callback)
  45. }
  46. if err != nil {
  47. return
  48. }
  49. log.Printf("%s proxy on %s", s.cfg.Protocol(), (*sc.Listener).Addr())
  50. return
  51. }
  52. func (s *TCP) Clean() {
  53. s.StopService()
  54. }
  55. func (s *TCP) callback(inConn net.Conn) {
  56. defer func() {
  57. if err := recover(); err != nil {
  58. log.Printf("%s conn handler crashed with err : %s \nstack: %s", s.cfg.Protocol(), err, string(debug.Stack()))
  59. }
  60. }()
  61. var err error
  62. switch *s.cfg.ParentType {
  63. case TYPE_TCP:
  64. fallthrough
  65. case TYPE_TLS:
  66. err = s.OutToTCP(&inConn)
  67. case TYPE_UDP:
  68. err = s.OutToUDP(&inConn)
  69. default:
  70. err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType)
  71. }
  72. if err != nil {
  73. log.Printf("connect to %s parent %s fail, ERR:%s", *s.cfg.ParentType, *s.cfg.Parent, err)
  74. utils.CloseConn(&inConn)
  75. }
  76. }
  77. func (s *TCP) OutToTCP(inConn *net.Conn) (err error) {
  78. var outConn net.Conn
  79. var _outConn interface{}
  80. _outConn, err = s.outPool.Pool.Get()
  81. if err == nil {
  82. outConn = _outConn.(net.Conn)
  83. }
  84. if err != nil {
  85. log.Printf("connect to %s , err:%s", *s.cfg.Parent, err)
  86. utils.CloseConn(inConn)
  87. return
  88. }
  89. inAddr := (*inConn).RemoteAddr().String()
  90. inLocalAddr := (*inConn).LocalAddr().String()
  91. outAddr := outConn.RemoteAddr().String()
  92. outLocalAddr := outConn.LocalAddr().String()
  93. utils.IoBind((*inConn), outConn, func(isSrcErr bool, err error) {
  94. log.Printf("conn %s - %s - %s -%s released", inAddr, inLocalAddr, outLocalAddr, outAddr)
  95. utils.CloseConn(inConn)
  96. utils.CloseConn(&outConn)
  97. }, func(n int, d bool) {}, 0)
  98. log.Printf("conn %s - %s - %s -%s connected", inAddr, inLocalAddr, outLocalAddr, outAddr)
  99. return
  100. }
  101. func (s *TCP) OutToUDP(inConn *net.Conn) (err error) {
  102. log.Printf("conn created , remote : %s ", (*inConn).RemoteAddr())
  103. for {
  104. srcAddr, body, err := utils.ReadUDPPacket(inConn)
  105. if err == io.EOF || err == io.ErrUnexpectedEOF {
  106. //log.Printf("connection %s released", srcAddr)
  107. utils.CloseConn(inConn)
  108. break
  109. }
  110. //log.Debugf("udp packet revecived:%s,%v", srcAddr, body)
  111. dstAddr, err := net.ResolveUDPAddr("udp", *s.cfg.Parent)
  112. if err != nil {
  113. log.Printf("can't resolve address: %s", err)
  114. utils.CloseConn(inConn)
  115. break
  116. }
  117. clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
  118. conn, err := net.DialUDP("udp", clientSrcAddr, dstAddr)
  119. if err != nil {
  120. log.Printf("connect to udp %s fail,ERR:%s", dstAddr.String(), err)
  121. continue
  122. }
  123. conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
  124. _, err = conn.Write(body)
  125. if err != nil {
  126. log.Printf("send udp packet to %s fail,ERR:%s", dstAddr.String(), err)
  127. continue
  128. }
  129. //log.Debugf("send udp packet to %s success", dstAddr.String())
  130. buf := make([]byte, 512)
  131. len, _, err := conn.ReadFromUDP(buf)
  132. if err != nil {
  133. log.Printf("read udp response from %s fail ,ERR:%s", dstAddr.String(), err)
  134. continue
  135. }
  136. respBody := buf[0:len]
  137. //log.Debugf("revecived udp packet from %s , %v", dstAddr.String(), respBody)
  138. _, err = (*inConn).Write(utils.UDPPacket(srcAddr, respBody))
  139. if err != nil {
  140. log.Printf("send udp response fail ,ERR:%s", err)
  141. utils.CloseConn(inConn)
  142. break
  143. }
  144. //log.Printf("send udp response success ,from:%s", dstAddr.String())
  145. }
  146. return
  147. }
  148. func (s *TCP) InitOutConnPool() {
  149. if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP {
  150. //dur int, isTLS bool, certBytes, keyBytes []byte,
  151. //parent string, timeout int, InitialCap int, MaxCap int
  152. s.outPool = utils.NewOutPool(
  153. *s.cfg.CheckParentInterval,
  154. *s.cfg.ParentType == TYPE_TLS,
  155. s.cfg.CertBytes, s.cfg.KeyBytes,
  156. *s.cfg.Parent,
  157. *s.cfg.Timeout,
  158. *s.cfg.PoolSize,
  159. *s.cfg.PoolSize*2,
  160. )
  161. }
  162. }