proxy.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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. "fmt"
  17. "io"
  18. "net"
  19. "sync"
  20. "github.com/fatedier/frp/models/config"
  21. "github.com/fatedier/frp/models/msg"
  22. "github.com/fatedier/frp/models/proto/tcp"
  23. "github.com/fatedier/frp/models/proto/udp"
  24. "github.com/fatedier/frp/utils/errors"
  25. "github.com/fatedier/frp/utils/log"
  26. frpNet "github.com/fatedier/frp/utils/net"
  27. )
  28. // Proxy defines how to work for different proxy type.
  29. type Proxy interface {
  30. Run() error
  31. // InWorkConn accept work connections registered to server.
  32. InWorkConn(conn frpNet.Conn)
  33. Close()
  34. log.Logger
  35. }
  36. func NewProxy(ctl *Control, pxyConf config.ProxyConf) (pxy Proxy) {
  37. baseProxy := BaseProxy{
  38. ctl: ctl,
  39. Logger: log.NewPrefixLogger(pxyConf.GetName()),
  40. }
  41. switch cfg := pxyConf.(type) {
  42. case *config.TcpProxyConf:
  43. pxy = &TcpProxy{
  44. BaseProxy: baseProxy,
  45. cfg: cfg,
  46. }
  47. case *config.UdpProxyConf:
  48. pxy = &UdpProxy{
  49. BaseProxy: baseProxy,
  50. cfg: cfg,
  51. }
  52. case *config.HttpProxyConf:
  53. pxy = &HttpProxy{
  54. BaseProxy: baseProxy,
  55. cfg: cfg,
  56. }
  57. case *config.HttpsProxyConf:
  58. pxy = &HttpsProxy{
  59. BaseProxy: baseProxy,
  60. cfg: cfg,
  61. }
  62. }
  63. return
  64. }
  65. type BaseProxy struct {
  66. ctl *Control
  67. closed bool
  68. mu sync.RWMutex
  69. log.Logger
  70. }
  71. // TCP
  72. type TcpProxy struct {
  73. BaseProxy
  74. cfg *config.TcpProxyConf
  75. }
  76. func (pxy *TcpProxy) Run() (err error) {
  77. return
  78. }
  79. func (pxy *TcpProxy) Close() {
  80. }
  81. func (pxy *TcpProxy) InWorkConn(conn frpNet.Conn) {
  82. defer conn.Close()
  83. HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, &pxy.cfg.BaseProxyConf, conn)
  84. }
  85. // HTTP
  86. type HttpProxy struct {
  87. BaseProxy
  88. cfg *config.HttpProxyConf
  89. }
  90. func (pxy *HttpProxy) Run() (err error) {
  91. return
  92. }
  93. func (pxy *HttpProxy) Close() {
  94. }
  95. func (pxy *HttpProxy) InWorkConn(conn frpNet.Conn) {
  96. defer conn.Close()
  97. HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, &pxy.cfg.BaseProxyConf, conn)
  98. }
  99. // HTTPS
  100. type HttpsProxy struct {
  101. BaseProxy
  102. cfg *config.HttpsProxyConf
  103. }
  104. func (pxy *HttpsProxy) Run() (err error) {
  105. return
  106. }
  107. func (pxy *HttpsProxy) Close() {
  108. }
  109. func (pxy *HttpsProxy) InWorkConn(conn frpNet.Conn) {
  110. defer conn.Close()
  111. HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, &pxy.cfg.BaseProxyConf, conn)
  112. }
  113. // UDP
  114. type UdpProxy struct {
  115. BaseProxy
  116. cfg *config.UdpProxyConf
  117. localAddr *net.UDPAddr
  118. readCh chan *msg.UdpPacket
  119. sendCh chan *msg.UdpPacket
  120. workConn frpNet.Conn
  121. }
  122. func (pxy *UdpProxy) Run() (err error) {
  123. pxy.localAddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", pxy.cfg.LocalIp, pxy.cfg.LocalPort))
  124. if err != nil {
  125. return
  126. }
  127. return
  128. }
  129. func (pxy *UdpProxy) Close() {
  130. pxy.mu.Lock()
  131. defer pxy.mu.Unlock()
  132. if !pxy.closed {
  133. pxy.closed = true
  134. if pxy.workConn != nil {
  135. pxy.workConn.Close()
  136. }
  137. if pxy.readCh != nil {
  138. close(pxy.readCh)
  139. }
  140. if pxy.sendCh != nil {
  141. close(pxy.sendCh)
  142. }
  143. }
  144. }
  145. func (pxy *UdpProxy) InWorkConn(conn frpNet.Conn) {
  146. pxy.Info("incoming a new work connection for udp proxy")
  147. // close resources releated with old workConn
  148. pxy.Close()
  149. pxy.mu.Lock()
  150. pxy.workConn = conn
  151. pxy.readCh = make(chan *msg.UdpPacket, 64)
  152. pxy.sendCh = make(chan *msg.UdpPacket, 64)
  153. pxy.closed = false
  154. pxy.mu.Unlock()
  155. workConnReaderFn := func(conn net.Conn) {
  156. for {
  157. var udpMsg msg.UdpPacket
  158. if errRet := msg.ReadMsgInto(conn, &udpMsg); errRet != nil {
  159. pxy.Warn("read from workConn for udp error: %v", errRet)
  160. return
  161. }
  162. if errRet := errors.PanicToError(func() {
  163. pxy.Trace("get udp package from workConn: %s", udpMsg.Content)
  164. pxy.readCh <- &udpMsg
  165. }); errRet != nil {
  166. pxy.Info("reader goroutine for udp work connection closed: %v", errRet)
  167. return
  168. }
  169. }
  170. }
  171. workConnSenderFn := func(conn net.Conn) {
  172. var errRet error
  173. for udpMsg := range pxy.sendCh {
  174. pxy.Trace("send udp package to workConn: %s", udpMsg.Content)
  175. if errRet = msg.WriteMsg(conn, udpMsg); errRet != nil {
  176. pxy.Info("sender goroutine for udp work connection closed")
  177. return
  178. }
  179. }
  180. }
  181. go workConnSenderFn(pxy.workConn)
  182. go workConnReaderFn(pxy.workConn)
  183. udp.Forwarder(pxy.localAddr, pxy.readCh, pxy.sendCh)
  184. }
  185. // Common handler for tcp work connections.
  186. func HandleTcpWorkConnection(localInfo *config.LocalSvrConf, baseInfo *config.BaseProxyConf, workConn frpNet.Conn) {
  187. localConn, err := frpNet.ConnectTcpServer(fmt.Sprintf("%s:%d", localInfo.LocalIp, localInfo.LocalPort))
  188. if err != nil {
  189. workConn.Error("connect to local service [%s:%d] error: %v", localInfo.LocalIp, localInfo.LocalPort, err)
  190. return
  191. }
  192. var remote io.ReadWriteCloser
  193. remote = workConn
  194. if baseInfo.UseEncryption {
  195. remote, err = tcp.WithEncryption(remote, []byte(config.ClientCommonCfg.PrivilegeToken))
  196. if err != nil {
  197. workConn.Error("create encryption stream error: %v", err)
  198. return
  199. }
  200. }
  201. if baseInfo.UseCompression {
  202. remote = tcp.WithCompression(remote)
  203. }
  204. workConn.Debug("join connections, localConn(l[%s] r[%s]) workConn(l[%s] r[%s])", localConn.LocalAddr().String(),
  205. localConn.RemoteAddr().String(), workConn.LocalAddr().String(), workConn.RemoteAddr().String())
  206. tcp.Join(localConn, remote)
  207. workConn.Debug("join connections closed")
  208. }