support protocol quic between frpc and frps (#3198)

This commit is contained in:
fatedier
2022-12-12 11:04:10 +08:00
committed by GitHub
parent 649df8827c
commit 2f66dc3e99
12 changed files with 328 additions and 189 deletions

View File

@@ -28,6 +28,7 @@ import (
"github.com/fatedier/golib/net/mux"
fmux "github.com/hashicorp/yamux"
quic "github.com/lucas-clemente/quic-go"
"github.com/fatedier/frp/assets"
"github.com/fatedier/frp/pkg/auth"
@@ -68,6 +69,9 @@ type Service struct {
// Accept connections using kcp
kcpListener net.Listener
// Accept connections using quic
quicListener quic.Listener
// Accept connections using websocket
websocketListener net.Listener
@@ -200,12 +204,24 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.KCPBindPort))
svr.kcpListener, err = frpNet.ListenKcp(address)
if err != nil {
err = fmt.Errorf("listen on kcp address udp %s error: %v", address, err)
err = fmt.Errorf("listen on kcp udp address %s error: %v", address, err)
return
}
log.Info("frps kcp listen on udp %s", address)
}
if cfg.QUICBindPort > 0 {
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.QUICBindPort))
quicTLSCfg := tlsConfig.Clone()
quicTLSCfg.NextProtos = []string{"frp"}
svr.quicListener, err = quic.ListenAddr(address, quicTLSCfg, nil)
if err != nil {
err = fmt.Errorf("listen on quic udp address %s error: %v", address, err)
return
}
log.Info("frps quic listen on quic %s", address)
}
// Listen for accepting connections from client using websocket protocol.
websocketPrefix := []byte("GET " + frpNet.FrpWebsocketPath)
websocketLn := svr.muxer.Listen(0, uint32(len(websocketPrefix)), func(data []byte) bool {
@@ -310,9 +326,12 @@ func (svr *Service) Run() {
if svr.rc.NatHoleController != nil {
go svr.rc.NatHoleController.Run()
}
if svr.cfg.KCPBindPort > 0 {
if svr.kcpListener != nil {
go svr.HandleListener(svr.kcpListener)
}
if svr.quicListener != nil {
go svr.HandleQUICListener(svr.quicListener)
}
go svr.HandleListener(svr.websocketListener)
go svr.HandleListener(svr.tlsListener)
@@ -437,6 +456,29 @@ func (svr *Service) HandleListener(l net.Listener) {
}
}
func (svr *Service) HandleQUICListener(l quic.Listener) {
// Listen for incoming connections from client.
for {
c, err := l.Accept(context.Background())
if err != nil {
log.Warn("QUICListener for incoming connections from client closed")
return
}
// Start a new goroutine to handle connection.
go func(ctx context.Context, frpConn quic.Connection) {
for {
stream, err := frpConn.AcceptStream(context.Background())
if err != nil {
log.Debug("Accept new quic mux stream error: %v", err)
_ = frpConn.CloseWithError(0, "")
return
}
go svr.handleConnection(ctx, frpNet.QuicStreamToNetConn(stream, frpConn))
}
}(context.Background(), c)
}
}
func (svr *Service) RegisterControl(ctlConn net.Conn, loginMsg *msg.Login) (err error) {
// If client's RunID is empty, it's a new client, we just create a new controller.
// Otherwise, we check if there is one controller has the same run id. If so, we release previous controller and start new one.