stcp.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Copyright 2017 fatedier, fatedier@gmail.com
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package visitor
  15. import (
  16. "io"
  17. "net"
  18. "strconv"
  19. "time"
  20. libio "github.com/fatedier/golib/io"
  21. v1 "github.com/fatedier/frp/pkg/config/v1"
  22. "github.com/fatedier/frp/pkg/msg"
  23. "github.com/fatedier/frp/pkg/util/util"
  24. "github.com/fatedier/frp/pkg/util/xlog"
  25. )
  26. type STCPVisitor struct {
  27. *BaseVisitor
  28. cfg *v1.STCPVisitorConfig
  29. }
  30. func (sv *STCPVisitor) Run() (err error) {
  31. if sv.cfg.BindPort > 0 {
  32. sv.l, err = net.Listen("tcp", net.JoinHostPort(sv.cfg.BindAddr, strconv.Itoa(sv.cfg.BindPort)))
  33. if err != nil {
  34. return
  35. }
  36. go sv.worker()
  37. }
  38. go sv.internalConnWorker()
  39. return
  40. }
  41. func (sv *STCPVisitor) Close() {
  42. sv.BaseVisitor.Close()
  43. }
  44. func (sv *STCPVisitor) worker() {
  45. xl := xlog.FromContextSafe(sv.ctx)
  46. for {
  47. conn, err := sv.l.Accept()
  48. if err != nil {
  49. xl.Warnf("stcp local listener closed")
  50. return
  51. }
  52. go sv.handleConn(conn)
  53. }
  54. }
  55. func (sv *STCPVisitor) internalConnWorker() {
  56. xl := xlog.FromContextSafe(sv.ctx)
  57. for {
  58. conn, err := sv.internalLn.Accept()
  59. if err != nil {
  60. xl.Warnf("stcp internal listener closed")
  61. return
  62. }
  63. go sv.handleConn(conn)
  64. }
  65. }
  66. func (sv *STCPVisitor) handleConn(userConn net.Conn) {
  67. xl := xlog.FromContextSafe(sv.ctx)
  68. defer userConn.Close()
  69. xl.Debugf("get a new stcp user connection")
  70. visitorConn, err := sv.helper.ConnectServer()
  71. if err != nil {
  72. return
  73. }
  74. defer visitorConn.Close()
  75. now := time.Now().Unix()
  76. newVisitorConnMsg := &msg.NewVisitorConn{
  77. RunID: sv.helper.RunID(),
  78. ProxyName: sv.cfg.ServerName,
  79. SignKey: util.GetAuthKey(sv.cfg.SecretKey, now),
  80. Timestamp: now,
  81. UseEncryption: sv.cfg.Transport.UseEncryption,
  82. UseCompression: sv.cfg.Transport.UseCompression,
  83. }
  84. err = msg.WriteMsg(visitorConn, newVisitorConnMsg)
  85. if err != nil {
  86. xl.Warnf("send newVisitorConnMsg to server error: %v", err)
  87. return
  88. }
  89. var newVisitorConnRespMsg msg.NewVisitorConnResp
  90. _ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
  91. err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
  92. if err != nil {
  93. xl.Warnf("get newVisitorConnRespMsg error: %v", err)
  94. return
  95. }
  96. _ = visitorConn.SetReadDeadline(time.Time{})
  97. if newVisitorConnRespMsg.Error != "" {
  98. xl.Warnf("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
  99. return
  100. }
  101. var remote io.ReadWriteCloser
  102. remote = visitorConn
  103. if sv.cfg.Transport.UseEncryption {
  104. remote, err = libio.WithEncryption(remote, []byte(sv.cfg.SecretKey))
  105. if err != nil {
  106. xl.Errorf("create encryption stream error: %v", err)
  107. return
  108. }
  109. }
  110. if sv.cfg.Transport.UseCompression {
  111. var recycleFn func()
  112. remote, recycleFn = libio.WithCompressionFromPool(remote)
  113. defer recycleFn()
  114. }
  115. libio.Join(userConn, remote)
  116. }