Merge pull request #2906 from fatedier/dev

bump version
This commit is contained in:
fatedier 2022-04-22 11:32:27 +08:00 committed by GitHub
commit eb1e19a821
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 95 additions and 50 deletions

View File

@ -1,7 +1,7 @@
builds: builds:
- skip: true - skip: true
checksum: checksum:
name_template: '{{ .ProjectName }}_{{ .Version }}_sha256_checksums.txt' name_template: '{{ .ProjectName }}_sha256_checksums.txt'
algorithm: sha256 algorithm: sha256
extra_files: extra_files:
- glob: ./release/packages/* - glob: ./release/packages/*

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

@ -1,8 +1,7 @@
### New ### New
* Support go http pprof. * Added new parameter `config_dir` in frpc to run multiple client instances in one process.
### Improve ### Fix
* Change underlying TCP connection keepalive interval to 2 hours. * Equal sign in environment variables causes parsing error.
* Create new connection to server for `sudp` visitor when needed, to avoid frequent reconnections.

View File

@ -366,7 +366,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
// Listen for clientConn's address and wait for visitor connection // Listen for clientConn's address and wait for visitor connection
lConn, err := net.ListenUDP("udp", laddr) lConn, err := net.ListenUDP("udp", laddr)
if err != nil { if err != nil {
xl.Error("listen on visitorConn's local adress error: %v", err) xl.Error("listen on visitorConn's local address error: %v", err)
return return
} }
defer lConn.Close() defer lConn.Close()

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()
@ -333,8 +356,15 @@ func (svr *Service) ReloadConf(pxyCfgs map[string]config.ProxyConf, visitorCfgs
svr.visitorCfgs = visitorCfgs svr.visitorCfgs = visitorCfgs
svr.cfgMu.Unlock() svr.cfgMu.Unlock()
svr.ctlMu.RLock()
ctl := svr.ctl
svr.ctlMu.RUnlock()
if ctl != nil {
return svr.ctl.ReloadConf(pxyCfgs, visitorCfgs) return svr.ctl.ReloadConf(pxyCfgs, visitorCfgs)
} }
return nil
}
func (svr *Service) Close() { func (svr *Service) Close() {
svr.GracefulClose(time.Duration(0)) svr.GracefulClose(time.Duration(0))
@ -342,8 +372,12 @@ func (svr *Service) Close() {
func (svr *Service) GracefulClose(d time.Duration) { func (svr *Service) GracefulClose(d time.Duration) {
atomic.StoreUint32(&svr.exit, 1) atomic.StoreUint32(&svr.exit, 1)
svr.ctlMu.RLock()
if svr.ctl != nil { if svr.ctl != nil {
svr.ctl.GracefulClose(d) svr.ctl.GracefulClose(d)
} }
svr.ctlMu.RUnlock()
svr.cancel() svr.cancel()
} }

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,32 @@ 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)
time.Sleep(time.Millisecond)
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 +145,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 +207,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 +217,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

@ -105,7 +105,7 @@ tls_enable = true
# specify a dns server, so frpc will use this instead of default one # specify a dns server, so frpc will use this instead of default one
# dns_server = 8.8.8.8 # dns_server = 8.8.8.8
# proxy names you want to start seperated by ',' # proxy names you want to start separated by ','
# default is empty, means all proxies # default is empty, means all proxies
# start = ssh,dns # start = ssh,dns

2
go.mod
View File

@ -16,7 +16,7 @@ require (
github.com/leodido/go-urn v1.2.1 // indirect github.com/leodido/go-urn v1.2.1 // indirect
github.com/onsi/ginkgo v1.16.4 github.com/onsi/ginkgo v1.16.4
github.com/onsi/gomega v1.13.0 github.com/onsi/gomega v1.13.0
github.com/pires/go-proxyproto v0.5.0 github.com/pires/go-proxyproto v0.6.2
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_golang v1.11.0
github.com/rodaine/table v1.0.1 github.com/rodaine/table v1.0.1

4
go.sum
View File

@ -300,8 +300,8 @@ github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je4
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pires/go-proxyproto v0.5.0 h1:A4Jv4ZCaV3AFJeGh5mGwkz4iuWUYMlQ7IoO/GTuSuLo= github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
github.com/pires/go-proxyproto v0.5.0/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=

View File

@ -133,7 +133,7 @@ type ClientCommonConf struct {
// It only works when "tls_enable" is valid and tls configuration of server // It only works when "tls_enable" is valid and tls configuration of server
// has been specified. // has been specified.
TLSTrustedCaFile string `ini:"tls_trusted_ca_file" json:"tls_trusted_ca_file"` TLSTrustedCaFile string `ini:"tls_trusted_ca_file" json:"tls_trusted_ca_file"`
// TLSServerName specifices the custom server name of tls certificate. By // TLSServerName specifies the custom server name of tls certificate. By
// default, server name if same to ServerAddr. // default, server name if same to ServerAddr.
TLSServerName string `ini:"tls_server_name" json:"tls_server_name"` TLSServerName string `ini:"tls_server_name" json:"tls_server_name"`
// By default, frpc will connect frps with first custom byte if tls is enabled. // By default, frpc will connect frps with first custom byte if tls is enabled.

View File

@ -29,11 +29,11 @@ func init() {
glbEnvs = make(map[string]string) glbEnvs = make(map[string]string)
envs := os.Environ() envs := os.Environ()
for _, env := range envs { for _, env := range envs {
kv := strings.Split(env, "=") pair := strings.SplitN(env, "=", 2)
if len(kv) != 2 { if len(pair) != 2 {
continue continue
} }
glbEnvs[kv[0]] = kv[1] glbEnvs[pair[0]] = pair[1]
} }
} }

View File

@ -19,7 +19,7 @@ import (
"strings" "strings"
) )
var version string = "0.41.0" var version string = "0.42.0"
func Full() string { func Full() string {
return version return version

View File

@ -89,7 +89,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
BufferPool: newWrapPool(), BufferPool: newWrapPool(),
ErrorLog: log.New(newWrapLogger(), "", 0), ErrorLog: log.New(newWrapLogger(), "", 0),
ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) { ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) {
frpLog.Warn("do http proxy request error: %v", err) frpLog.Warn("do http proxy request [host: %s] error: %v", req.Host, err)
rw.WriteHeader(http.StatusNotFound) rw.WriteHeader(http.StatusNotFound)
rw.Write(getNotFoundPageContent()) rw.Write(getNotFoundPageContent())
}, },

View File

@ -258,7 +258,7 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) {
case workConn, ok = <-ctl.workConnCh: case workConn, ok = <-ctl.workConnCh:
if !ok { if !ok {
err = frpErr.ErrCtlClosed err = frpErr.ErrCtlClosed
xl.Warn("no work connections avaiable, %v", err) xl.Warn("no work connections available, %v", err)
return return
} }

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})