1
0

vistor.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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 client
  15. import (
  16. "io"
  17. "sync"
  18. "time"
  19. "github.com/fatedier/frp/models/config"
  20. "github.com/fatedier/frp/models/msg"
  21. frpIo "github.com/fatedier/frp/utils/io"
  22. "github.com/fatedier/frp/utils/log"
  23. frpNet "github.com/fatedier/frp/utils/net"
  24. "github.com/fatedier/frp/utils/util"
  25. )
  26. // Vistor is used for forward traffics from local port tot remote service.
  27. type Vistor interface {
  28. Run() error
  29. Close()
  30. log.Logger
  31. }
  32. func NewVistor(ctl *Control, pxyConf config.ProxyConf) (vistor Vistor) {
  33. baseVistor := BaseVistor{
  34. ctl: ctl,
  35. Logger: log.NewPrefixLogger(pxyConf.GetName()),
  36. }
  37. switch cfg := pxyConf.(type) {
  38. case *config.StcpProxyConf:
  39. vistor = &StcpVistor{
  40. BaseVistor: baseVistor,
  41. cfg: cfg,
  42. }
  43. }
  44. return
  45. }
  46. type BaseVistor struct {
  47. ctl *Control
  48. l frpNet.Listener
  49. closed bool
  50. mu sync.RWMutex
  51. log.Logger
  52. }
  53. type StcpVistor struct {
  54. BaseVistor
  55. cfg *config.StcpProxyConf
  56. }
  57. func (sv *StcpVistor) Run() (err error) {
  58. sv.l, err = frpNet.ListenTcp(sv.cfg.BindAddr, int64(sv.cfg.BindPort))
  59. if err != nil {
  60. return
  61. }
  62. go sv.worker()
  63. return
  64. }
  65. func (sv *StcpVistor) Close() {
  66. sv.l.Close()
  67. }
  68. func (sv *StcpVistor) worker() {
  69. for {
  70. conn, err := sv.l.Accept()
  71. if err != nil {
  72. sv.Warn("stcp local listener closed")
  73. return
  74. }
  75. go sv.handleConn(conn)
  76. }
  77. }
  78. func (sv *StcpVistor) handleConn(userConn frpNet.Conn) {
  79. defer userConn.Close()
  80. sv.Debug("get a new stcp user connection")
  81. vistorConn, err := sv.ctl.connectServer()
  82. if err != nil {
  83. return
  84. }
  85. defer vistorConn.Close()
  86. now := time.Now().Unix()
  87. newVistorConnMsg := &msg.NewVistorConn{
  88. ProxyName: sv.cfg.ServerName,
  89. SignKey: util.GetAuthKey(sv.cfg.Sk, now),
  90. Timestamp: now,
  91. UseEncryption: sv.cfg.UseEncryption,
  92. UseCompression: sv.cfg.UseCompression,
  93. }
  94. err = msg.WriteMsg(vistorConn, newVistorConnMsg)
  95. if err != nil {
  96. sv.Warn("send newVistorConnMsg to server error: %v", err)
  97. return
  98. }
  99. var newVistorConnRespMsg msg.NewVistorConnResp
  100. vistorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
  101. err = msg.ReadMsgInto(vistorConn, &newVistorConnRespMsg)
  102. if err != nil {
  103. sv.Warn("get newVistorConnRespMsg error: %v", err)
  104. return
  105. }
  106. vistorConn.SetReadDeadline(time.Time{})
  107. if newVistorConnRespMsg.Error != "" {
  108. sv.Warn("start new vistor connection error: %s", newVistorConnRespMsg.Error)
  109. return
  110. }
  111. var remote io.ReadWriteCloser
  112. remote = vistorConn
  113. if sv.cfg.UseEncryption {
  114. remote, err = frpIo.WithEncryption(remote, []byte(sv.cfg.Sk))
  115. if err != nil {
  116. sv.Error("create encryption stream error: %v", err)
  117. return
  118. }
  119. }
  120. if sv.cfg.UseCompression {
  121. remote = frpIo.WithCompression(remote)
  122. }
  123. frpIo.Join(userConn, remote)
  124. }