frpc: support multiple confs (#2873)

This commit is contained in:
fatedier 2022-03-28 12:12:35 +08:00 committed by GitHub
parent 305e40fa8a
commit 18a2af4703
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 66 additions and 32 deletions

View File

@ -16,6 +16,9 @@ file:
fmt: fmt:
go fmt ./... go fmt ./...
vet:
go vet ./...
frps: frps:
env CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o bin/frps ./cmd/frps env CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o bin/frps ./cmd/frps
@ -37,7 +40,7 @@ e2e:
e2e-trace: e2e-trace:
DEBUG=true LOG_LEVEL=trace ./hack/run-e2e.sh DEBUG=true LOG_LEVEL=trace ./hack/run-e2e.sh
alltest: gotest e2e alltest: vet gotest e2e
clean: clean:
rm -f ./bin/frpc rm -f ./bin/frpc

View File

@ -19,9 +19,11 @@ import (
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"io" "io"
"math/rand"
"net" "net"
"runtime" "runtime"
"strconv" "strconv"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -36,11 +38,17 @@ import (
"github.com/fatedier/frp/pkg/util/util" "github.com/fatedier/frp/pkg/util/util"
"github.com/fatedier/frp/pkg/util/version" "github.com/fatedier/frp/pkg/util/version"
"github.com/fatedier/frp/pkg/util/xlog" "github.com/fatedier/frp/pkg/util/xlog"
"github.com/fatedier/golib/crypto"
libdial "github.com/fatedier/golib/net/dial" libdial "github.com/fatedier/golib/net/dial"
fmux "github.com/hashicorp/yamux" fmux "github.com/hashicorp/yamux"
) )
func init() {
crypto.DefaultSalt = "frp"
rand.Seed(time.Now().UnixNano())
}
// Service is a client service. // Service is a client service.
type Service struct { type Service struct {
// uniq id got from frps, attach it in loginMsg // uniq id got from frps, attach it in loginMsg
@ -98,6 +106,21 @@ func (svr *Service) GetController() *Control {
func (svr *Service) Run() error { func (svr *Service) Run() error {
xl := xlog.FromContextSafe(svr.ctx) xl := xlog.FromContextSafe(svr.ctx)
// set custom DNSServer
if svr.cfg.DNSServer != "" {
dnsAddr := svr.cfg.DNSServer
if !strings.Contains(dnsAddr, ":") {
dnsAddr += ":53"
}
// Change default dns server for frpc
net.DefaultResolver = &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
return net.Dial("udp", dnsAddr)
},
}
}
// login to frps // login to frps
for { for {
conn, session, err := svr.login() conn, session, err := svr.login()

View File

@ -15,18 +15,10 @@
package main package main
import ( import (
"math/rand"
"time"
_ "github.com/fatedier/frp/assets/frpc" _ "github.com/fatedier/frp/assets/frpc"
"github.com/fatedier/frp/cmd/frpc/sub" "github.com/fatedier/frp/cmd/frpc/sub"
"github.com/fatedier/golib/crypto"
) )
func main() { func main() {
crypto.DefaultSalt = "frp"
rand.Seed(time.Now().UnixNano())
sub.Execute() sub.Execute()
} }

View File

@ -15,13 +15,14 @@
package sub package sub
import ( import (
"context"
"fmt" "fmt"
"io/fs"
"net" "net"
"os" "os"
"os/signal" "os/signal"
"path/filepath"
"strconv" "strconv"
"strings" "sync"
"syscall" "syscall"
"time" "time"
@ -41,6 +42,7 @@ const (
var ( var (
cfgFile string cfgFile string
cfgDir string
showVersion bool showVersion bool
serverAddr string serverAddr string
@ -72,15 +74,12 @@ var (
bindPort int bindPort int
tlsEnable bool tlsEnable bool
kcpDoneCh chan struct{}
) )
func init() { func init() {
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "./frpc.ini", "config file of frpc") rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "./frpc.ini", "config file of frpc")
rootCmd.PersistentFlags().StringVarP(&cfgDir, "config_dir", "", "", "config directory, run one frpc service for each file in config directory")
rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc") rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc")
kcpDoneCh = make(chan struct{})
} }
func RegisterCommonFlags(cmd *cobra.Command) { func RegisterCommonFlags(cmd *cobra.Command) {
@ -104,6 +103,31 @@ var rootCmd = &cobra.Command{
return nil return nil
} }
// If cfgDir is not empty, run multiple frpc service for each config file in cfgDir.
// Note that it's only designed for testing. It's not guaranteed to be stable.
if cfgDir != "" {
var wg sync.WaitGroup
filepath.WalkDir(cfgDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return nil
}
if d.IsDir() {
return nil
}
wg.Add(1)
go func() {
defer wg.Done()
err := runClient(path)
if err != nil {
fmt.Printf("frpc service error for config file [%s]\n", path)
}
}()
return nil
})
wg.Wait()
return nil
}
// Do not show command usage here. // Do not show command usage here.
err := runClient(cfgFile) err := runClient(cfgFile)
if err != nil { if err != nil {
@ -120,12 +144,12 @@ func Execute() {
} }
} }
func handleSignal(svr *client.Service) { func handleSignal(svr *client.Service, doneCh chan struct{}) {
ch := make(chan os.Signal) ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
<-ch <-ch
svr.GracefulClose(500 * time.Millisecond) svr.GracefulClose(500 * time.Millisecond)
close(kcpDoneCh) close(doneCh)
} }
func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) { func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) {
@ -182,18 +206,9 @@ func startService(
log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel, log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel,
cfg.LogMaxDays, cfg.DisableLogColor) cfg.LogMaxDays, cfg.DisableLogColor)
if cfg.DNSServer != "" { if cfgFile != "" {
s := cfg.DNSServer log.Trace("start frpc service for config file [%s]", cfgFile)
if !strings.Contains(s, ":") { defer log.Trace("frpc service for config file [%s] stopped", cfgFile)
s += ":53"
}
// Change default dns server for frpc
net.DefaultResolver = &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
return net.Dial("udp", s)
},
}
} }
svr, errRet := client.NewService(cfg, pxyCfgs, visitorCfgs, cfgFile) svr, errRet := client.NewService(cfg, pxyCfgs, visitorCfgs, cfgFile)
if errRet != nil { if errRet != nil {
@ -201,9 +216,10 @@ func startService(
return return
} }
kcpDoneCh := make(chan struct{})
// Capture the exit signal if we use kcp. // Capture the exit signal if we use kcp.
if cfg.Protocol == "kcp" { if cfg.Protocol == "kcp" {
go handleSignal(svr) go handleSignal(svr, kcpDoneCh)
} }
err = svr.Run() err = svr.Run()

View File

@ -150,7 +150,7 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
type = tcp type = tcp
local_port = {{ .%s }} local_port = {{ .%s }}
remote_port = 0 remote_port = 0
`, framework.TCPEchoServerPort, remotePort) `, framework.TCPEchoServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf}) f.RunProcesses([]string{serverConf}, []string{clientConf})