mirror of
https://github.com/fatedier/frp.git
synced 2024-11-24 02:59:19 +08:00
lint by golangci-lint (#3080)
This commit is contained in:
parent
f4e4fbea62
commit
9d077b02cf
@ -2,14 +2,16 @@ version: 2
|
||||
jobs:
|
||||
go-version-latest:
|
||||
docker:
|
||||
- image: cimg/go:1.18-node
|
||||
- image: cimg/go:1.19-node
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
- run: make
|
||||
- run: make alltest
|
||||
go-version-last:
|
||||
docker:
|
||||
- image: cimg/go:1.17-node
|
||||
- image: cimg/go:1.18-node
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
- run: make
|
||||
|
41
.github/workflows/golangci-lint.yml
vendored
Normal file
41
.github/workflows/golangci-lint.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
name: golangci-lint
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
pull_request:
|
||||
permissions:
|
||||
contents: read
|
||||
# Optional: allow read access to pull request. Use with `only-new-issues` option.
|
||||
pull-requests: read
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
- uses: actions/checkout@v3
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
|
||||
version: v1.49.0
|
||||
|
||||
# Optional: golangci-lint command line arguments.
|
||||
# args: --issues-exit-code=0
|
||||
|
||||
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
||||
# only-new-issues: true
|
||||
|
||||
# Optional: if set to true then the all caching functionality will be complete disabled,
|
||||
# takes precedence over all other caching options.
|
||||
# skip-cache: true
|
||||
|
||||
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
|
||||
# skip-pkg-cache: true
|
||||
|
||||
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
|
||||
# skip-build-cache: true
|
2
.github/workflows/goreleaser.yml
vendored
2
.github/workflows/goreleaser.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.18
|
||||
go-version: 1.19
|
||||
|
||||
- run: |
|
||||
# https://github.com/actions/setup-go/issues/107
|
||||
|
141
.golangci.yml
Normal file
141
.golangci.yml
Normal file
@ -0,0 +1,141 @@
|
||||
service:
|
||||
# When updating this, also update the version stored in docker/build-tools/Dockerfile in the istio/tools repo.
|
||||
golangci-lint-version: 1.49.x # use the fixed version to not introduce new linters unexpectedly
|
||||
|
||||
run:
|
||||
concurrency: 4
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
deadline: 20m
|
||||
build-tags:
|
||||
- integ
|
||||
- integfuzz
|
||||
# which dirs to skip: they won't be analyzed;
|
||||
# can use regexp here: generated.*, regexp is applied on full path;
|
||||
# default value is empty list, but next dirs are always skipped independently
|
||||
# from this option's value:
|
||||
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
|
||||
skip-dirs:
|
||||
- genfiles$
|
||||
- vendor$
|
||||
- bin$
|
||||
|
||||
# which files to skip: they will be analyzed, but issues from them
|
||||
# won't be reported. Default value is empty list, but there is
|
||||
# no need to include all autogenerated files, we confidently recognize
|
||||
# autogenerated files. If it's not please let us know.
|
||||
skip-files:
|
||||
- ".*\\.pb\\.go"
|
||||
- ".*\\.gen\\.go"
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- unused
|
||||
- errcheck
|
||||
- exportloopref
|
||||
- gocritic
|
||||
- gofumpt
|
||||
- goimports
|
||||
- revive
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- lll
|
||||
- misspell
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- gci
|
||||
- bodyclose
|
||||
- gosec
|
||||
- asciicheck
|
||||
- prealloc
|
||||
- predeclared
|
||||
- makezero
|
||||
fast: false
|
||||
|
||||
linters-settings:
|
||||
errcheck:
|
||||
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-type-assertions: false
|
||||
|
||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-blank: false
|
||||
govet:
|
||||
# report about shadowed variables
|
||||
check-shadowing: false
|
||||
maligned:
|
||||
# print struct with more effective memory layout or not, false by default
|
||||
suggest-new: true
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
locale: US
|
||||
ignore-words:
|
||||
- cancelled
|
||||
- marshalled
|
||||
lll:
|
||||
# max line length, lines longer will be reported. Default is 120.
|
||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
||||
line-length: 160
|
||||
# tab width in spaces. Default to 1.
|
||||
tab-width: 1
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- exitAfterDefer
|
||||
unused:
|
||||
check-exported: false
|
||||
unparam:
|
||||
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
|
||||
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- default
|
||||
- prefix(github.com/fatedier/frp/)
|
||||
gosec:
|
||||
severity: "low"
|
||||
confidence: "low"
|
||||
excludes:
|
||||
- G102
|
||||
- G112
|
||||
- G306
|
||||
- G401
|
||||
- G402
|
||||
- G404
|
||||
- G501
|
||||
|
||||
issues:
|
||||
# List of regexps of issue texts to exclude, empty list by default.
|
||||
# But independently from this option we use default exclude patterns,
|
||||
# it can be disabled by `exclude-use-default: false`. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`
|
||||
# exclude:
|
||||
# - composite literal uses unkeyed fields
|
||||
|
||||
exclude-rules:
|
||||
# Exclude some linters from running on test files.
|
||||
- path: _test\.go$|^tests/|^samples/
|
||||
linters:
|
||||
- errcheck
|
||||
- maligned
|
||||
|
||||
# Independently from option `exclude` we use default exclude patterns,
|
||||
# it can be disabled by this option. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`.
|
||||
# Default value for this option is true.
|
||||
exclude-use-default: true
|
||||
|
||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||
max-per-linter: 0
|
||||
|
||||
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||
max-same-issues: 0
|
@ -20,10 +20,10 @@ import (
|
||||
"net/http/pprof"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/fatedier/frp/assets"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -77,6 +77,8 @@ func (svr *Service) RunAdminServer(address string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
go server.Serve(ln)
|
||||
go func() {
|
||||
_ = server.Serve(ln)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("api response [/api/reload], code [%d]", res.Code)
|
||||
w.WriteHeader(res.Code)
|
||||
if len(res.Msg) > 0 {
|
||||
w.Write([]byte(res.Msg))
|
||||
_, _ = w.Write([]byte(res.Msg))
|
||||
}
|
||||
}()
|
||||
|
||||
@ -68,7 +68,6 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
log.Info("success reload conf")
|
||||
return
|
||||
}
|
||||
|
||||
type StatusResp struct {
|
||||
@ -173,7 +172,7 @@ func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request) {
|
||||
defer func() {
|
||||
log.Info("Http response [/api/status]")
|
||||
buf, _ = json.Marshal(&res)
|
||||
w.Write(buf)
|
||||
_, _ = w.Write(buf)
|
||||
}()
|
||||
|
||||
ps := svr.ctl.pm.GetAllProxyStatus()
|
||||
@ -202,7 +201,6 @@ func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request) {
|
||||
sort.Sort(ByProxyStatusResp(res.STCP))
|
||||
sort.Sort(ByProxyStatusResp(res.XTCP))
|
||||
sort.Sort(ByProxyStatusResp(res.SUDP))
|
||||
return
|
||||
}
|
||||
|
||||
// GET api/config
|
||||
@ -214,7 +212,7 @@ func (svr *Service) apiGetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("Http get response [/api/config], code [%d]", res.Code)
|
||||
w.WriteHeader(res.Code)
|
||||
if len(res.Msg) > 0 {
|
||||
w.Write([]byte(res.Msg))
|
||||
_, _ = w.Write([]byte(res.Msg))
|
||||
}
|
||||
}()
|
||||
|
||||
@ -254,7 +252,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("Http put response [/api/config], code [%d]", res.Code)
|
||||
w.WriteHeader(res.Code)
|
||||
if len(res.Msg) > 0 {
|
||||
w.Write([]byte(res.Msg))
|
||||
_, _ = w.Write([]byte(res.Msg))
|
||||
}
|
||||
}()
|
||||
|
||||
@ -315,7 +313,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
content = strings.Join(newRows, "\n")
|
||||
|
||||
err = os.WriteFile(svr.cfgFile, []byte(content), 0644)
|
||||
err = os.WriteFile(svr.cfgFile, []byte(content), 0o644)
|
||||
if err != nil {
|
||||
res.Code = 500
|
||||
res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err)
|
||||
|
@ -21,9 +21,13 @@ import (
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/control/shutdown"
|
||||
"github.com/fatedier/golib/crypto"
|
||||
libdial "github.com/fatedier/golib/net/dial"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
|
||||
"github.com/fatedier/frp/client/proxy"
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
@ -31,11 +35,6 @@ import (
|
||||
"github.com/fatedier/frp/pkg/transport"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/control/shutdown"
|
||||
"github.com/fatedier/golib/crypto"
|
||||
libdial "github.com/fatedier/golib/net/dial"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
)
|
||||
|
||||
type Control struct {
|
||||
@ -79,8 +78,6 @@ type Control struct {
|
||||
// The UDP port that the server is listening on
|
||||
serverUDPPort int
|
||||
|
||||
mu sync.RWMutex
|
||||
|
||||
xl *xlog.Logger
|
||||
|
||||
// service context
|
||||
@ -95,8 +92,8 @@ func NewControl(ctx context.Context, runID string, conn net.Conn, session *fmux.
|
||||
pxyCfgs map[string]config.ProxyConf,
|
||||
visitorCfgs map[string]config.VisitorConf,
|
||||
serverUDPPort int,
|
||||
authSetter auth.Setter) *Control {
|
||||
|
||||
authSetter auth.Setter,
|
||||
) *Control {
|
||||
// new xlog instance
|
||||
ctl := &Control{
|
||||
runID: runID,
|
||||
@ -131,7 +128,6 @@ func (ctl *Control) Run() {
|
||||
|
||||
// start all visitors
|
||||
go ctl.vm.Run()
|
||||
return
|
||||
}
|
||||
|
||||
func (ctl *Control) HandleReqWorkConn(inMsg *msg.ReqWorkConn) {
|
||||
@ -400,24 +396,21 @@ func (ctl *Control) worker() {
|
||||
go ctl.reader()
|
||||
go ctl.writer()
|
||||
|
||||
select {
|
||||
case <-ctl.closedCh:
|
||||
// close related channels and wait until other goroutines done
|
||||
close(ctl.readCh)
|
||||
ctl.readerShutdown.WaitDone()
|
||||
ctl.msgHandlerShutdown.WaitDone()
|
||||
<-ctl.closedCh
|
||||
// close related channels and wait until other goroutines done
|
||||
close(ctl.readCh)
|
||||
ctl.readerShutdown.WaitDone()
|
||||
ctl.msgHandlerShutdown.WaitDone()
|
||||
|
||||
close(ctl.sendCh)
|
||||
ctl.writerShutdown.WaitDone()
|
||||
close(ctl.sendCh)
|
||||
ctl.writerShutdown.WaitDone()
|
||||
|
||||
ctl.pm.Close()
|
||||
ctl.vm.Close()
|
||||
ctl.pm.Close()
|
||||
ctl.vm.Close()
|
||||
|
||||
close(ctl.closedDoneCh)
|
||||
if ctl.session != nil {
|
||||
ctl.session.Close()
|
||||
}
|
||||
return
|
||||
close(ctl.closedDoneCh)
|
||||
if ctl.session != nil {
|
||||
ctl.session.Close()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,7 @@ import (
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrPayloadType = errors.New("error payload type")
|
||||
)
|
||||
var ErrPayloadType = errors.New("error payload type")
|
||||
|
||||
type Handler func(payload interface{}) error
|
||||
|
||||
|
@ -26,9 +26,7 @@ import (
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrHealthCheckType = errors.New("error health check type")
|
||||
)
|
||||
var ErrHealthCheckType = errors.New("error health check type")
|
||||
|
||||
type Monitor struct {
|
||||
checkType string
|
||||
@ -54,8 +52,8 @@ type Monitor struct {
|
||||
func NewMonitor(ctx context.Context, checkType string,
|
||||
intervalS int, timeoutS int, maxFailedTimes int,
|
||||
addr string, url string,
|
||||
statusNormalFn func(), statusFailedFn func()) *Monitor {
|
||||
|
||||
statusNormalFn func(), statusFailedFn func(),
|
||||
) *Monitor {
|
||||
if intervalS <= 0 {
|
||||
intervalS = 10
|
||||
}
|
||||
@ -152,7 +150,7 @@ func (monitor *Monitor) doTCPCheck(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (monitor *Monitor) doHTTPCheck(ctx context.Context) error {
|
||||
req, err := http.NewRequest("GET", monitor.url, nil)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", monitor.url, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -161,7 +159,7 @@ func (monitor *Monitor) doHTTPCheck(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
_, _ = io.Copy(io.Discard, resp.Body)
|
||||
|
||||
if resp.StatusCode/100 != 2 {
|
||||
return fmt.Errorf("do http health check, StatusCode is [%d] not 2xx", resp.StatusCode)
|
||||
|
@ -24,14 +24,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
plugin "github.com/fatedier/frp/pkg/plugin/client"
|
||||
"github.com/fatedier/frp/pkg/proto/udp"
|
||||
"github.com/fatedier/frp/pkg/util/limit"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
libdial "github.com/fatedier/golib/net/dial"
|
||||
@ -39,6 +31,14 @@ import (
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
pp "github.com/pires/go-proxyproto"
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
plugin "github.com/fatedier/frp/pkg/plugin/client"
|
||||
"github.com/fatedier/frp/pkg/proto/udp"
|
||||
"github.com/fatedier/frp/pkg/util/limit"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
)
|
||||
|
||||
// Proxy defines how to handle work connections for different proxy type.
|
||||
@ -322,7 +322,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
|
||||
// Wait for client address at most 5 seconds.
|
||||
var natHoleRespMsg msg.NatHoleResp
|
||||
clientConn.SetReadDeadline(time.Now().Add(5 * time.Second))
|
||||
_ = clientConn.SetReadDeadline(time.Now().Add(5 * time.Second))
|
||||
|
||||
buf := pool.GetBuf(1024)
|
||||
n, err := clientConn.Read(buf)
|
||||
@ -335,8 +335,8 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
xl.Error("get natHoleRespMsg error: %v", err)
|
||||
return
|
||||
}
|
||||
clientConn.SetReadDeadline(time.Time{})
|
||||
clientConn.Close()
|
||||
_ = clientConn.SetReadDeadline(time.Time{})
|
||||
_ = clientConn.Close()
|
||||
|
||||
if natHoleRespMsg.Error != "" {
|
||||
xl.Error("natHoleRespMsg get error info: %s", natHoleRespMsg.Error)
|
||||
@ -357,10 +357,13 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
xl.Error("get natHoleResp visitor address error: %v", natHoleRespMsg.VisitorAddr)
|
||||
return
|
||||
}
|
||||
pxy.sendDetectMsg(host, int(port), laddr, []byte(natHoleRespMsg.Sid))
|
||||
_ = pxy.sendDetectMsg(host, int(port), laddr, []byte(natHoleRespMsg.Sid))
|
||||
xl.Trace("send all detect msg done")
|
||||
|
||||
msg.WriteMsg(conn, &msg.NatHoleClientDetectOK{})
|
||||
if err := msg.WriteMsg(conn, &msg.NatHoleClientDetectOK{}); err != nil {
|
||||
xl.Error("write message error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Listen for clientConn's address and wait for visitor connection
|
||||
lConn, err := net.ListenUDP("udp", laddr)
|
||||
@ -370,7 +373,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
}
|
||||
defer lConn.Close()
|
||||
|
||||
lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
||||
_ = lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
||||
sidBuf := pool.GetBuf(1024)
|
||||
var uAddr *net.UDPAddr
|
||||
n, uAddr, err = lConn.ReadFromUDP(sidBuf)
|
||||
@ -378,7 +381,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
xl.Warn("get sid from visitor error: %v", err)
|
||||
return
|
||||
}
|
||||
lConn.SetReadDeadline(time.Time{})
|
||||
_ = lConn.SetReadDeadline(time.Time{})
|
||||
if string(sidBuf[:n]) != natHoleRespMsg.Sid {
|
||||
xl.Warn("incorrect sid from visitor")
|
||||
return
|
||||
@ -386,7 +389,10 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
pool.PutBuf(sidBuf)
|
||||
xl.Info("nat hole connection make success, sid [%s]", natHoleRespMsg.Sid)
|
||||
|
||||
lConn.WriteToUDP(sidBuf[:n], uAddr)
|
||||
if _, err := lConn.WriteToUDP(sidBuf[:n], uAddr); err != nil {
|
||||
xl.Error("write uaddr error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
kcpConn, err := frpNet.NewKCPConnFromUDP(lConn, false, uAddr.String())
|
||||
if err != nil {
|
||||
@ -424,12 +430,13 @@ func (pxy *XTCPProxy) sendDetectMsg(addr string, port int, laddr *net.UDPAddr, c
|
||||
return err
|
||||
}
|
||||
|
||||
//uConn := ipv4.NewConn(tConn)
|
||||
//uConn.SetTTL(3)
|
||||
// uConn := ipv4.NewConn(tConn)
|
||||
// uConn.SetTTL(3)
|
||||
|
||||
tConn.Write(content)
|
||||
tConn.Close()
|
||||
return nil
|
||||
if _, err := tConn.Write(content); err != nil {
|
||||
return err
|
||||
}
|
||||
return tConn.Close()
|
||||
}
|
||||
|
||||
// UDP
|
||||
@ -539,7 +546,7 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
}
|
||||
}
|
||||
}
|
||||
heartbeatFn := func(conn net.Conn, sendCh chan msg.Message) {
|
||||
heartbeatFn := func(sendCh chan msg.Message) {
|
||||
var errRet error
|
||||
for {
|
||||
time.Sleep(time.Duration(30) * time.Second)
|
||||
@ -554,7 +561,7 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
|
||||
go workConnSenderFn(pxy.workConn, pxy.sendCh)
|
||||
go workConnReaderFn(pxy.workConn, pxy.readCh)
|
||||
go heartbeatFn(pxy.workConn, pxy.sendCh)
|
||||
go heartbeatFn(pxy.sendCh)
|
||||
udp.Forwarder(pxy.localAddr, pxy.readCh, pxy.sendCh, int(pxy.clientCfg.UDPPacketSize))
|
||||
}
|
||||
|
||||
@ -685,7 +692,7 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
}
|
||||
}
|
||||
|
||||
heartbeatFn := func(conn net.Conn, sendCh chan msg.Message) {
|
||||
heartbeatFn := func(sendCh chan msg.Message) {
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer func() {
|
||||
ticker.Stop()
|
||||
@ -711,14 +718,15 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
|
||||
go workConnSenderFn(workConn, sendCh)
|
||||
go workConnReaderFn(workConn, readCh)
|
||||
go heartbeatFn(workConn, sendCh)
|
||||
go heartbeatFn(sendCh)
|
||||
|
||||
udp.Forwarder(pxy.localAddr, readCh, sendCh, int(pxy.clientCfg.UDPPacketSize))
|
||||
}
|
||||
|
||||
// Common handler for tcp work connections.
|
||||
func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf, proxyPlugin plugin.Plugin,
|
||||
baseInfo *config.BaseProxyConf, limiter *rate.Limiter, workConn net.Conn, encKey []byte, m *msg.StartWorkConn) {
|
||||
baseInfo *config.BaseProxyConf, limiter *rate.Limiter, workConn net.Conn, encKey []byte, m *msg.StartWorkConn,
|
||||
) {
|
||||
xl := xlog.FromContextSafe(ctx)
|
||||
var (
|
||||
remote io.ReadWriteCloser
|
||||
@ -773,7 +781,7 @@ func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
h.WriteTo(buf)
|
||||
_, _ = h.WriteTo(buf)
|
||||
extraInfo = buf.Bytes()
|
||||
}
|
||||
}
|
||||
@ -800,7 +808,11 @@ func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf
|
||||
localConn.RemoteAddr().String(), workConn.LocalAddr().String(), workConn.RemoteAddr().String())
|
||||
|
||||
if len(extraInfo) > 0 {
|
||||
localConn.Write(extraInfo)
|
||||
if _, err := localConn.Write(extraInfo); err != nil {
|
||||
workConn.Close()
|
||||
xl.Error("write extraInfo to local conn error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
frpIo.Join(localConn, remote)
|
||||
|
@ -6,12 +6,12 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
|
||||
"github.com/fatedier/frp/client/event"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
@ -113,10 +113,8 @@ func (pm *Manager) Reload(pxyCfgs map[string]config.ProxyConf) {
|
||||
cfg, ok := pxyCfgs[name]
|
||||
if !ok {
|
||||
del = true
|
||||
} else {
|
||||
if !pxy.Cfg.Compare(cfg) {
|
||||
del = true
|
||||
}
|
||||
} else if !pxy.Cfg.Compare(cfg) {
|
||||
del = true
|
||||
}
|
||||
|
||||
if del {
|
||||
|
@ -8,13 +8,13 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
|
||||
"github.com/fatedier/frp/client/event"
|
||||
"github.com/fatedier/frp/client/health"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -27,9 +27,9 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
statusCheckInterval time.Duration = 3 * time.Second
|
||||
waitResponseTimeout = 20 * time.Second
|
||||
startErrTimeout = 30 * time.Second
|
||||
statusCheckInterval = 3 * time.Second
|
||||
waitResponseTimeout = 20 * time.Second
|
||||
startErrTimeout = 30 * time.Second
|
||||
)
|
||||
|
||||
type WorkingStatus struct {
|
||||
@ -145,7 +145,7 @@ func (pw *Wrapper) Stop() {
|
||||
}
|
||||
|
||||
func (pw *Wrapper) close() {
|
||||
pw.handler(&event.CloseProxyPayload{
|
||||
_ = pw.handler(&event.CloseProxyPayload{
|
||||
CloseProxyMsg: &msg.CloseProxy{
|
||||
ProxyName: pw.Name,
|
||||
},
|
||||
@ -174,7 +174,7 @@ func (pw *Wrapper) checkWorker() {
|
||||
var newProxyMsg msg.NewProxy
|
||||
pw.Cfg.MarshalToMsg(&newProxyMsg)
|
||||
pw.lastSendStartMsg = now
|
||||
pw.handler(&event.StartProxyPayload{
|
||||
_ = pw.handler(&event.StartProxyPayload{
|
||||
NewProxyMsg: &newProxyMsg,
|
||||
})
|
||||
}
|
||||
@ -201,7 +201,7 @@ func (pw *Wrapper) checkWorker() {
|
||||
func (pw *Wrapper) statusNormalCallback() {
|
||||
xl := pw.xl
|
||||
atomic.StoreUint32(&pw.health, 0)
|
||||
errors.PanicToError(func() {
|
||||
_ = errors.PanicToError(func() {
|
||||
select {
|
||||
case pw.healthNotifyCh <- struct{}{}:
|
||||
default:
|
||||
@ -213,7 +213,7 @@ func (pw *Wrapper) statusNormalCallback() {
|
||||
func (pw *Wrapper) statusFailedCallback() {
|
||||
xl := pw.xl
|
||||
atomic.StoreUint32(&pw.health, 1)
|
||||
errors.PanicToError(func() {
|
||||
_ = errors.PanicToError(func() {
|
||||
select {
|
||||
case pw.healthNotifyCh <- struct{}{}:
|
||||
default:
|
||||
|
@ -28,6 +28,10 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/crypto"
|
||||
libdial "github.com/fatedier/golib/net/dial"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
|
||||
"github.com/fatedier/frp/assets"
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
@ -38,10 +42,6 @@ import (
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
"github.com/fatedier/frp/pkg/util/version"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
"github.com/fatedier/golib/crypto"
|
||||
libdial "github.com/fatedier/golib/net/dial"
|
||||
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -81,8 +81,12 @@ type Service struct {
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func NewService(cfg config.ClientCommonConf, pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf, cfgFile string) (svr *Service, err error) {
|
||||
|
||||
func NewService(
|
||||
cfg config.ClientCommonConf,
|
||||
pxyCfgs map[string]config.ProxyConf,
|
||||
visitorCfgs map[string]config.VisitorConf,
|
||||
cfgFile string,
|
||||
) (svr *Service, err error) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
svr = &Service{
|
||||
authSetter: auth.NewAuthSetter(cfg.ClientConfig),
|
||||
@ -208,7 +212,7 @@ func (svr *Service) keepControllerWorking() {
|
||||
xl.Warn("reconnect to server error: %v, wait %v for another retry", err, delayTime)
|
||||
util.RandomSleep(delayTime, 0.9, 1.1)
|
||||
|
||||
delayTime = delayTime * 2
|
||||
delayTime *= 2
|
||||
if delayTime > maxDelayTime {
|
||||
delayTime = maxDelayTime
|
||||
}
|
||||
@ -333,11 +337,11 @@ func (svr *Service) login() (conn net.Conn, session *fmux.Session, err error) {
|
||||
}
|
||||
|
||||
var loginRespMsg msg.LoginResp
|
||||
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
_ = conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
if err = msg.ReadMsgInto(conn, &loginRespMsg); err != nil {
|
||||
return
|
||||
}
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
_ = conn.SetReadDeadline(time.Time{})
|
||||
|
||||
if loginRespMsg.Error != "" {
|
||||
err = fmt.Errorf("%s", loginRespMsg.Error)
|
||||
|
@ -24,17 +24,17 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
"github.com/fatedier/golib/pool"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
"github.com/fatedier/frp/pkg/proto/udp"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
"github.com/fatedier/golib/pool"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
)
|
||||
|
||||
// Visitor is used for forward traffics from local port tot remote service.
|
||||
@ -71,9 +71,8 @@ func NewVisitor(ctx context.Context, ctl *Control, cfg config.VisitorConf) (visi
|
||||
}
|
||||
|
||||
type BaseVisitor struct {
|
||||
ctl *Control
|
||||
l net.Listener
|
||||
closed bool
|
||||
ctl *Control
|
||||
l net.Listener
|
||||
|
||||
mu sync.RWMutex
|
||||
ctx context.Context
|
||||
@ -138,13 +137,13 @@ func (sv *STCPVisitor) handleConn(userConn net.Conn) {
|
||||
}
|
||||
|
||||
var newVisitorConnRespMsg msg.NewVisitorConnResp
|
||||
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
_ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
|
||||
if err != nil {
|
||||
xl.Warn("get newVisitorConnRespMsg error: %v", err)
|
||||
return
|
||||
}
|
||||
visitorConn.SetReadDeadline(time.Time{})
|
||||
_ = visitorConn.SetReadDeadline(time.Time{})
|
||||
|
||||
if newVisitorConnRespMsg.Error != "" {
|
||||
xl.Warn("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
|
||||
@ -239,7 +238,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
|
||||
|
||||
// Wait for client address at most 10 seconds.
|
||||
var natHoleRespMsg msg.NatHoleResp
|
||||
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
_ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
buf := pool.GetBuf(1024)
|
||||
n, err := visitorConn.Read(buf)
|
||||
if err != nil {
|
||||
@ -252,7 +251,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
|
||||
xl.Warn("get natHoleRespMsg error: %v", err)
|
||||
return
|
||||
}
|
||||
visitorConn.SetReadDeadline(time.Time{})
|
||||
_ = visitorConn.SetReadDeadline(time.Time{})
|
||||
pool.PutBuf(buf)
|
||||
|
||||
if natHoleRespMsg.Error != "" {
|
||||
@ -279,17 +278,20 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
|
||||
}
|
||||
defer lConn.Close()
|
||||
|
||||
lConn.Write([]byte(natHoleRespMsg.Sid))
|
||||
if _, err := lConn.Write([]byte(natHoleRespMsg.Sid)); err != nil {
|
||||
xl.Error("write sid error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// read ack sid from client
|
||||
sidBuf := pool.GetBuf(1024)
|
||||
lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
||||
_ = lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
||||
n, err = lConn.Read(sidBuf)
|
||||
if err != nil {
|
||||
xl.Warn("get sid from client error: %v", err)
|
||||
return
|
||||
}
|
||||
lConn.SetReadDeadline(time.Time{})
|
||||
_ = lConn.SetReadDeadline(time.Time{})
|
||||
if string(sidBuf[:n]) != natHoleRespMsg.Sid {
|
||||
xl.Warn("incorrect sid from client")
|
||||
return
|
||||
@ -411,7 +413,6 @@ func (sv *SUDPVisitor) dispatcher() {
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
|
||||
@ -437,13 +438,13 @@ func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
|
||||
)
|
||||
|
||||
// frpc will send heartbeat in workConn to frpc visitor for keeping alive
|
||||
conn.SetReadDeadline(time.Now().Add(60 * time.Second))
|
||||
_ = conn.SetReadDeadline(time.Now().Add(60 * time.Second))
|
||||
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
|
||||
xl.Warn("read from workconn for user udp conn error: %v", errRet)
|
||||
return
|
||||
}
|
||||
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
_ = conn.SetReadDeadline(time.Time{})
|
||||
switch m := rawMsg.(type) {
|
||||
case *msg.Ping:
|
||||
xl.Debug("frpc visitor get ping message from frpc")
|
||||
@ -523,12 +524,12 @@ func (sv *SUDPVisitor) getNewVisitorConn() (net.Conn, error) {
|
||||
}
|
||||
|
||||
var newVisitorConnRespMsg msg.NewVisitorConnResp
|
||||
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
_ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("frpc read newVisitorConnRespMsg error: %v", err)
|
||||
}
|
||||
visitorConn.SetReadDeadline(time.Time{})
|
||||
_ = visitorConn.SetReadDeadline(time.Time{})
|
||||
|
||||
if newVisitorConnRespMsg.Error != "" {
|
||||
return nil, fmt.Errorf("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
|
||||
|
@ -65,7 +65,7 @@ func (vm *VisitorManager) Run() {
|
||||
name := cfg.GetBaseInfo().ProxyName
|
||||
if _, exist := vm.visitors[name]; !exist {
|
||||
xl.Info("try to start visitor [%s]", name)
|
||||
vm.startVisitor(cfg)
|
||||
_ = vm.startVisitor(cfg)
|
||||
}
|
||||
}
|
||||
vm.mu.Unlock()
|
||||
@ -99,10 +99,8 @@ func (vm *VisitorManager) Reload(cfgs map[string]config.VisitorConf) {
|
||||
cfg, ok := cfgs[name]
|
||||
if !ok {
|
||||
del = true
|
||||
} else {
|
||||
if !oldCfg.Compare(cfg) {
|
||||
del = true
|
||||
}
|
||||
} else if !oldCfg.Compare(cfg) {
|
||||
del = true
|
||||
}
|
||||
|
||||
if del {
|
||||
@ -123,13 +121,12 @@ func (vm *VisitorManager) Reload(cfgs map[string]config.VisitorConf) {
|
||||
if _, ok := vm.cfgs[name]; !ok {
|
||||
vm.cfgs[name] = cfg
|
||||
addNames = append(addNames, name)
|
||||
vm.startVisitor(cfg)
|
||||
_ = vm.startVisitor(cfg)
|
||||
}
|
||||
}
|
||||
if len(addNames) > 0 {
|
||||
xl.Info("visitor added: %v", addNames)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (vm *VisitorManager) Close() {
|
||||
|
@ -19,10 +19,10 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -22,9 +22,9 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -26,13 +26,13 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/client"
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/pkg/util/version"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -107,7 +107,7 @@ var rootCmd = &cobra.Command{
|
||||
// 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 {
|
||||
_ = filepath.WalkDir(cfgDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@ -183,7 +183,7 @@ func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) {
|
||||
|
||||
cfg.Complete()
|
||||
if err = cfg.Validate(); err != nil {
|
||||
err = fmt.Errorf("Parse config error: %v", err)
|
||||
err = fmt.Errorf("parse config error: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
@ -203,7 +203,6 @@ func startService(
|
||||
visitorCfgs map[string]config.VisitorConf,
|
||||
cfgFile string,
|
||||
) (err error) {
|
||||
|
||||
log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel,
|
||||
cfg.LogMaxDays, cfg.DisableLogColor)
|
||||
|
||||
|
@ -23,11 +23,11 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fatedier/frp/client"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
|
||||
"github.com/rodaine/table"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/client"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -18,10 +18,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -18,10 +18,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -18,10 +18,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -18,9 +18,9 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -18,10 +18,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -18,14 +18,14 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
"github.com/fatedier/frp/pkg/util/version"
|
||||
"github.com/fatedier/frp/server"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -50,16 +50,13 @@ var (
|
||||
dashboardUser string
|
||||
dashboardPwd string
|
||||
enablePrometheus bool
|
||||
assetsDir string
|
||||
logFile string
|
||||
logLevel string
|
||||
logMaxDays int64
|
||||
disableLogColor bool
|
||||
token string
|
||||
subDomainHost string
|
||||
tcpMux bool
|
||||
allowPorts string
|
||||
maxPoolCount int64
|
||||
maxPortsPerClient int64
|
||||
tlsOnly bool
|
||||
dashboardTLSMode bool
|
||||
@ -151,7 +148,7 @@ func parseServerCommonCfg(fileType int, source []byte) (cfg config.ServerCommonC
|
||||
cfg.Complete()
|
||||
err = cfg.Validate()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Parse config error: %v", err)
|
||||
err = fmt.Errorf("parse config error: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
@ -189,7 +186,7 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) {
|
||||
// e.g. 1000-2000,2001,2002,3000-4000
|
||||
ports, errRet := util.ParseRangeNumbers(allowPorts)
|
||||
if errRet != nil {
|
||||
err = fmt.Errorf("Parse conf error: allow_ports: %v", errRet)
|
||||
err = fmt.Errorf("parse conf error: allow_ports: %v", errRet)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,9 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM golang:1.18 AS building
|
||||
FROM golang:1.19 AS building
|
||||
|
||||
COPY . /building
|
||||
WORKDIR /building
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM golang:1.18 AS building
|
||||
FROM golang:1.19 AS building
|
||||
|
||||
COPY . /building
|
||||
WORKDIR /building
|
||||
|
43
go.mod
43
go.mod
@ -1,6 +1,6 @@
|
||||
module github.com/fatedier/frp
|
||||
|
||||
go 1.16
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||
@ -13,21 +13,54 @@ require (
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/onsi/ginkgo v1.16.4
|
||||
github.com/onsi/gomega v1.13.0
|
||||
github.com/pires/go-proxyproto v0.6.2
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/rodaine/table v1.0.1
|
||||
github.com/spf13/cobra v1.1.3
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||
gopkg.in/ini.v1 v1.62.0
|
||||
gopkg.in/square/go-jose.v2 v2.4.1 // indirect
|
||||
k8s.io/apimachinery v0.21.2
|
||||
k8s.io/client-go v0.21.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.6 // indirect
|
||||
github.com/klauspost/reedsolomon v1.9.15 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.26.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
|
||||
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
google.golang.org/appengine v1.6.5 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.4.1 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
)
|
||||
|
2
go.sum
2
go.sum
@ -55,7 +55,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@ -383,7 +382,6 @@ github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVc
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
|
||||
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
|
@ -5,7 +5,7 @@ ROOT=$(unset CDPATH && cd $(dirname "${BASH_SOURCE[0]}")/.. && pwd)
|
||||
which ginkgo &> /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ginkgo not found, try to install..."
|
||||
go install github.com/onsi/ginkgo/ginkgo@latest
|
||||
go install github.com/onsi/ginkgo/ginkgo@v1.16.5
|
||||
fi
|
||||
|
||||
debug=false
|
||||
|
@ -18,10 +18,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
|
||||
"github.com/coreos/go-oidc"
|
||||
"golang.org/x/oauth2/clientcredentials"
|
||||
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
)
|
||||
|
||||
type OidcClientConfig struct {
|
||||
@ -34,7 +34,7 @@ type OidcClientConfig struct {
|
||||
// is "".
|
||||
OidcClientSecret string `ini:"oidc_client_secret" json:"oidc_client_secret"`
|
||||
// OidcAudience specifies the audience of the token in OIDC authentication
|
||||
//if AuthenticationMethod == "oidc". By default, this value is "".
|
||||
// if AuthenticationMethod == "oidc". By default, this value is "".
|
||||
OidcAudience string `ini:"oidc_audience" json:"oidc_audience"`
|
||||
// OidcTokenEndpointURL specifies the URL which implements OIDC Token Endpoint.
|
||||
// It will be used to get an OIDC token if AuthenticationMethod == "oidc".
|
||||
|
@ -20,10 +20,10 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// ClientCommonConf contains information for a client service. It is
|
||||
@ -113,7 +113,7 @@ type ClientCommonConf struct {
|
||||
// all supplied proxies are enabled. By default, this value is an empty
|
||||
// set.
|
||||
Start []string `ini:"start" json:"start"`
|
||||
//Start map[string]struct{} `json:"start"`
|
||||
// Start map[string]struct{} `json:"start"`
|
||||
// Protocol specifies the protocol to use when interacting with the server.
|
||||
// Valid values are "tcp", "kcp" and "websocket". By default, this value
|
||||
// is "tcp".
|
||||
@ -214,7 +214,7 @@ func (cfg *ClientCommonConf) Validate() error {
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.TLSEnable == false {
|
||||
if !cfg.TLSEnable {
|
||||
if cfg.TLSCertFile != "" {
|
||||
fmt.Println("WARNING! tls_cert_file is invalid when tls_enable is false")
|
||||
}
|
||||
@ -281,7 +281,6 @@ func LoadAllProxyConfsFromIni(
|
||||
source interface{},
|
||||
start []string,
|
||||
) (map[string]ProxyConf, map[string]VisitorConf, error) {
|
||||
|
||||
f, err := ini.LoadSources(ini.LoadOptions{
|
||||
Insensitive: false,
|
||||
InsensitiveSections: false,
|
||||
@ -366,7 +365,6 @@ func LoadAllProxyConfsFromIni(
|
||||
}
|
||||
|
||||
func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
|
||||
|
||||
// Validation
|
||||
localPortStr := section.Key("local_port").String()
|
||||
remotePortStr := section.Key("remote_port").String()
|
||||
@ -404,8 +402,12 @@ func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
|
||||
}
|
||||
|
||||
copySection(section, tmpsection)
|
||||
tmpsection.NewKey("local_port", fmt.Sprintf("%d", localPorts[i]))
|
||||
tmpsection.NewKey("remote_port", fmt.Sprintf("%d", remotePorts[i]))
|
||||
if _, err := tmpsection.NewKey("local_port", fmt.Sprintf("%d", localPorts[i])); err != nil {
|
||||
return fmt.Errorf("local_port new key in section error: %v", err)
|
||||
}
|
||||
if _, err := tmpsection.NewKey("remote_port", fmt.Sprintf("%d", remotePorts[i])); err != nil {
|
||||
return fmt.Errorf("remote_port new key in section error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -413,6 +415,6 @@ func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
|
||||
|
||||
func copySection(source, target *ini.Section) {
|
||||
for key, value := range source.KeysHash() {
|
||||
target.NewKey(key, value)
|
||||
_, _ = target.NewKey(key, value)
|
||||
}
|
||||
}
|
||||
|
@ -17,18 +17,17 @@ package config
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
testUser = "test"
|
||||
)
|
||||
|
||||
var (
|
||||
testClientBytesWithFull = []byte(`
|
||||
var testClientBytesWithFull = []byte(`
|
||||
# [common] is integral section
|
||||
[common]
|
||||
server_addr = 0.0.0.9
|
||||
@ -237,7 +236,6 @@ var (
|
||||
use_encryption = false
|
||||
use_compression = false
|
||||
`)
|
||||
)
|
||||
|
||||
func Test_LoadClientCommonConf(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
@ -42,7 +42,7 @@ func ParseClientConfig(filePath string) (
|
||||
}
|
||||
cfg.Complete()
|
||||
if err = cfg.Validate(); err != nil {
|
||||
err = fmt.Errorf("Parse config error: %v", err)
|
||||
err = fmt.Errorf("parse config error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -21,10 +21,10 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// Proxy
|
||||
@ -420,10 +420,6 @@ func (cfg *BaseProxyConf) checkForCli() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *BaseProxyConf) checkForSvr(conf ServerCommonConf) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DomainConf
|
||||
func (cfg *DomainConf) check() (err error) {
|
||||
if len(cfg.CustomDomains) == 0 && cfg.SubDomain == "" {
|
||||
|
@ -17,10 +17,10 @@ package config
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -49,7 +49,6 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
source []byte
|
||||
expected ProxyConf
|
||||
}{
|
||||
|
||||
{
|
||||
sname: "ssh",
|
||||
source: []byte(`
|
||||
@ -457,5 +456,4 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) {
|
||||
|
||||
assert.Equal(c.expected, actual)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,12 +18,12 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// ServerCommonConf contains information for a server service. It is
|
||||
@ -236,7 +236,6 @@ func GetDefaultServerConf() ServerCommonConf {
|
||||
}
|
||||
|
||||
func UnmarshalServerConfFromIni(source interface{}) (ServerCommonConf, error) {
|
||||
|
||||
f, err := ini.LoadSources(ini.LoadOptions{
|
||||
Insensitive: false,
|
||||
InsensitiveSections: false,
|
||||
@ -308,7 +307,7 @@ func (cfg *ServerCommonConf) Complete() {
|
||||
}
|
||||
|
||||
func (cfg *ServerCommonConf) Validate() error {
|
||||
if cfg.DashboardTLSMode == false {
|
||||
if !cfg.DashboardTLSMode {
|
||||
if cfg.DashboardTLSCertFile != "" {
|
||||
fmt.Println("WARNING! dashboard_tls_cert_file is invalid when dashboard_tls_mode is false")
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ package config
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_LoadServerCommonConf(t *testing.T) {
|
||||
@ -126,10 +126,10 @@ func Test_LoadServerCommonConf(t *testing.T) {
|
||||
HeartbeatTimeout: 99,
|
||||
UserConnTimeout: 9,
|
||||
AllowPorts: map[int]struct{}{
|
||||
10: struct{}{},
|
||||
11: struct{}{},
|
||||
12: struct{}{},
|
||||
99: struct{}{},
|
||||
10: {},
|
||||
11: {},
|
||||
12: {},
|
||||
99: {},
|
||||
},
|
||||
MaxPoolCount: 59,
|
||||
MaxPortsPerClient: 9,
|
||||
|
@ -75,21 +75,22 @@ func (q *BandwidthQuantity) UnmarshalString(s string) error {
|
||||
f float64
|
||||
err error
|
||||
)
|
||||
if strings.HasSuffix(s, "MB") {
|
||||
switch {
|
||||
case strings.HasSuffix(s, "MB"):
|
||||
base = MB
|
||||
fstr := strings.TrimSuffix(s, "MB")
|
||||
f, err = strconv.ParseFloat(fstr, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if strings.HasSuffix(s, "KB") {
|
||||
case strings.HasSuffix(s, "KB"):
|
||||
base = KB
|
||||
fstr := strings.TrimSuffix(s, "KB")
|
||||
f, err = strconv.ParseFloat(fstr, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
return errors.New("unit not support")
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,7 @@ import (
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
glbEnvs map[string]string
|
||||
)
|
||||
var glbEnvs map[string]string
|
||||
|
||||
func init() {
|
||||
glbEnvs = make(map[string]string)
|
||||
|
@ -18,9 +18,9 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
)
|
||||
|
||||
// Visitor
|
||||
@ -136,6 +136,7 @@ func (cfg *BaseVisitorConf) check() (err error) {
|
||||
}
|
||||
|
||||
func (cfg *BaseVisitorConf) unmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
||||
_ = section
|
||||
|
||||
// Custom decoration after basic unmarshal:
|
||||
// proxy name
|
||||
|
@ -17,10 +17,10 @@ package config
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
)
|
||||
|
||||
const testVisitorPrefix = "test."
|
||||
|
@ -16,26 +16,26 @@ package consts
|
||||
|
||||
var (
|
||||
// proxy status
|
||||
Idle string = "idle"
|
||||
Working string = "working"
|
||||
Closed string = "closed"
|
||||
Online string = "online"
|
||||
Offline string = "offline"
|
||||
Idle = "idle"
|
||||
Working = "working"
|
||||
Closed = "closed"
|
||||
Online = "online"
|
||||
Offline = "offline"
|
||||
|
||||
// proxy type
|
||||
TCPProxy string = "tcp"
|
||||
UDPProxy string = "udp"
|
||||
TCPMuxProxy string = "tcpmux"
|
||||
HTTPProxy string = "http"
|
||||
HTTPSProxy string = "https"
|
||||
STCPProxy string = "stcp"
|
||||
XTCPProxy string = "xtcp"
|
||||
SUDPProxy string = "sudp"
|
||||
TCPProxy = "tcp"
|
||||
UDPProxy = "udp"
|
||||
TCPMuxProxy = "tcpmux"
|
||||
HTTPProxy = "http"
|
||||
HTTPSProxy = "https"
|
||||
STCPProxy = "stcp"
|
||||
XTCPProxy = "xtcp"
|
||||
SUDPProxy = "sudp"
|
||||
|
||||
// authentication method
|
||||
TokenAuthMethod string = "token"
|
||||
OidcAuthMethod string = "oidc"
|
||||
TokenAuthMethod = "token"
|
||||
OidcAuthMethod = "oidc"
|
||||
|
||||
// TCP multiplexer
|
||||
HTTPConnectTCPMultiplexer string = "httpconnect"
|
||||
HTTPConnectTCPMultiplexer = "httpconnect"
|
||||
)
|
||||
|
@ -30,7 +30,7 @@ func EnablePrometheus() {
|
||||
sm.Add(prometheus.ServerMetrics)
|
||||
}
|
||||
|
||||
var sm *serverMetrics = &serverMetrics{}
|
||||
var sm = &serverMetrics{}
|
||||
|
||||
func init() {
|
||||
metrics.Register(sm)
|
||||
|
@ -23,9 +23,12 @@ import (
|
||||
server "github.com/fatedier/frp/server/metrics"
|
||||
)
|
||||
|
||||
var sm *serverMetrics = newServerMetrics()
|
||||
var ServerMetrics server.ServerMetrics
|
||||
var StatsCollector Collector
|
||||
var (
|
||||
sm = newServerMetrics()
|
||||
|
||||
ServerMetrics server.ServerMetrics
|
||||
StatsCollector Collector
|
||||
)
|
||||
|
||||
func init() {
|
||||
ServerMetrics = sm
|
||||
|
@ -4,5 +4,7 @@ import (
|
||||
"github.com/fatedier/frp/pkg/metrics/aggregate"
|
||||
)
|
||||
|
||||
var EnableMem = aggregate.EnableMem
|
||||
var EnablePrometheus = aggregate.EnablePrometheus
|
||||
var (
|
||||
EnableMem = aggregate.EnableMem
|
||||
EnablePrometheus = aggregate.EnablePrometheus
|
||||
)
|
||||
|
@ -1,9 +1,9 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"github.com/fatedier/frp/server/metrics"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"github.com/fatedier/frp/server/metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -22,9 +22,7 @@ import (
|
||||
|
||||
type Message = jsonMsg.Message
|
||||
|
||||
var (
|
||||
msgCtl *jsonMsg.MsgCtl
|
||||
)
|
||||
var msgCtl *jsonMsg.MsgCtl
|
||||
|
||||
func init() {
|
||||
msgCtl = jsonMsg.NewMsgCtl()
|
||||
|
@ -37,28 +37,26 @@ const (
|
||||
TypeNatHoleSid = '5'
|
||||
)
|
||||
|
||||
var (
|
||||
msgTypeMap = map[byte]interface{}{
|
||||
TypeLogin: Login{},
|
||||
TypeLoginResp: LoginResp{},
|
||||
TypeNewProxy: NewProxy{},
|
||||
TypeNewProxyResp: NewProxyResp{},
|
||||
TypeCloseProxy: CloseProxy{},
|
||||
TypeNewWorkConn: NewWorkConn{},
|
||||
TypeReqWorkConn: ReqWorkConn{},
|
||||
TypeStartWorkConn: StartWorkConn{},
|
||||
TypeNewVisitorConn: NewVisitorConn{},
|
||||
TypeNewVisitorConnResp: NewVisitorConnResp{},
|
||||
TypePing: Ping{},
|
||||
TypePong: Pong{},
|
||||
TypeUDPPacket: UDPPacket{},
|
||||
TypeNatHoleVisitor: NatHoleVisitor{},
|
||||
TypeNatHoleClient: NatHoleClient{},
|
||||
TypeNatHoleResp: NatHoleResp{},
|
||||
TypeNatHoleClientDetectOK: NatHoleClientDetectOK{},
|
||||
TypeNatHoleSid: NatHoleSid{},
|
||||
}
|
||||
)
|
||||
var msgTypeMap = map[byte]interface{}{
|
||||
TypeLogin: Login{},
|
||||
TypeLoginResp: LoginResp{},
|
||||
TypeNewProxy: NewProxy{},
|
||||
TypeNewProxyResp: NewProxyResp{},
|
||||
TypeCloseProxy: CloseProxy{},
|
||||
TypeNewWorkConn: NewWorkConn{},
|
||||
TypeReqWorkConn: ReqWorkConn{},
|
||||
TypeStartWorkConn: StartWorkConn{},
|
||||
TypeNewVisitorConn: NewVisitorConn{},
|
||||
TypeNewVisitorConnResp: NewVisitorConnResp{},
|
||||
TypePing: Ping{},
|
||||
TypePong: Pong{},
|
||||
TypeUDPPacket: UDPPacket{},
|
||||
TypeNatHoleVisitor: NatHoleVisitor{},
|
||||
TypeNatHoleClient: NatHoleClient{},
|
||||
TypeNatHoleResp: NatHoleResp{},
|
||||
TypeNatHoleClientDetectOK: NatHoleClientDetectOK{},
|
||||
TypeNatHoleSid: NatHoleSid{},
|
||||
}
|
||||
|
||||
// When frpc start, client send this message to login to server.
|
||||
type Login struct {
|
||||
@ -129,8 +127,7 @@ type NewWorkConn struct {
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
}
|
||||
|
||||
type ReqWorkConn struct {
|
||||
}
|
||||
type ReqWorkConn struct{}
|
||||
|
||||
type StartWorkConn struct {
|
||||
ProxyName string `json:"proxy_name,omitempty"`
|
||||
@ -187,8 +184,7 @@ type NatHoleResp struct {
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type NatHoleClientDetectOK struct {
|
||||
}
|
||||
type NatHoleClientDetectOK struct{}
|
||||
|
||||
type NatHoleSid struct {
|
||||
Sid string `json:"sid,omitempty"`
|
||||
|
@ -7,15 +7,15 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
"github.com/fatedier/golib/pool"
|
||||
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
"github.com/fatedier/golib/pool"
|
||||
)
|
||||
|
||||
// Timeout seconds.
|
||||
// NatHoleTimeout seconds.
|
||||
var NatHoleTimeout int64 = 10
|
||||
|
||||
type SidRequest struct {
|
||||
@ -107,7 +107,7 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
|
||||
session := &Session{
|
||||
Sid: sid,
|
||||
VisitorAddr: raddr,
|
||||
NotifyCh: make(chan struct{}, 0),
|
||||
NotifyCh: make(chan struct{}),
|
||||
}
|
||||
nc.mu.Lock()
|
||||
clientCfg, ok := nc.clientCfgs[m.ProxyName]
|
||||
@ -115,14 +115,14 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
|
||||
nc.mu.Unlock()
|
||||
errInfo := fmt.Sprintf("xtcp server for [%s] doesn't exist", m.ProxyName)
|
||||
log.Debug(errInfo)
|
||||
nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
||||
_, _ = nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
||||
return
|
||||
}
|
||||
if m.SignKey != util.GetAuthKey(clientCfg.Sk, m.Timestamp) {
|
||||
nc.mu.Unlock()
|
||||
errInfo := fmt.Sprintf("xtcp connection of [%s] auth failed", m.ProxyName)
|
||||
log.Debug(errInfo)
|
||||
nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
||||
_, _ = nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
||||
return
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
|
||||
case <-session.NotifyCh:
|
||||
resp := nc.GenNatHoleResponse(session, "")
|
||||
log.Trace("send nat hole response to visitor")
|
||||
nc.listener.WriteToUDP(resp, raddr)
|
||||
_, _ = nc.listener.WriteToUDP(resp, raddr)
|
||||
case <-time.After(time.Duration(NatHoleTimeout) * time.Second):
|
||||
return
|
||||
}
|
||||
@ -169,7 +169,7 @@ func (nc *Controller) HandleClient(m *msg.NatHoleClient, raddr *net.UDPAddr) {
|
||||
|
||||
resp := nc.GenNatHoleResponse(session, "")
|
||||
log.Trace("send nat hole response to client")
|
||||
nc.listener.WriteToUDP(resp, raddr)
|
||||
_, _ = nc.listener.WriteToUDP(resp, raddr)
|
||||
}
|
||||
|
||||
func (nc *Controller) GenNatHoleResponse(session *Session, errInfo string) []byte {
|
||||
|
@ -86,17 +86,20 @@ func NewHTTP2HTTPSPlugin(params map[string]string) (Plugin, error) {
|
||||
}
|
||||
|
||||
p.s = &http.Server{
|
||||
Handler: rp,
|
||||
Handler: rp,
|
||||
ReadHeaderTimeout: 0,
|
||||
}
|
||||
|
||||
go p.s.Serve(listener)
|
||||
go func() {
|
||||
_ = p.s.Serve(listener)
|
||||
}()
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *HTTP2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||
p.l.PutConn(wrapConn)
|
||||
_ = p.l.PutConn(wrapConn)
|
||||
}
|
||||
|
||||
func (p *HTTP2HTTPSPlugin) Name() string {
|
||||
|
@ -22,10 +22,10 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
gnet "github.com/fatedier/golib/net"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
)
|
||||
|
||||
const PluginHTTPProxy = "http_proxy"
|
||||
@ -56,7 +56,9 @@ func NewHTTPProxyPlugin(params map[string]string) (Plugin, error) {
|
||||
Handler: hp,
|
||||
}
|
||||
|
||||
go hp.s.Serve(listener)
|
||||
go func() {
|
||||
_ = hp.s.Serve(listener)
|
||||
}()
|
||||
return hp, nil
|
||||
}
|
||||
|
||||
@ -86,8 +88,7 @@ func (hp *HTTPProxy) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBuf
|
||||
return
|
||||
}
|
||||
|
||||
hp.l.PutConn(sc)
|
||||
return
|
||||
_ = hp.l.PutConn(sc)
|
||||
}
|
||||
|
||||
func (hp *HTTPProxy) Close() error {
|
||||
@ -153,7 +154,7 @@ func (hp *HTTPProxy) ConnectHandler(rw http.ResponseWriter, req *http.Request) {
|
||||
client.Close()
|
||||
return
|
||||
}
|
||||
client.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||
_, _ = client.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||
|
||||
go frpIo.Join(remote, client)
|
||||
}
|
||||
@ -188,7 +189,10 @@ func (hp *HTTPProxy) handleConnectReq(req *http.Request, rwc io.ReadWriteCloser)
|
||||
defer rwc.Close()
|
||||
if ok := hp.Auth(req); !ok {
|
||||
res := getBadResponse()
|
||||
res.Write(rwc)
|
||||
_ = res.Write(rwc)
|
||||
if res.Body != nil {
|
||||
res.Body.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -200,10 +204,10 @@ func (hp *HTTPProxy) handleConnectReq(req *http.Request, rwc io.ReadWriteCloser)
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
}
|
||||
res.Write(rwc)
|
||||
_ = res.Write(rwc)
|
||||
return
|
||||
}
|
||||
rwc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||
_, _ = rwc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||
|
||||
frpIo.Join(remote, rwc)
|
||||
}
|
||||
|
@ -106,7 +106,9 @@ func NewHTTPS2HTTPPlugin(params map[string]string) (Plugin, error) {
|
||||
}
|
||||
ln := tls.NewListener(listener, tlsConfig)
|
||||
|
||||
go p.s.Serve(ln)
|
||||
go func() {
|
||||
_ = p.s.Serve(ln)
|
||||
}()
|
||||
return p, nil
|
||||
}
|
||||
|
||||
@ -122,7 +124,7 @@ func (p *HTTPS2HTTPPlugin) genTLSConfig() (*tls.Config, error) {
|
||||
|
||||
func (p *HTTPS2HTTPPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||
p.l.PutConn(wrapConn)
|
||||
_ = p.l.PutConn(wrapConn)
|
||||
}
|
||||
|
||||
func (p *HTTPS2HTTPPlugin) Name() string {
|
||||
|
@ -111,7 +111,9 @@ func NewHTTPS2HTTPSPlugin(params map[string]string) (Plugin, error) {
|
||||
}
|
||||
ln := tls.NewListener(listener, tlsConfig)
|
||||
|
||||
go p.s.Serve(ln)
|
||||
go func() {
|
||||
_ = p.s.Serve(ln)
|
||||
}()
|
||||
return p, nil
|
||||
}
|
||||
|
||||
@ -127,7 +129,7 @@ func (p *HTTPS2HTTPSPlugin) genTLSConfig() (*tls.Config, error) {
|
||||
|
||||
func (p *HTTPS2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||
p.l.PutConn(wrapConn)
|
||||
_ = p.l.PutConn(wrapConn)
|
||||
}
|
||||
|
||||
func (p *HTTPS2HTTPSPlugin) Name() string {
|
||||
|
@ -19,9 +19,9 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
|
||||
gosocks5 "github.com/armon/go-socks5"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
)
|
||||
|
||||
const PluginSocks5 = "socks5"
|
||||
@ -32,9 +32,6 @@ func init() {
|
||||
|
||||
type Socks5Plugin struct {
|
||||
Server *gosocks5.Server
|
||||
|
||||
user string
|
||||
passwd string
|
||||
}
|
||||
|
||||
func NewSocks5Plugin(params map[string]string) (p Plugin, err error) {
|
||||
@ -56,7 +53,7 @@ func NewSocks5Plugin(params map[string]string) (p Plugin, err error) {
|
||||
func (sp *Socks5Plugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||
defer conn.Close()
|
||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||
sp.Server.ServeConn(wrapConn)
|
||||
_ = sp.Server.ServeConn(wrapConn)
|
||||
}
|
||||
|
||||
func (sp *Socks5Plugin) Name() string {
|
||||
|
@ -19,9 +19,9 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
)
|
||||
|
||||
const PluginStaticFile = "static_file"
|
||||
@ -69,13 +69,15 @@ func NewStaticFilePlugin(params map[string]string) (Plugin, error) {
|
||||
sp.s = &http.Server{
|
||||
Handler: router,
|
||||
}
|
||||
go sp.s.Serve(listener)
|
||||
go func() {
|
||||
_ = sp.s.Serve(listener)
|
||||
}()
|
||||
return sp, nil
|
||||
}
|
||||
|
||||
func (sp *StaticFilePlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||
sp.l.PutConn(wrapConn)
|
||||
_ = sp.l.PutConn(wrapConn)
|
||||
}
|
||||
|
||||
func (sp *StaticFilePlugin) Name() string {
|
||||
|
@ -57,7 +57,9 @@ func (uds *UnixDomainSocketPlugin) Handle(conn io.ReadWriteCloser, realConn net.
|
||||
return
|
||||
}
|
||||
if len(extraBufToLocal) > 0 {
|
||||
localConn.Write(extraBufToLocal)
|
||||
if _, err := localConn.Write(extraBufToLocal); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
frpIo.Join(localConn, conn)
|
||||
|
@ -43,12 +43,12 @@ type httpPlugin struct {
|
||||
}
|
||||
|
||||
func NewHTTPPluginOptions(options HTTPPluginOptions) Plugin {
|
||||
var url = fmt.Sprintf("%s%s", options.Addr, options.Path)
|
||||
url := fmt.Sprintf("%s%s", options.Addr, options.Path)
|
||||
|
||||
var client *http.Client
|
||||
if strings.HasPrefix(url, "https://") {
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: options.TLSVerify == false},
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: !options.TLSVerify},
|
||||
}
|
||||
client = &http.Client{Transport: tr}
|
||||
} else {
|
||||
|
@ -154,9 +154,8 @@ func (m *Manager) CloseProxy(content *CloseProxyContent) error {
|
||||
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf("send CloseProxy request to plugin errors: %s", strings.Join(errs, "; "))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) Ping(content *PingContent) (*PingContent, error) {
|
||||
|
@ -20,10 +20,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
"github.com/fatedier/golib/pool"
|
||||
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
)
|
||||
|
||||
func NewUDPPacket(buf []byte, laddr, raddr *net.UDPAddr) *msg.UDPPacket {
|
||||
@ -47,7 +47,7 @@ func ForwardUserConn(udpConn *net.UDPConn, readCh <-chan *msg.UDPPacket, sendCh
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
udpConn.WriteToUDP(buf, udpMsg.RemoteAddr)
|
||||
_, _ = udpConn.WriteToUDP(buf, udpMsg.RemoteAddr)
|
||||
}
|
||||
}()
|
||||
|
||||
@ -70,9 +70,7 @@ func ForwardUserConn(udpConn *net.UDPConn, readCh <-chan *msg.UDPPacket, sendCh
|
||||
}
|
||||
|
||||
func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UDPPacket, sendCh chan<- msg.Message, bufSize int) {
|
||||
var (
|
||||
mu sync.RWMutex
|
||||
)
|
||||
var mu sync.RWMutex
|
||||
udpConnMap := make(map[string]*net.UDPConn)
|
||||
|
||||
// read from dstAddr and write to sendCh
|
||||
@ -87,7 +85,7 @@ func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UDPPacket, sendCh chan<-
|
||||
|
||||
buf := pool.GetBuf(bufSize)
|
||||
for {
|
||||
udpConn.SetReadDeadline(time.Now().Add(30 * time.Second))
|
||||
_ = udpConn.SetReadDeadline(time.Now().Add(30 * time.Second))
|
||||
n, _, err := udpConn.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -19,7 +19,7 @@ func newCustomTLSKeyPair(certfile, keyfile string) (*tls.Certificate, error) {
|
||||
}
|
||||
|
||||
func newRandomTLSKeyPair() *tls.Certificate {
|
||||
key, err := rsa.GenerateKey(rand.Reader, 1024)
|
||||
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -58,7 +58,7 @@ func newCertPool(caPath string) (*x509.CertPool, error) {
|
||||
}
|
||||
|
||||
func NewServerTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) {
|
||||
var base = &tls.Config{}
|
||||
base := &tls.Config{}
|
||||
|
||||
if certPath == "" || keyPath == "" {
|
||||
// server will generate tls conf by itself
|
||||
@ -87,7 +87,7 @@ func NewServerTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) {
|
||||
}
|
||||
|
||||
func NewClientTLSConfig(certPath, keyPath, caPath, serverName string) (*tls.Config, error) {
|
||||
var base = &tls.Config{}
|
||||
base := &tls.Config{}
|
||||
|
||||
if certPath == "" || keyPath == "" {
|
||||
// client will not generate tls conf by itself
|
||||
|
@ -40,19 +40,19 @@ func SetLogFile(logWay string, logFile string, maxdays int64, disableLogColor bo
|
||||
if logWay == "console" {
|
||||
params := ""
|
||||
if disableLogColor {
|
||||
params = fmt.Sprintf(`{"color": false}`)
|
||||
params = `{"color": false}`
|
||||
}
|
||||
Log.SetLogger("console", params)
|
||||
_ = Log.SetLogger("console", params)
|
||||
} else {
|
||||
params := fmt.Sprintf(`{"filename": "%s", "maxdays": %d}`, logFile, maxdays)
|
||||
Log.SetLogger("file", params)
|
||||
_ = Log.SetLogger("file", params)
|
||||
}
|
||||
}
|
||||
|
||||
// SetLogLevel set log level, default is warning
|
||||
// value: error, warning, info, debug, trace
|
||||
func SetLogLevel(logLevel string) {
|
||||
level := 4 // warning
|
||||
var level int
|
||||
switch logLevel {
|
||||
case "error":
|
||||
level = 3
|
||||
@ -65,7 +65,7 @@ func SetLogLevel(logLevel string) {
|
||||
case "trace":
|
||||
level = 8
|
||||
default:
|
||||
level = 4
|
||||
level = 4 // warning
|
||||
}
|
||||
Log.SetLevel(level)
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ func ListenKcp(address string) (l *KCPListener, err error) {
|
||||
if err != nil {
|
||||
return l, err
|
||||
}
|
||||
listener.SetReadBuffer(4194304)
|
||||
listener.SetWriteBuffer(4194304)
|
||||
_ = listener.SetReadBuffer(4194304)
|
||||
_ = listener.SetWriteBuffer(4194304)
|
||||
|
||||
l = &KCPListener{
|
||||
listener: listener,
|
||||
|
@ -23,32 +23,30 @@ import (
|
||||
gnet "github.com/fatedier/golib/net"
|
||||
)
|
||||
|
||||
var (
|
||||
FRPTLSHeadByte = 0x17
|
||||
)
|
||||
var FRPTLSHeadByte = 0x17
|
||||
|
||||
func CheckAndEnableTLSServerConnWithTimeout(
|
||||
c net.Conn, tlsConfig *tls.Config, tlsOnly bool, timeout time.Duration,
|
||||
) (out net.Conn, isTLS bool, custom bool, err error) {
|
||||
|
||||
sc, r := gnet.NewSharedConnSize(c, 2)
|
||||
buf := make([]byte, 1)
|
||||
var n int
|
||||
c.SetReadDeadline(time.Now().Add(timeout))
|
||||
_ = c.SetReadDeadline(time.Now().Add(timeout))
|
||||
n, err = r.Read(buf)
|
||||
c.SetReadDeadline(time.Time{})
|
||||
_ = c.SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if n == 1 && int(buf[0]) == FRPTLSHeadByte {
|
||||
switch {
|
||||
case n == 1 && int(buf[0]) == FRPTLSHeadByte:
|
||||
out = tls.Server(c, tlsConfig)
|
||||
isTLS = true
|
||||
custom = true
|
||||
} else if n == 1 && int(buf[0]) == 0x16 {
|
||||
case n == 1 && int(buf[0]) == 0x16:
|
||||
out = tls.Server(sc, tlsConfig)
|
||||
isTLS = true
|
||||
} else {
|
||||
default:
|
||||
if tlsOnly {
|
||||
err = fmt.Errorf("non-TLS connection received on a TlsOnly server")
|
||||
return
|
||||
|
@ -55,7 +55,7 @@ func NewFakeUDPConn(l *UDPListener, laddr, raddr net.Addr) *FakeUDPConn {
|
||||
for {
|
||||
time.Sleep(5 * time.Second)
|
||||
fc.mu.RLock()
|
||||
if time.Now().Sub(fc.lastActive) > 10*time.Second {
|
||||
if time.Since(fc.lastActive) > 10*time.Second {
|
||||
fc.mu.RUnlock()
|
||||
fc.Close()
|
||||
break
|
||||
@ -68,8 +68,7 @@ func NewFakeUDPConn(l *UDPListener, laddr, raddr net.Addr) *FakeUDPConn {
|
||||
|
||||
func (c *FakeUDPConn) putPacket(content []byte) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
}
|
||||
_ = recover()
|
||||
}()
|
||||
|
||||
select {
|
||||
@ -109,7 +108,7 @@ func (c *FakeUDPConn) Write(b []byte) (n int, err error) {
|
||||
LocalAddr: c.localAddr,
|
||||
RemoteAddr: c.remoteAddr,
|
||||
}
|
||||
c.l.writeUDPPacket(packet)
|
||||
_ = c.l.writeUDPPacket(packet)
|
||||
|
||||
c.mu.Lock()
|
||||
c.lastActive = time.Now()
|
||||
@ -208,7 +207,7 @@ func ListenUDP(bindAddr string, bindPort int) (l *UDPListener, err error) {
|
||||
}
|
||||
|
||||
if addr, ok := packet.RemoteAddr.(*net.UDPAddr); ok {
|
||||
readConn.WriteToUDP(packet.Buf, addr)
|
||||
_, _ = readConn.WriteToUDP(packet.Buf, addr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
@ -9,9 +9,7 @@ import (
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrWebsocketListenerClosed = errors.New("websocket listener closed")
|
||||
)
|
||||
var ErrWebsocketListenerClosed = errors.New("websocket listener closed")
|
||||
|
||||
const (
|
||||
FrpWebsocketPath = "/~!frp"
|
||||
@ -21,8 +19,7 @@ type WebsocketListener struct {
|
||||
ln net.Listener
|
||||
acceptCh chan net.Conn
|
||||
|
||||
server *http.Server
|
||||
httpMutex *http.ServeMux
|
||||
server *http.Server
|
||||
}
|
||||
|
||||
// NewWebsocketListener to handle websocket connections
|
||||
@ -47,7 +44,9 @@ func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) {
|
||||
Handler: muxer,
|
||||
}
|
||||
|
||||
go wl.server.Serve(ln)
|
||||
go func() {
|
||||
_ = wl.server.Serve(ln)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,10 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
gnet "github.com/fatedier/golib/net"
|
||||
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
"github.com/fatedier/frp/pkg/util/vhost"
|
||||
gnet "github.com/fatedier/golib/net"
|
||||
)
|
||||
|
||||
type HTTPConnectTCPMuxer struct {
|
||||
@ -66,7 +67,11 @@ func (muxer *HTTPConnectTCPMuxer) sendConnectResponse(c net.Conn, reqInfo map[st
|
||||
if muxer.passthrough {
|
||||
return nil
|
||||
}
|
||||
return util.OkResponse().Write(c)
|
||||
res := util.OkResponse()
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
return res.Write(c)
|
||||
}
|
||||
|
||||
func (muxer *HTTPConnectTCPMuxer) getHostFromHTTPConnect(c net.Conn) (net.Conn, map[string]string, error) {
|
||||
@ -82,11 +87,15 @@ func (muxer *HTTPConnectTCPMuxer) getHostFromHTTPConnect(c net.Conn) (net.Conn,
|
||||
reqInfoMap["Scheme"] = "tcp"
|
||||
reqInfoMap["HTTPUser"] = httpUser
|
||||
|
||||
var outConn net.Conn = c
|
||||
outConn := c
|
||||
if muxer.passthrough {
|
||||
outConn = sc
|
||||
if muxer.authRequired && httpUser == "" {
|
||||
util.ProxyUnauthorizedResponse().Write(c)
|
||||
resp := util.ProxyUnauthorizedResponse()
|
||||
if resp.Body != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
_ = resp.Write(c)
|
||||
outConn = c
|
||||
}
|
||||
}
|
||||
|
@ -60,10 +60,8 @@ func CanonicalHost(host string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(host, ".") {
|
||||
// Strip trailing dot from fully qualified domain names.
|
||||
host = host[:len(host)-1]
|
||||
}
|
||||
// Strip trailing dot from fully qualified domain names.
|
||||
host = strings.TrimSuffix(host, ".")
|
||||
return host, nil
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ func RandIDWithLen(idLen int) (id string, err error) {
|
||||
}
|
||||
|
||||
func GetAuthKey(token string, timestamp int64) (key string) {
|
||||
token = token + fmt.Sprintf("%d", timestamp)
|
||||
token += fmt.Sprintf("%d", timestamp)
|
||||
md5Ctx := md5.New()
|
||||
md5Ctx.Write([]byte(token))
|
||||
data := md5Ctx.Sum(nil)
|
||||
@ -70,7 +70,8 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
|
||||
numArray := strings.Split(numRangeStr, "-")
|
||||
// length: only 1 or 2 is correct
|
||||
rangeType := len(numArray)
|
||||
if rangeType == 1 {
|
||||
switch rangeType {
|
||||
case 1:
|
||||
// single number
|
||||
singleNum, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
|
||||
if errRet != nil {
|
||||
@ -78,7 +79,7 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
|
||||
return
|
||||
}
|
||||
numbers = append(numbers, singleNum)
|
||||
} else if rangeType == 2 {
|
||||
case 2:
|
||||
// range numbers
|
||||
min, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
|
||||
if errRet != nil {
|
||||
@ -97,7 +98,7 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
|
||||
for i := min; i <= max; i++ {
|
||||
numbers = append(numbers, i)
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
err = fmt.Errorf("range number is invalid")
|
||||
return
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var version string = "0.44.0"
|
||||
var version = "0.44.0"
|
||||
|
||||
func Full() string {
|
||||
return version
|
||||
|
@ -23,27 +23,26 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
"github.com/fatedier/golib/pool"
|
||||
|
||||
frpLog "github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
|
||||
"github.com/fatedier/golib/pool"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoRouteFound = errors.New("no route found")
|
||||
)
|
||||
var ErrNoRouteFound = errors.New("no route found")
|
||||
|
||||
type HTTPReverseProxyOptions struct {
|
||||
ResponseHeaderTimeoutS int64
|
||||
}
|
||||
|
||||
type HTTPReverseProxy struct {
|
||||
proxy *ReverseProxy
|
||||
proxy *httputil.ReverseProxy
|
||||
vhostRouter *Routers
|
||||
|
||||
responseHeaderTimeout time.Duration
|
||||
@ -57,7 +56,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
||||
responseHeaderTimeout: time.Duration(option.ResponseHeaderTimeoutS) * time.Second,
|
||||
vhostRouter: vhostRouter,
|
||||
}
|
||||
proxy := &ReverseProxy{
|
||||
proxy := &httputil.ReverseProxy{
|
||||
// Modify incoming requests by route policies.
|
||||
Director: func(req *http.Request) {
|
||||
req.URL.Scheme = "http"
|
||||
@ -81,7 +80,6 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
||||
} else {
|
||||
req.URL.Host = req.Host
|
||||
}
|
||||
|
||||
},
|
||||
// Create a connection to one proxy routed by route policy.
|
||||
Transport: &http.Transport{
|
||||
@ -114,7 +112,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
||||
ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) {
|
||||
frpLog.Warn("do http proxy request [host: %s] error: %v", req.Host, err)
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
rw.Write(getNotFoundPageContent())
|
||||
_, _ = rw.Write(getNotFoundPageContent())
|
||||
},
|
||||
}
|
||||
rp.proxy = proxy
|
||||
@ -257,10 +255,28 @@ func (rp *HTTPReverseProxy) connectHandler(rw http.ResponseWriter, req *http.Req
|
||||
client.Close()
|
||||
return
|
||||
}
|
||||
req.Write(remote)
|
||||
_ = req.Write(remote)
|
||||
go frpIo.Join(remote, client)
|
||||
}
|
||||
|
||||
func parseBasicAuth(auth string) (username, password string, ok bool) {
|
||||
const prefix = "Basic "
|
||||
// Case insensitive prefix match. See Issue 22736.
|
||||
if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
|
||||
return
|
||||
}
|
||||
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cs := string(c)
|
||||
s := strings.IndexByte(cs, ':')
|
||||
if s < 0 {
|
||||
return
|
||||
}
|
||||
return cs[:s], cs[s+1:], true
|
||||
}
|
||||
|
||||
func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Request {
|
||||
newctx := req.Context()
|
||||
newctx = context.WithValue(newctx, RouteInfoURL, req.URL.Path)
|
||||
|
@ -24,9 +24,7 @@ import (
|
||||
"github.com/fatedier/frp/pkg/util/version"
|
||||
)
|
||||
|
||||
var (
|
||||
NotFoundPagePath = ""
|
||||
)
|
||||
var NotFoundPagePath = ""
|
||||
|
||||
const (
|
||||
NotFound = `<!DOCTYPE html>
|
||||
|
@ -1,636 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// HTTP reverse proxy handler
|
||||
|
||||
package vhost
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http/httpguts"
|
||||
)
|
||||
|
||||
// ReverseProxy is an HTTP Handler that takes an incoming request and
|
||||
// sends it to another server, proxying the response back to the
|
||||
// client.
|
||||
//
|
||||
// ReverseProxy by default sets the client IP as the value of the
|
||||
// X-Forwarded-For header.
|
||||
//
|
||||
// If an X-Forwarded-For header already exists, the client IP is
|
||||
// appended to the existing values. As a special case, if the header
|
||||
// exists in the Request.Header map but has a nil value (such as when
|
||||
// set by the Director func), the X-Forwarded-For header is
|
||||
// not modified.
|
||||
//
|
||||
// To prevent IP spoofing, be sure to delete any pre-existing
|
||||
// X-Forwarded-For header coming from the client or
|
||||
// an untrusted proxy.
|
||||
type ReverseProxy struct {
|
||||
// Director must be a function which modifies
|
||||
// the request into a new request to be sent
|
||||
// using Transport. Its response is then copied
|
||||
// back to the original client unmodified.
|
||||
// Director must not access the provided Request
|
||||
// after returning.
|
||||
Director func(*http.Request)
|
||||
|
||||
// The transport used to perform proxy requests.
|
||||
// If nil, http.DefaultTransport is used.
|
||||
Transport http.RoundTripper
|
||||
|
||||
// FlushInterval specifies the flush interval
|
||||
// to flush to the client while copying the
|
||||
// response body.
|
||||
// If zero, no periodic flushing is done.
|
||||
// A negative value means to flush immediately
|
||||
// after each write to the client.
|
||||
// The FlushInterval is ignored when ReverseProxy
|
||||
// recognizes a response as a streaming response, or
|
||||
// if its ContentLength is -1; for such responses, writes
|
||||
// are flushed to the client immediately.
|
||||
FlushInterval time.Duration
|
||||
|
||||
// ErrorLog specifies an optional logger for errors
|
||||
// that occur when attempting to proxy the request.
|
||||
// If nil, logging is done via the log package's standard logger.
|
||||
ErrorLog *log.Logger
|
||||
|
||||
// BufferPool optionally specifies a buffer pool to
|
||||
// get byte slices for use by io.CopyBuffer when
|
||||
// copying HTTP response bodies.
|
||||
BufferPool BufferPool
|
||||
|
||||
// ModifyResponse is an optional function that modifies the
|
||||
// Response from the backend. It is called if the backend
|
||||
// returns a response at all, with any HTTP status code.
|
||||
// If the backend is unreachable, the optional ErrorHandler is
|
||||
// called without any call to ModifyResponse.
|
||||
//
|
||||
// If ModifyResponse returns an error, ErrorHandler is called
|
||||
// with its error value. If ErrorHandler is nil, its default
|
||||
// implementation is used.
|
||||
ModifyResponse func(*http.Response) error
|
||||
|
||||
// ErrorHandler is an optional function that handles errors
|
||||
// reaching the backend or errors from ModifyResponse.
|
||||
//
|
||||
// If nil, the default is to log the provided error and return
|
||||
// a 502 Status Bad Gateway response.
|
||||
ErrorHandler func(http.ResponseWriter, *http.Request, error)
|
||||
}
|
||||
|
||||
// A BufferPool is an interface for getting and returning temporary
|
||||
// byte slices for use by io.CopyBuffer.
|
||||
type BufferPool interface {
|
||||
Get() []byte
|
||||
Put([]byte)
|
||||
}
|
||||
|
||||
func singleJoiningSlash(a, b string) string {
|
||||
aslash := strings.HasSuffix(a, "/")
|
||||
bslash := strings.HasPrefix(b, "/")
|
||||
switch {
|
||||
case aslash && bslash:
|
||||
return a + b[1:]
|
||||
case !aslash && !bslash:
|
||||
return a + "/" + b
|
||||
}
|
||||
return a + b
|
||||
}
|
||||
|
||||
func joinURLPath(a, b *url.URL) (path, rawpath string) {
|
||||
if a.RawPath == "" && b.RawPath == "" {
|
||||
return singleJoiningSlash(a.Path, b.Path), ""
|
||||
}
|
||||
// Same as singleJoiningSlash, but uses EscapedPath to determine
|
||||
// whether a slash should be added
|
||||
apath := a.EscapedPath()
|
||||
bpath := b.EscapedPath()
|
||||
|
||||
aslash := strings.HasSuffix(apath, "/")
|
||||
bslash := strings.HasPrefix(bpath, "/")
|
||||
|
||||
switch {
|
||||
case aslash && bslash:
|
||||
return a.Path + b.Path[1:], apath + bpath[1:]
|
||||
case !aslash && !bslash:
|
||||
return a.Path + "/" + b.Path, apath + "/" + bpath
|
||||
}
|
||||
return a.Path + b.Path, apath + bpath
|
||||
}
|
||||
|
||||
// NewSingleHostReverseProxy returns a new ReverseProxy that routes
|
||||
// URLs to the scheme, host, and base path provided in target. If the
|
||||
// target's path is "/base" and the incoming request was for "/dir",
|
||||
// the target request will be for /base/dir.
|
||||
// NewSingleHostReverseProxy does not rewrite the Host header.
|
||||
// To rewrite Host headers, use ReverseProxy directly with a custom
|
||||
// Director policy.
|
||||
func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
|
||||
targetQuery := target.RawQuery
|
||||
director := func(req *http.Request) {
|
||||
req.URL.Scheme = target.Scheme
|
||||
req.URL.Host = target.Host
|
||||
req.URL.Path, req.URL.RawPath = joinURLPath(target, req.URL)
|
||||
if targetQuery == "" || req.URL.RawQuery == "" {
|
||||
req.URL.RawQuery = targetQuery + req.URL.RawQuery
|
||||
} else {
|
||||
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
|
||||
}
|
||||
if _, ok := req.Header["User-Agent"]; !ok {
|
||||
// explicitly disable User-Agent so it's not set to default value
|
||||
req.Header.Set("User-Agent", "")
|
||||
}
|
||||
}
|
||||
return &ReverseProxy{Director: director}
|
||||
}
|
||||
|
||||
func copyHeader(dst, src http.Header) {
|
||||
for k, vv := range src {
|
||||
for _, v := range vv {
|
||||
dst.Add(k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hop-by-hop headers. These are removed when sent to the backend.
|
||||
// As of RFC 7230, hop-by-hop headers are required to appear in the
|
||||
// Connection header field. These are the headers defined by the
|
||||
// obsoleted RFC 2616 (section 13.5.1) and are used for backward
|
||||
// compatibility.
|
||||
var hopHeaders = []string{
|
||||
"Connection",
|
||||
"Proxy-Connection", // non-standard but still sent by libcurl and rejected by e.g. google
|
||||
"Keep-Alive",
|
||||
"Proxy-Authenticate",
|
||||
"Proxy-Authorization",
|
||||
"Te", // canonicalized version of "TE"
|
||||
"Trailer", // not Trailers per URL above; https://www.rfc-editor.org/errata_search.php?eid=4522
|
||||
"Transfer-Encoding",
|
||||
"Upgrade",
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) defaultErrorHandler(rw http.ResponseWriter, req *http.Request, err error) {
|
||||
p.logf("http: proxy error: %v", err)
|
||||
rw.WriteHeader(http.StatusBadGateway)
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) getErrorHandler() func(http.ResponseWriter, *http.Request, error) {
|
||||
if p.ErrorHandler != nil {
|
||||
return p.ErrorHandler
|
||||
}
|
||||
return p.defaultErrorHandler
|
||||
}
|
||||
|
||||
// modifyResponse conditionally runs the optional ModifyResponse hook
|
||||
// and reports whether the request should proceed.
|
||||
func (p *ReverseProxy) modifyResponse(rw http.ResponseWriter, res *http.Response, req *http.Request) bool {
|
||||
if p.ModifyResponse == nil {
|
||||
return true
|
||||
}
|
||||
if err := p.ModifyResponse(res); err != nil {
|
||||
res.Body.Close()
|
||||
p.getErrorHandler()(rw, req, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func parseBasicAuth(auth string) (username, password string, ok bool) {
|
||||
const prefix = "Basic "
|
||||
// Case insensitive prefix match. See Issue 22736.
|
||||
if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
|
||||
return
|
||||
}
|
||||
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cs := string(c)
|
||||
s := strings.IndexByte(cs, ':')
|
||||
if s < 0 {
|
||||
return
|
||||
}
|
||||
return cs[:s], cs[s+1:], true
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
transport := p.Transport
|
||||
if transport == nil {
|
||||
transport = http.DefaultTransport
|
||||
}
|
||||
|
||||
ctx := req.Context()
|
||||
if cn, ok := rw.(http.CloseNotifier); ok {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
notifyChan := cn.CloseNotify()
|
||||
go func() {
|
||||
select {
|
||||
case <-notifyChan:
|
||||
cancel()
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
outreq := req.Clone(ctx)
|
||||
if req.ContentLength == 0 {
|
||||
outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
|
||||
}
|
||||
if outreq.Header == nil {
|
||||
outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
|
||||
}
|
||||
|
||||
p.Director(outreq)
|
||||
outreq.Close = false
|
||||
|
||||
reqUpType := upgradeType(outreq.Header)
|
||||
removeConnectionHeaders(outreq.Header)
|
||||
|
||||
// Remove hop-by-hop headers to the backend. Especially
|
||||
// important is "Connection" because we want a persistent
|
||||
// connection, regardless of what the client sent to us.
|
||||
for _, h := range hopHeaders {
|
||||
hv := outreq.Header.Get(h)
|
||||
if hv == "" {
|
||||
continue
|
||||
}
|
||||
if h == "Te" && hv == "trailers" {
|
||||
// Issue 21096: tell backend applications that
|
||||
// care about trailer support that we support
|
||||
// trailers. (We do, but we don't go out of
|
||||
// our way to advertise that unless the
|
||||
// incoming client request thought it was
|
||||
// worth mentioning)
|
||||
continue
|
||||
}
|
||||
outreq.Header.Del(h)
|
||||
}
|
||||
|
||||
// After stripping all the hop-by-hop connection headers above, add back any
|
||||
// necessary for protocol upgrades, such as for websockets.
|
||||
if reqUpType != "" {
|
||||
outreq.Header.Set("Connection", "Upgrade")
|
||||
outreq.Header.Set("Upgrade", reqUpType)
|
||||
}
|
||||
|
||||
if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
|
||||
// If we aren't the first proxy retain prior
|
||||
// X-Forwarded-For information as a comma+space
|
||||
// separated list and fold multiple headers into one.
|
||||
prior, ok := outreq.Header["X-Forwarded-For"]
|
||||
omit := ok && prior == nil // Issue 38079: nil now means don't populate the header
|
||||
if len(prior) > 0 {
|
||||
clientIP = strings.Join(prior, ", ") + ", " + clientIP
|
||||
}
|
||||
if !omit {
|
||||
outreq.Header.Set("X-Forwarded-For", clientIP)
|
||||
}
|
||||
}
|
||||
|
||||
res, err := transport.RoundTrip(outreq)
|
||||
if err != nil {
|
||||
p.getErrorHandler()(rw, outreq, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Deal with 101 Switching Protocols responses: (WebSocket, h2c, etc)
|
||||
if res.StatusCode == http.StatusSwitchingProtocols {
|
||||
if !p.modifyResponse(rw, res, outreq) {
|
||||
return
|
||||
}
|
||||
p.handleUpgradeResponse(rw, outreq, res)
|
||||
return
|
||||
}
|
||||
|
||||
removeConnectionHeaders(res.Header)
|
||||
|
||||
for _, h := range hopHeaders {
|
||||
res.Header.Del(h)
|
||||
}
|
||||
|
||||
if !p.modifyResponse(rw, res, outreq) {
|
||||
return
|
||||
}
|
||||
|
||||
copyHeader(rw.Header(), res.Header)
|
||||
|
||||
// The "Trailer" header isn't included in the Transport's response,
|
||||
// at least for *http.Transport. Build it up from Trailer.
|
||||
announcedTrailers := len(res.Trailer)
|
||||
if announcedTrailers > 0 {
|
||||
trailerKeys := make([]string, 0, len(res.Trailer))
|
||||
for k := range res.Trailer {
|
||||
trailerKeys = append(trailerKeys, k)
|
||||
}
|
||||
rw.Header().Add("Trailer", strings.Join(trailerKeys, ", "))
|
||||
}
|
||||
|
||||
rw.WriteHeader(res.StatusCode)
|
||||
|
||||
err = p.copyResponse(rw, res.Body, p.flushInterval(res))
|
||||
if err != nil {
|
||||
defer res.Body.Close()
|
||||
// Since we're streaming the response, if we run into an error all we can do
|
||||
// is abort the request. Issue 23643: ReverseProxy should use ErrAbortHandler
|
||||
// on read error while copying body.
|
||||
if !shouldPanicOnCopyError(req) {
|
||||
p.logf("suppressing panic for copyResponse error in test; copy error: %v", err)
|
||||
return
|
||||
}
|
||||
panic(http.ErrAbortHandler)
|
||||
}
|
||||
res.Body.Close() // close now, instead of defer, to populate res.Trailer
|
||||
|
||||
if len(res.Trailer) > 0 {
|
||||
// Force chunking if we saw a response trailer.
|
||||
// This prevents net/http from calculating the length for short
|
||||
// bodies and adding a Content-Length.
|
||||
if fl, ok := rw.(http.Flusher); ok {
|
||||
fl.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
if len(res.Trailer) == announcedTrailers {
|
||||
copyHeader(rw.Header(), res.Trailer)
|
||||
return
|
||||
}
|
||||
|
||||
for k, vv := range res.Trailer {
|
||||
k = http.TrailerPrefix + k
|
||||
for _, v := range vv {
|
||||
rw.Header().Add(k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var inOurTests bool // whether we're in our own tests
|
||||
|
||||
// shouldPanicOnCopyError reports whether the reverse proxy should
|
||||
// panic with http.ErrAbortHandler. This is the right thing to do by
|
||||
// default, but Go 1.10 and earlier did not, so existing unit tests
|
||||
// weren't expecting panics. Only panic in our own tests, or when
|
||||
// running under the HTTP server.
|
||||
func shouldPanicOnCopyError(req *http.Request) bool {
|
||||
if inOurTests {
|
||||
// Our tests know to handle this panic.
|
||||
return true
|
||||
}
|
||||
if req.Context().Value(http.ServerContextKey) != nil {
|
||||
// We seem to be running under an HTTP server, so
|
||||
// it'll recover the panic.
|
||||
return true
|
||||
}
|
||||
// Otherwise act like Go 1.10 and earlier to not break
|
||||
// existing tests.
|
||||
return false
|
||||
}
|
||||
|
||||
// removeConnectionHeaders removes hop-by-hop headers listed in the "Connection" header of h.
|
||||
// See RFC 7230, section 6.1
|
||||
func removeConnectionHeaders(h http.Header) {
|
||||
for _, f := range h["Connection"] {
|
||||
for _, sf := range strings.Split(f, ",") {
|
||||
if sf = textproto.TrimString(sf); sf != "" {
|
||||
h.Del(sf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// flushInterval returns the p.FlushInterval value, conditionally
|
||||
// overriding its value for a specific request/response.
|
||||
func (p *ReverseProxy) flushInterval(res *http.Response) time.Duration {
|
||||
resCT := res.Header.Get("Content-Type")
|
||||
|
||||
// For Server-Sent Events responses, flush immediately.
|
||||
// The MIME type is defined in https://www.w3.org/TR/eventsource/#text-event-stream
|
||||
if resCT == "text/event-stream" {
|
||||
return -1 // negative means immediately
|
||||
}
|
||||
|
||||
// We might have the case of streaming for which Content-Length might be unset.
|
||||
if res.ContentLength == -1 {
|
||||
return -1
|
||||
}
|
||||
|
||||
return p.FlushInterval
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader, flushInterval time.Duration) error {
|
||||
if flushInterval != 0 {
|
||||
if wf, ok := dst.(writeFlusher); ok {
|
||||
mlw := &maxLatencyWriter{
|
||||
dst: wf,
|
||||
latency: flushInterval,
|
||||
}
|
||||
defer mlw.stop()
|
||||
|
||||
// set up initial timer so headers get flushed even if body writes are delayed
|
||||
mlw.flushPending = true
|
||||
mlw.t = time.AfterFunc(flushInterval, mlw.delayedFlush)
|
||||
|
||||
dst = mlw
|
||||
}
|
||||
}
|
||||
|
||||
var buf []byte
|
||||
if p.BufferPool != nil {
|
||||
buf = p.BufferPool.Get()
|
||||
defer p.BufferPool.Put(buf)
|
||||
}
|
||||
_, err := p.copyBuffer(dst, src, buf)
|
||||
return err
|
||||
}
|
||||
|
||||
// copyBuffer returns any write errors or non-EOF read errors, and the amount
|
||||
// of bytes written.
|
||||
func (p *ReverseProxy) copyBuffer(dst io.Writer, src io.Reader, buf []byte) (int64, error) {
|
||||
if len(buf) == 0 {
|
||||
buf = make([]byte, 32*1024)
|
||||
}
|
||||
var written int64
|
||||
for {
|
||||
nr, rerr := src.Read(buf)
|
||||
if rerr != nil && rerr != io.EOF && rerr != context.Canceled {
|
||||
p.logf("httputil: ReverseProxy read error during body copy: %v", rerr)
|
||||
}
|
||||
if nr > 0 {
|
||||
nw, werr := dst.Write(buf[:nr])
|
||||
if nw > 0 {
|
||||
written += int64(nw)
|
||||
}
|
||||
if werr != nil {
|
||||
return written, werr
|
||||
}
|
||||
if nr != nw {
|
||||
return written, io.ErrShortWrite
|
||||
}
|
||||
}
|
||||
if rerr != nil {
|
||||
if rerr == io.EOF {
|
||||
rerr = nil
|
||||
}
|
||||
return written, rerr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) logf(format string, args ...interface{}) {
|
||||
if p.ErrorLog != nil {
|
||||
p.ErrorLog.Printf(format, args...)
|
||||
} else {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
type writeFlusher interface {
|
||||
io.Writer
|
||||
http.Flusher
|
||||
}
|
||||
|
||||
type maxLatencyWriter struct {
|
||||
dst writeFlusher
|
||||
latency time.Duration // non-zero; negative means to flush immediately
|
||||
|
||||
mu sync.Mutex // protects t, flushPending, and dst.Flush
|
||||
t *time.Timer
|
||||
flushPending bool
|
||||
}
|
||||
|
||||
func (m *maxLatencyWriter) Write(p []byte) (n int, err error) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
n, err = m.dst.Write(p)
|
||||
if m.latency < 0 {
|
||||
m.dst.Flush()
|
||||
return
|
||||
}
|
||||
if m.flushPending {
|
||||
return
|
||||
}
|
||||
if m.t == nil {
|
||||
m.t = time.AfterFunc(m.latency, m.delayedFlush)
|
||||
} else {
|
||||
m.t.Reset(m.latency)
|
||||
}
|
||||
m.flushPending = true
|
||||
return
|
||||
}
|
||||
|
||||
func (m *maxLatencyWriter) delayedFlush() {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if !m.flushPending { // if stop was called but AfterFunc already started this goroutine
|
||||
return
|
||||
}
|
||||
m.dst.Flush()
|
||||
m.flushPending = false
|
||||
}
|
||||
|
||||
func (m *maxLatencyWriter) stop() {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.flushPending = false
|
||||
if m.t != nil {
|
||||
m.t.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
func upgradeType(h http.Header) string {
|
||||
if !httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade") {
|
||||
return ""
|
||||
}
|
||||
return strings.ToLower(h.Get("Upgrade"))
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.Request, res *http.Response) {
|
||||
reqUpType := upgradeType(req.Header)
|
||||
resUpType := upgradeType(res.Header)
|
||||
if reqUpType != resUpType {
|
||||
p.getErrorHandler()(rw, req, fmt.Errorf("backend tried to switch protocol %q when %q was requested", resUpType, reqUpType))
|
||||
return
|
||||
}
|
||||
|
||||
hj, ok := rw.(http.Hijacker)
|
||||
if !ok {
|
||||
p.getErrorHandler()(rw, req, fmt.Errorf("can't switch protocols using non-Hijacker ResponseWriter type %T", rw))
|
||||
return
|
||||
}
|
||||
backConn, ok := res.Body.(io.ReadWriteCloser)
|
||||
if !ok {
|
||||
p.getErrorHandler()(rw, req, fmt.Errorf("internal error: 101 switching protocols response with non-writable body"))
|
||||
return
|
||||
}
|
||||
|
||||
backConnCloseCh := make(chan bool)
|
||||
go func() {
|
||||
// Ensure that the cancelation of a request closes the backend.
|
||||
// See issue https://golang.org/issue/35559.
|
||||
select {
|
||||
case <-req.Context().Done():
|
||||
case <-backConnCloseCh:
|
||||
}
|
||||
backConn.Close()
|
||||
}()
|
||||
|
||||
defer close(backConnCloseCh)
|
||||
|
||||
conn, brw, err := hj.Hijack()
|
||||
if err != nil {
|
||||
p.getErrorHandler()(rw, req, fmt.Errorf("Hijack failed on protocol switch: %v", err))
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
copyHeader(rw.Header(), res.Header)
|
||||
|
||||
res.Header = rw.Header()
|
||||
res.Body = nil // so res.Write only writes the headers; we have res.Body in backConn above
|
||||
if err := res.Write(brw); err != nil {
|
||||
p.getErrorHandler()(rw, req, fmt.Errorf("response write: %v", err))
|
||||
return
|
||||
}
|
||||
if err := brw.Flush(); err != nil {
|
||||
p.getErrorHandler()(rw, req, fmt.Errorf("response flush: %v", err))
|
||||
return
|
||||
}
|
||||
errc := make(chan error, 1)
|
||||
spc := switchProtocolCopier{user: conn, backend: backConn}
|
||||
go spc.copyToBackend(errc)
|
||||
go spc.copyFromBackend(errc)
|
||||
<-errc
|
||||
return
|
||||
}
|
||||
|
||||
// switchProtocolCopier exists so goroutines proxying data back and
|
||||
// forth have nice names in stacks.
|
||||
type switchProtocolCopier struct {
|
||||
user, backend io.ReadWriter
|
||||
}
|
||||
|
||||
func (c switchProtocolCopier) copyFromBackend(errc chan<- error) {
|
||||
_, err := io.Copy(c.user, c.backend)
|
||||
errc <- err
|
||||
}
|
||||
|
||||
func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
|
||||
_, err := io.Copy(c.backend, c.user)
|
||||
errc <- err
|
||||
}
|
@ -7,9 +7,7 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrRouterConfigConflict = errors.New("router config conflict")
|
||||
)
|
||||
var ErrRouterConfigConflict = errors.New("router config conflict")
|
||||
|
||||
type routerByHTTPUser map[string][]*Router
|
||||
|
||||
@ -133,9 +131,11 @@ type ByLocation []*Router
|
||||
func (a ByLocation) Len() int {
|
||||
return len(a)
|
||||
}
|
||||
|
||||
func (a ByLocation) Swap(i, j int) {
|
||||
a[i], a[j] = a[j], a[i]
|
||||
}
|
||||
|
||||
func (a ByLocation) Less(i, j int) bool {
|
||||
return strings.Compare(a[i].location, a[j].location) < 0
|
||||
}
|
||||
|
@ -19,11 +19,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
)
|
||||
|
||||
type RouteInfo string
|
||||
@ -36,10 +36,12 @@ const (
|
||||
RouteInfoURLHost RouteInfo = "urlHost"
|
||||
)
|
||||
|
||||
type muxFunc func(net.Conn) (net.Conn, map[string]string, error)
|
||||
type httpAuthFunc func(net.Conn, string, string, string) (bool, error)
|
||||
type hostRewriteFunc func(net.Conn, string) (net.Conn, error)
|
||||
type successFunc func(net.Conn, map[string]string) error
|
||||
type (
|
||||
muxFunc func(net.Conn) (net.Conn, map[string]string, error)
|
||||
httpAuthFunc func(net.Conn, string, string, string) (bool, error)
|
||||
hostRewriteFunc func(net.Conn, string) (net.Conn, error)
|
||||
successFunc func(net.Conn, map[string]string) error
|
||||
)
|
||||
|
||||
// Muxer is only used for https and tcpmux proxy.
|
||||
type Muxer struct {
|
||||
@ -60,7 +62,6 @@ func NewMuxer(
|
||||
rewriteFunc hostRewriteFunc,
|
||||
timeout time.Duration,
|
||||
) (mux *Muxer, err error) {
|
||||
|
||||
mux = &Muxer{
|
||||
listener: listener,
|
||||
timeout: timeout,
|
||||
@ -111,9 +112,8 @@ func (v *Muxer) Listen(ctx context.Context, cfg *RouteConfig) (l *Listener, err
|
||||
}
|
||||
|
||||
func (v *Muxer) getListener(name, path, httpUser string) (*Listener, bool) {
|
||||
|
||||
findRouter := func(inName, inPath, inHTTPUser string) (*Listener, bool) {
|
||||
vr, ok := v.registryRouter.Get(inName, inPath, httpUser)
|
||||
vr, ok := v.registryRouter.Get(inName, inPath, inHTTPUser)
|
||||
if ok {
|
||||
return vr.payload.(*Listener), true
|
||||
}
|
||||
@ -167,14 +167,14 @@ func (v *Muxer) run() {
|
||||
|
||||
func (v *Muxer) handle(c net.Conn) {
|
||||
if err := c.SetDeadline(time.Now().Add(v.timeout)); err != nil {
|
||||
c.Close()
|
||||
_ = c.Close()
|
||||
return
|
||||
}
|
||||
|
||||
sConn, reqInfoMap, err := v.vhostFunc(c)
|
||||
if err != nil {
|
||||
log.Debug("get hostname from http/https request error: %v", err)
|
||||
c.Close()
|
||||
_ = c.Close()
|
||||
return
|
||||
}
|
||||
|
||||
@ -184,9 +184,12 @@ func (v *Muxer) handle(c net.Conn) {
|
||||
l, ok := v.getListener(name, path, httpUser)
|
||||
if !ok {
|
||||
res := notFoundResponse()
|
||||
res.Write(c)
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
_ = res.Write(c)
|
||||
log.Debug("http request for host [%s] path [%s] httpUser [%s] not found", name, path, httpUser)
|
||||
c.Close()
|
||||
_ = c.Close()
|
||||
return
|
||||
}
|
||||
|
||||
@ -194,7 +197,7 @@ func (v *Muxer) handle(c net.Conn) {
|
||||
if v.successFunc != nil {
|
||||
if err := v.successFunc(c, reqInfoMap); err != nil {
|
||||
xl.Info("success func failure on vhost connection: %v", err)
|
||||
c.Close()
|
||||
_ = c.Close()
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -203,17 +206,20 @@ func (v *Muxer) handle(c net.Conn) {
|
||||
// then verify user access
|
||||
if l.mux.authFunc != nil && l.userName != "" && l.passWord != "" {
|
||||
bAccess, err := l.mux.authFunc(c, l.userName, l.passWord, reqInfoMap["Authorization"])
|
||||
if bAccess == false || err != nil {
|
||||
if !bAccess || err != nil {
|
||||
xl.Debug("check http Authorization failed")
|
||||
res := noAuthResponse()
|
||||
res.Write(c)
|
||||
c.Close()
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
_ = res.Write(c)
|
||||
_ = c.Close()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err = sConn.SetDeadline(time.Time{}); err != nil {
|
||||
c.Close()
|
||||
_ = c.Close()
|
||||
return
|
||||
}
|
||||
c = sConn
|
||||
|
@ -23,6 +23,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/control/shutdown"
|
||||
"github.com/fatedier/golib/crypto"
|
||||
"github.com/fatedier/golib/errors"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
@ -35,10 +39,6 @@ import (
|
||||
"github.com/fatedier/frp/server/controller"
|
||||
"github.com/fatedier/frp/server/metrics"
|
||||
"github.com/fatedier/frp/server/proxy"
|
||||
|
||||
"github.com/fatedier/golib/control/shutdown"
|
||||
"github.com/fatedier/golib/crypto"
|
||||
"github.com/fatedier/golib/errors"
|
||||
)
|
||||
|
||||
type ControlManager struct {
|
||||
@ -154,7 +154,6 @@ func NewControl(
|
||||
loginMsg *msg.Login,
|
||||
serverCfg config.ServerCommonConf,
|
||||
) *Control {
|
||||
|
||||
poolCount := loginMsg.PoolCount
|
||||
if poolCount > int(serverCfg.MaxPoolCount) {
|
||||
poolCount = int(serverCfg.MaxPoolCount)
|
||||
@ -193,7 +192,7 @@ func (ctl *Control) Start() {
|
||||
ServerUDPPort: ctl.serverCfg.BindUDPPort,
|
||||
Error: "",
|
||||
}
|
||||
msg.WriteMsg(ctl.conn, loginRespMsg)
|
||||
_ = msg.WriteMsg(ctl.conn, loginRespMsg)
|
||||
|
||||
go ctl.writer()
|
||||
for i := 0; i < ctl.poolCount; i++ {
|
||||
@ -270,7 +269,7 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) {
|
||||
}
|
||||
|
||||
// When we get a work connection from pool, replace it with a new one.
|
||||
errors.PanicToError(func() {
|
||||
_ = errors.PanicToError(func() {
|
||||
ctl.sendCh <- &msg.ReqWorkConn{}
|
||||
})
|
||||
return
|
||||
@ -388,7 +387,7 @@ func (ctl *Control) stoper() {
|
||||
},
|
||||
}
|
||||
go func() {
|
||||
ctl.pluginManager.CloseProxy(notifyContent)
|
||||
_ = ctl.pluginManager.CloseProxy(notifyContent)
|
||||
}()
|
||||
}
|
||||
|
||||
@ -467,7 +466,7 @@ func (ctl *Control) manager() {
|
||||
}
|
||||
ctl.sendCh <- resp
|
||||
case *msg.CloseProxy:
|
||||
ctl.CloseProxy(m)
|
||||
_ = ctl.CloseProxy(m)
|
||||
xl.Info("close proxy [%s] success", m.ProxyName)
|
||||
case *msg.Ping:
|
||||
content := &plugin.PingContent{
|
||||
@ -528,13 +527,13 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
|
||||
err = fmt.Errorf("exceed the max_ports_per_client")
|
||||
return
|
||||
}
|
||||
ctl.portsUsedNum = ctl.portsUsedNum + pxy.GetUsedPortsNum()
|
||||
ctl.portsUsedNum += pxy.GetUsedPortsNum()
|
||||
ctl.mu.Unlock()
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
ctl.mu.Lock()
|
||||
ctl.portsUsedNum = ctl.portsUsedNum - pxy.GetUsedPortsNum()
|
||||
ctl.portsUsedNum -= pxy.GetUsedPortsNum()
|
||||
ctl.mu.Unlock()
|
||||
}
|
||||
}()
|
||||
@ -570,7 +569,7 @@ func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) {
|
||||
}
|
||||
|
||||
if ctl.serverCfg.MaxPortsPerClient > 0 {
|
||||
ctl.portsUsedNum = ctl.portsUsedNum - pxy.GetUsedPortsNum()
|
||||
ctl.portsUsedNum -= pxy.GetUsedPortsNum()
|
||||
}
|
||||
pxy.Close()
|
||||
ctl.pxyManager.Del(pxy.GetName())
|
||||
@ -590,7 +589,7 @@ func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) {
|
||||
},
|
||||
}
|
||||
go func() {
|
||||
ctl.pluginManager.CloseProxy(notifyContent)
|
||||
_ = ctl.pluginManager.CloseProxy(notifyContent)
|
||||
}()
|
||||
|
||||
return
|
||||
|
@ -21,11 +21,11 @@ import (
|
||||
"net/http/pprof"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/frp/assets"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
|
||||
"github.com/fatedier/frp/assets"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -92,6 +92,8 @@ func (svr *Service) RunDashboardServer(address string) (err error) {
|
||||
}
|
||||
ln = tls.NewListener(ln, tlsCfg)
|
||||
}
|
||||
go server.Serve(ln)
|
||||
go func() {
|
||||
_ = server.Serve(ln)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
@ -18,13 +18,13 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
"github.com/fatedier/frp/pkg/metrics/mem"
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/pkg/util/version"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type GeneralResponse struct {
|
||||
@ -63,7 +63,7 @@ func (svr *Service) APIServerInfo(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
||||
w.WriteHeader(res.Code)
|
||||
if len(res.Msg) > 0 {
|
||||
w.Write([]byte(res.Msg))
|
||||
_, _ = w.Write([]byte(res.Msg))
|
||||
}
|
||||
}()
|
||||
|
||||
@ -179,7 +179,7 @@ func (svr *Service) APIProxyByType(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
||||
w.WriteHeader(res.Code)
|
||||
if len(res.Msg) > 0 {
|
||||
w.Write([]byte(res.Msg))
|
||||
_, _ = w.Write([]byte(res.Msg))
|
||||
}
|
||||
}()
|
||||
log.Info("Http request: [%s]", r.URL.Path)
|
||||
@ -245,12 +245,12 @@ func (svr *Service) APIProxyByTypeAndName(w http.ResponseWriter, r *http.Request
|
||||
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
||||
w.WriteHeader(res.Code)
|
||||
if len(res.Msg) > 0 {
|
||||
w.Write([]byte(res.Msg))
|
||||
_, _ = w.Write([]byte(res.Msg))
|
||||
}
|
||||
}()
|
||||
log.Info("Http request: [%s]", r.URL.Path)
|
||||
|
||||
proxyStatsResp := GetProxyStatsResp{}
|
||||
var proxyStatsResp GetProxyStatsResp
|
||||
proxyStatsResp, res.Code, res.Msg = svr.getProxyStatsByTypeAndName(proxyType, name)
|
||||
if res.Code != 200 {
|
||||
return
|
||||
@ -313,7 +313,7 @@ func (svr *Service) APIProxyTraffic(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
||||
w.WriteHeader(res.Code)
|
||||
if len(res.Msg) > 0 {
|
||||
w.Write([]byte(res.Msg))
|
||||
_, _ = w.Write([]byte(res.Msg))
|
||||
}
|
||||
}()
|
||||
log.Info("Http request: [%s]", r.URL.Path)
|
||||
|
@ -31,7 +31,6 @@ func (ctl *HTTPGroupController) Register(
|
||||
proxyName, group, groupKey string,
|
||||
routeConfig vhost.RouteConfig,
|
||||
) (err error) {
|
||||
|
||||
indexKey := group
|
||||
ctl.mu.Lock()
|
||||
g, ok := ctl.groups[indexKey]
|
||||
@ -86,7 +85,6 @@ func (g *HTTPGroup) Register(
|
||||
proxyName, group, groupKey string,
|
||||
routeConfig vhost.RouteConfig,
|
||||
) (err error) {
|
||||
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
if len(g.createFuncs) == 0 {
|
||||
@ -152,7 +150,7 @@ func (g *HTTPGroup) createConn(remoteAddr string) (net.Conn, error) {
|
||||
routeByHTTPUser := g.routeByHTTPUser
|
||||
if len(g.pxyNames) > 0 {
|
||||
name := g.pxyNames[int(newIndex)%len(g.pxyNames)]
|
||||
f, _ = g.createFuncs[name]
|
||||
f = g.createFuncs[name]
|
||||
}
|
||||
g.mu.RUnlock()
|
||||
|
||||
|
@ -19,9 +19,9 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/fatedier/frp/server/ports"
|
||||
|
||||
gerr "github.com/fatedier/golib/errors"
|
||||
|
||||
"github.com/fatedier/frp/server/ports"
|
||||
)
|
||||
|
||||
// TCPGroupCtl manage all TCPGroups
|
||||
@ -44,8 +44,8 @@ func NewTCPGroupCtl(portManager *ports.Manager) *TCPGroupCtl {
|
||||
// Listen is the wrapper for TCPGroup's Listen
|
||||
// If there are no group, we will create one here
|
||||
func (tgc *TCPGroupCtl) Listen(proxyName string, group string, groupKey string,
|
||||
addr string, port int) (l net.Listener, realPort int, err error) {
|
||||
|
||||
addr string, port int,
|
||||
) (l net.Listener, realPort int, err error) {
|
||||
tgc.mu.Lock()
|
||||
tcpGroup, ok := tgc.groups[group]
|
||||
if !ok {
|
||||
@ -73,7 +73,6 @@ type TCPGroup struct {
|
||||
realPort int
|
||||
|
||||
acceptCh chan net.Conn
|
||||
index uint64
|
||||
tcpLn net.Listener
|
||||
lns []*TCPGroupListener
|
||||
ctl *TCPGroupCtl
|
||||
|
@ -20,11 +20,11 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
gerr "github.com/fatedier/golib/errors"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
"github.com/fatedier/frp/pkg/util/tcpmux"
|
||||
"github.com/fatedier/frp/pkg/util/vhost"
|
||||
|
||||
gerr "github.com/fatedier/golib/errors"
|
||||
)
|
||||
|
||||
// TCPMuxGroupCtl manage all TCPMuxGroups
|
||||
@ -51,7 +51,6 @@ func (tmgc *TCPMuxGroupCtl) Listen(
|
||||
multiplexer, group, groupKey string,
|
||||
routeConfig vhost.RouteConfig,
|
||||
) (l net.Listener, err error) {
|
||||
|
||||
tmgc.mu.Lock()
|
||||
tcpMuxGroup, ok := tmgc.groups[group]
|
||||
if !ok {
|
||||
@ -84,7 +83,6 @@ type TCPMuxGroup struct {
|
||||
routeByHTTPUser string
|
||||
|
||||
acceptCh chan net.Conn
|
||||
index uint64
|
||||
tcpMuxLn net.Listener
|
||||
lns []*TCPMuxGroupListener
|
||||
ctl *TCPMuxGroupCtl
|
||||
@ -108,7 +106,6 @@ func (tmg *TCPMuxGroup) HTTPConnectListen(
|
||||
group, groupKey string,
|
||||
routeConfig vhost.RouteConfig,
|
||||
) (ln *TCPMuxGroupListener, err error) {
|
||||
|
||||
tmg.mu.Lock()
|
||||
defer tmg.mu.Unlock()
|
||||
if len(tmg.lns) == 0 {
|
||||
|
@ -19,13 +19,13 @@ import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
"github.com/fatedier/frp/pkg/util/vhost"
|
||||
"github.com/fatedier/frp/server/metrics"
|
||||
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
)
|
||||
|
||||
type HTTPProxy struct {
|
||||
@ -89,7 +89,7 @@ func (pxy *HTTPProxy) Run() (remoteAddr string, err error) {
|
||||
pxy.rc.HTTPReverseProxy.UnRegister(tmpRouteConfig)
|
||||
})
|
||||
}
|
||||
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(pxy.serverCfg.VhostHTTPPort)))
|
||||
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, pxy.serverCfg.VhostHTTPPort))
|
||||
xl.Info("http proxy listen for host [%s] location [%s] group [%s], routeByHTTPUser [%s]",
|
||||
routeConfig.Domain, routeConfig.Location, pxy.cfg.Group, pxy.cfg.RouteByHTTPUser)
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ func (pxy *HTTPSProxy) Run() (remoteAddr string, err error) {
|
||||
}
|
||||
xl.Info("https proxy listen for host [%s]", routeConfig.Domain)
|
||||
pxy.listeners = append(pxy.listeners, l)
|
||||
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(pxy.serverCfg.VhostHTTPSPort)))
|
||||
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, pxy.serverCfg.VhostHTTPSPort))
|
||||
}
|
||||
|
||||
pxy.startListenHandler(pxy, HandleUserTCPConnection)
|
||||
|
@ -23,6 +23,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
||||
@ -30,8 +32,6 @@ import (
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
"github.com/fatedier/frp/server/controller"
|
||||
"github.com/fatedier/frp/server/metrics"
|
||||
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
)
|
||||
|
||||
type GetWorkConnFn func() (net.Conn, error)
|
||||
@ -184,8 +184,8 @@ func (pxy *BaseProxy) startListenHandler(p Proxy, handler func(Proxy, net.Conn,
|
||||
}
|
||||
|
||||
func NewProxy(ctx context.Context, userInfo plugin.UserInfo, rc *controller.ResourceController, poolCount int,
|
||||
getWorkConnFn GetWorkConnFn, pxyConf config.ProxyConf, serverCfg config.ServerCommonConf) (pxy Proxy, err error) {
|
||||
|
||||
getWorkConnFn GetWorkConnFn, pxyConf config.ProxyConf, serverCfg config.ServerCommonConf,
|
||||
) (pxy Proxy, err error) {
|
||||
xl := xlog.FromContextSafe(ctx).Spawn().AppendPrefix(pxyConf.GetBaseInfo().ProxyName)
|
||||
basePxy := BaseProxy{
|
||||
name: pxyConf.GetBaseInfo().ProxyName,
|
||||
|
@ -22,14 +22,14 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
"github.com/fatedier/frp/pkg/proto/udp"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/server/metrics"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
)
|
||||
|
||||
type UDPProxy struct {
|
||||
@ -98,18 +98,20 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
|
||||
)
|
||||
xl.Trace("loop waiting message from udp workConn")
|
||||
// client will send heartbeat in workConn for keeping alive
|
||||
conn.SetReadDeadline(time.Now().Add(time.Duration(60) * time.Second))
|
||||
_ = conn.SetReadDeadline(time.Now().Add(time.Duration(60) * time.Second))
|
||||
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
|
||||
xl.Warn("read from workConn for udp error: %v", errRet)
|
||||
conn.Close()
|
||||
_ = conn.Close()
|
||||
// notify proxy to start a new work connection
|
||||
// ignore error here, it means the proxy is closed
|
||||
errors.PanicToError(func() {
|
||||
_ = errors.PanicToError(func() {
|
||||
pxy.checkCloseCh <- 1
|
||||
})
|
||||
return
|
||||
}
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
if err := conn.SetReadDeadline(time.Time{}); err != nil {
|
||||
xl.Warn("set read deadline error: %v", err)
|
||||
}
|
||||
switch m := rawMsg.(type) {
|
||||
case *msg.Ping:
|
||||
xl.Trace("udp work conn get ping message")
|
||||
|
@ -17,10 +17,10 @@ package proxy
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
)
|
||||
|
||||
type XTCPProxy struct {
|
||||
@ -91,7 +91,7 @@ func (pxy *XTCPProxy) GetConf() config.ProxyConf {
|
||||
func (pxy *XTCPProxy) Close() {
|
||||
pxy.BaseProxy.Close()
|
||||
pxy.rc.NatHoleController.CloseClient(pxy.GetName())
|
||||
errors.PanicToError(func() {
|
||||
_ = errors.PanicToError(func() {
|
||||
close(pxy.closeCh)
|
||||
})
|
||||
}
|
||||
|
@ -26,6 +26,9 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/net/mux"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
|
||||
"github.com/fatedier/frp/assets"
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
@ -47,9 +50,6 @@ import (
|
||||
"github.com/fatedier/frp/server/ports"
|
||||
"github.com/fatedier/frp/server/proxy"
|
||||
"github.com/fatedier/frp/server/visitor"
|
||||
|
||||
"github.com/fatedier/golib/net/mux"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -127,26 +127,26 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
||||
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.TCPMuxHTTPConnectPort))
|
||||
l, err = net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Create server listener error, %v", err)
|
||||
err = fmt.Errorf("create server listener error, %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
svr.rc.TCPMuxHTTPConnectMuxer, err = tcpmux.NewHTTPConnectTCPMuxer(l, cfg.TCPMuxPassthrough, vhostReadWriteTimeout)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Create vhost tcpMuxer error, %v", err)
|
||||
err = fmt.Errorf("create vhost tcpMuxer error, %v", err)
|
||||
return
|
||||
}
|
||||
log.Info("tcpmux httpconnect multiplexer listen on %s, passthough: %v", address, cfg.TCPMuxPassthrough)
|
||||
}
|
||||
|
||||
// Init all plugins
|
||||
plugin_names := make([]string, 0, len(cfg.HTTPPlugins))
|
||||
pluginNames := make([]string, 0, len(cfg.HTTPPlugins))
|
||||
for n := range cfg.HTTPPlugins {
|
||||
plugin_names = append(plugin_names, n)
|
||||
pluginNames = append(pluginNames, n)
|
||||
}
|
||||
sort.Strings(plugin_names)
|
||||
sort.Strings(pluginNames)
|
||||
|
||||
for _, name := range plugin_names {
|
||||
for _, name := range pluginNames {
|
||||
svr.pluginManager.Register(plugin.NewHTTPPluginOptions(cfg.HTTPPlugins[name]))
|
||||
log.Info("plugin [%s] has been registered", name)
|
||||
}
|
||||
@ -181,13 +181,15 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
||||
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.BindPort))
|
||||
ln, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Create server listener error, %v", err)
|
||||
err = fmt.Errorf("create server listener error, %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
svr.muxer = mux.NewMux(ln)
|
||||
svr.muxer.SetKeepAlive(time.Duration(cfg.TCPKeepAlive) * time.Second)
|
||||
go svr.muxer.Serve()
|
||||
go func() {
|
||||
_ = svr.muxer.Serve()
|
||||
}()
|
||||
ln = svr.muxer.DefaultListener()
|
||||
|
||||
svr.listener = ln
|
||||
@ -198,7 +200,7 @@ 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 address udp %s error: %v", address, err)
|
||||
return
|
||||
}
|
||||
log.Info("frps kcp listen on udp %s", address)
|
||||
@ -229,11 +231,13 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
||||
} else {
|
||||
l, err = net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Create vhost http listener error, %v", err)
|
||||
err = fmt.Errorf("create vhost http listener error, %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
go server.Serve(l)
|
||||
go func() {
|
||||
_ = server.Serve(l)
|
||||
}()
|
||||
log.Info("http service listen on %s", address)
|
||||
}
|
||||
|
||||
@ -246,7 +250,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
||||
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.VhostHTTPSPort))
|
||||
l, err = net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Create server listener error, %v", err)
|
||||
err = fmt.Errorf("create server listener error, %v", err)
|
||||
return
|
||||
}
|
||||
log.Info("https service listen on %s", address)
|
||||
@ -254,7 +258,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
||||
|
||||
svr.rc.VhostHTTPSMuxer, err = vhost.NewHTTPSMuxer(l, vhostReadWriteTimeout)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Create vhost httpsMuxer error, %v", err)
|
||||
err = fmt.Errorf("create vhost httpsMuxer error, %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -271,7 +275,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
||||
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.BindUDPPort))
|
||||
nc, err = nathole.NewController(address)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Create nat hole controller error, %v", err)
|
||||
err = fmt.Errorf("create nat hole controller error, %v", err)
|
||||
return
|
||||
}
|
||||
svr.rc.NatHoleController = nc
|
||||
@ -287,7 +291,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
||||
address := net.JoinHostPort(cfg.DashboardAddr, strconv.Itoa(cfg.DashboardPort))
|
||||
err = svr.RunDashboardServer(address)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Create dashboard web server error, %v", err)
|
||||
err = fmt.Errorf("create dashboard web server error, %v", err)
|
||||
return
|
||||
}
|
||||
log.Info("Dashboard listen on %s", address)
|
||||
@ -324,13 +328,13 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn) {
|
||||
err error
|
||||
)
|
||||
|
||||
conn.SetReadDeadline(time.Now().Add(connReadTimeout))
|
||||
_ = conn.SetReadDeadline(time.Now().Add(connReadTimeout))
|
||||
if rawMsg, err = msg.ReadMsg(conn); err != nil {
|
||||
log.Trace("Failed to read message: %v", err)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
_ = conn.SetReadDeadline(time.Time{})
|
||||
|
||||
switch m := rawMsg.(type) {
|
||||
case *msg.Login:
|
||||
@ -349,7 +353,7 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn) {
|
||||
// Otherwise send success message in control's work goroutine.
|
||||
if err != nil {
|
||||
xl.Warn("register control error: %v", err)
|
||||
msg.WriteMsg(conn, &msg.LoginResp{
|
||||
_ = msg.WriteMsg(conn, &msg.LoginResp{
|
||||
Version: version.Full(),
|
||||
Error: util.GenerateResponseErrorString("register control error", err, svr.cfg.DetailedErrorsToClient),
|
||||
})
|
||||
@ -362,13 +366,13 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn) {
|
||||
case *msg.NewVisitorConn:
|
||||
if err = svr.RegisterVisitorConn(conn, m); err != nil {
|
||||
xl.Warn("register visitor conn error: %v", err)
|
||||
msg.WriteMsg(conn, &msg.NewVisitorConnResp{
|
||||
_ = msg.WriteMsg(conn, &msg.NewVisitorConnResp{
|
||||
ProxyName: m.ProxyName,
|
||||
Error: util.GenerateResponseErrorString("register visitor conn error", err, svr.cfg.DetailedErrorsToClient),
|
||||
})
|
||||
conn.Close()
|
||||
} else {
|
||||
msg.WriteMsg(conn, &msg.NewVisitorConnResp{
|
||||
_ = msg.WriteMsg(conn, &msg.NewVisitorConnResp{
|
||||
ProxyName: m.ProxyName,
|
||||
Error: "",
|
||||
})
|
||||
@ -504,7 +508,7 @@ func (svr *Service) RegisterWorkConn(workConn net.Conn, newMsg *msg.NewWorkConn)
|
||||
}
|
||||
if err != nil {
|
||||
xl.Warn("invalid NewWorkConn with run id [%s]", newMsg.RunID)
|
||||
msg.WriteMsg(workConn, &msg.StartWorkConn{
|
||||
_ = msg.WriteMsg(workConn, &msg.StartWorkConn{
|
||||
Error: util.GenerateResponseErrorString("invalid NewWorkConn", err, ctl.serverCfg.DetailedErrorsToClient),
|
||||
})
|
||||
return fmt.Errorf("invalid NewWorkConn with run id [%s]", newMsg.RunID)
|
||||
|
@ -20,10 +20,10 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
)
|
||||
|
||||
// Manager for visitor listeners.
|
||||
@ -57,8 +57,8 @@ func (vm *Manager) Listen(name string, sk string) (l *frpNet.CustomListener, err
|
||||
}
|
||||
|
||||
func (vm *Manager) NewConn(name string, conn net.Conn, timestamp int64, signKey string,
|
||||
useEncryption bool, useCompression bool) (err error) {
|
||||
|
||||
useEncryption bool, useCompression bool,
|
||||
) (err error) {
|
||||
vm.mu.RLock()
|
||||
defer vm.mu.RUnlock()
|
||||
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/fatedier/frp/pkg/transport"
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
@ -12,18 +14,16 @@ import (
|
||||
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/port"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
var _ = Describe("[Feature: Basic]", func() {
|
||||
var _ = ginkgo.Describe("[Feature: Basic]", func() {
|
||||
f := framework.NewDefaultFramework()
|
||||
|
||||
Describe("TCP && UDP", func() {
|
||||
ginkgo.Describe("TCP && UDP", func() {
|
||||
types := []string{"tcp", "udp"}
|
||||
for _, t := range types {
|
||||
proxyType := t
|
||||
It(fmt.Sprintf("Expose a %s echo server", strings.ToUpper(proxyType)), func() {
|
||||
ginkgo.It(fmt.Sprintf("Expose a %s echo server", strings.ToUpper(proxyType)), func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
clientConf := consts.DefaultClientConfig
|
||||
|
||||
@ -93,8 +93,8 @@ var _ = Describe("[Feature: Basic]", func() {
|
||||
}
|
||||
})
|
||||
|
||||
Describe("HTTP", func() {
|
||||
It("proxy to HTTP server", func() {
|
||||
ginkgo.Describe("HTTP", func() {
|
||||
ginkgo.It("proxy to HTTP server", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
vhostHTTPPort := f.AllocPort()
|
||||
serverConf += fmt.Sprintf(`
|
||||
@ -175,8 +175,8 @@ var _ = Describe("[Feature: Basic]", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("HTTPS", func() {
|
||||
It("proxy to HTTPS server", func() {
|
||||
ginkgo.Describe("HTTPS", func() {
|
||||
ginkgo.It("proxy to HTTPS server", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
vhostHTTPSPort := f.AllocPort()
|
||||
serverConf += fmt.Sprintf(`
|
||||
@ -237,7 +237,7 @@ var _ = Describe("[Feature: Basic]", func() {
|
||||
framework.ExpectNoError(err)
|
||||
localServer := httpserver.New(
|
||||
httpserver.WithBindPort(localPort),
|
||||
httpserver.WithTlsConfig(tlsConfig),
|
||||
httpserver.WithTLSConfig(tlsConfig),
|
||||
httpserver.WithResponse([]byte("test")),
|
||||
)
|
||||
f.RunServer("", localServer)
|
||||
@ -275,11 +275,11 @@ var _ = Describe("[Feature: Basic]", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("STCP && SUDP", func() {
|
||||
ginkgo.Describe("STCP && SUDP", func() {
|
||||
types := []string{"stcp", "sudp"}
|
||||
for _, t := range types {
|
||||
proxyType := t
|
||||
It(fmt.Sprintf("Expose echo server with %s", strings.ToUpper(proxyType)), func() {
|
||||
ginkgo.It(fmt.Sprintf("Expose echo server with %s", strings.ToUpper(proxyType)), func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
clientServerConf := consts.DefaultClientConfig
|
||||
clientVisitorConf := consts.DefaultClientConfig
|
||||
@ -381,8 +381,8 @@ var _ = Describe("[Feature: Basic]", func() {
|
||||
}
|
||||
})
|
||||
|
||||
Describe("TCPMUX", func() {
|
||||
It("Type tcpmux", func() {
|
||||
ginkgo.Describe("TCPMUX", func() {
|
||||
ginkgo.It("Type tcpmux", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
clientConf := consts.DefaultClientConfig
|
||||
|
||||
|
@ -6,18 +6,18 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||
clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
var _ = Describe("[Feature: ClientManage]", func() {
|
||||
var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
||||
f := framework.NewDefaultFramework()
|
||||
|
||||
It("Update && Reload API", func() {
|
||||
ginkgo.It("Update && Reload API", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
|
||||
adminPort := f.AllocPort()
|
||||
@ -62,7 +62,9 @@ var _ = Describe("[Feature: ClientManage]", func() {
|
||||
// change p2 port and remove p3 proxy
|
||||
newClientConf := strings.ReplaceAll(conf, strconv.Itoa(p2Port), strconv.Itoa(newP2Port))
|
||||
p3Index := strings.Index(newClientConf, "[p3]")
|
||||
newClientConf = newClientConf[:p3Index]
|
||||
if p3Index >= 0 {
|
||||
newClientConf = newClientConf[:p3Index]
|
||||
}
|
||||
|
||||
err = client.UpdateConfig(newClientConf)
|
||||
framework.ExpectNoError(err)
|
||||
@ -77,7 +79,7 @@ var _ = Describe("[Feature: ClientManage]", func() {
|
||||
framework.NewRequestExpect(f).Port(p3Port).Explain("p3 port").ExpectError(true).Ensure()
|
||||
})
|
||||
|
||||
It("healthz", func() {
|
||||
ginkgo.It("healthz", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
|
||||
dashboardPort := f.AllocPort()
|
||||
@ -99,5 +101,4 @@ var _ = Describe("[Feature: ClientManage]", func() {
|
||||
}).Port(dashboardPort).
|
||||
Ensure(framework.ExpectResponseCode(401))
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -4,12 +4,12 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/cert"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/port"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
type generalTestConfigures struct {
|
||||
@ -54,15 +54,15 @@ func runClientServerTest(f *framework.Framework, configures *generalTestConfigur
|
||||
|
||||
// defineClientServerTest test a normal tcp and udp proxy with specified TestConfigures.
|
||||
func defineClientServerTest(desc string, f *framework.Framework, configures *generalTestConfigures) {
|
||||
It(desc, func() {
|
||||
ginkgo.It(desc, func() {
|
||||
runClientServerTest(f, configures)
|
||||
})
|
||||
}
|
||||
|
||||
var _ = Describe("[Feature: Client-Server]", func() {
|
||||
var _ = ginkgo.Describe("[Feature: Client-Server]", func() {
|
||||
f := framework.NewDefaultFramework()
|
||||
|
||||
Describe("Protocol", func() {
|
||||
ginkgo.Describe("Protocol", func() {
|
||||
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
||||
for _, protocol := range supportProtocols {
|
||||
configures := &generalTestConfigures{
|
||||
@ -76,7 +76,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
}
|
||||
})
|
||||
|
||||
Describe("Authentication", func() {
|
||||
ginkgo.Describe("Authentication", func() {
|
||||
defineClientServerTest("Token Correct", f, &generalTestConfigures{
|
||||
server: "token = 123456",
|
||||
client: "token = 123456",
|
||||
@ -89,7 +89,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("TLS", func() {
|
||||
ginkgo.Describe("TLS", func() {
|
||||
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
||||
for _, protocol := range supportProtocols {
|
||||
tmp := protocol
|
||||
@ -114,7 +114,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("TLS with custom certificate", func() {
|
||||
ginkgo.Describe("TLS with custom certificate", func() {
|
||||
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
||||
|
||||
var (
|
||||
@ -122,7 +122,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
serverCrtPath, serverKeyPath string
|
||||
clientCrtPath, clientKeyPath string
|
||||
)
|
||||
JustBeforeEach(func() {
|
||||
ginkgo.JustBeforeEach(func() {
|
||||
generator := &cert.SelfSignedCertGenerator{}
|
||||
artifacts, err := generator.Generate("0.0.0.0")
|
||||
framework.ExpectNoError(err)
|
||||
@ -131,7 +131,8 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
serverCrtPath = f.WriteTempFile("server.crt", string(artifacts.Cert))
|
||||
serverKeyPath = f.WriteTempFile("server.key", string(artifacts.Key))
|
||||
generator.SetCA(artifacts.CACert, artifacts.CAKey)
|
||||
generator.Generate("0.0.0.0")
|
||||
_, err = generator.Generate("0.0.0.0")
|
||||
framework.ExpectNoError(err)
|
||||
clientCrtPath = f.WriteTempFile("client.crt", string(artifacts.Cert))
|
||||
clientKeyPath = f.WriteTempFile("client.key", string(artifacts.Key))
|
||||
})
|
||||
@ -139,7 +140,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
for _, protocol := range supportProtocols {
|
||||
tmp := protocol
|
||||
|
||||
It("one-way authentication: "+tmp, func() {
|
||||
ginkgo.It("one-way authentication: "+tmp, func() {
|
||||
runClientServerTest(f, &generalTestConfigures{
|
||||
server: fmt.Sprintf(`
|
||||
protocol = %s
|
||||
@ -155,7 +156,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
})
|
||||
})
|
||||
|
||||
It("mutual authentication: "+tmp, func() {
|
||||
ginkgo.It("mutual authentication: "+tmp, func() {
|
||||
runClientServerTest(f, &generalTestConfigures{
|
||||
server: fmt.Sprintf(`
|
||||
protocol = %s
|
||||
@ -176,13 +177,13 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
}
|
||||
})
|
||||
|
||||
Describe("TLS with custom certificate and specified server name", func() {
|
||||
ginkgo.Describe("TLS with custom certificate and specified server name", func() {
|
||||
var (
|
||||
caCrtPath string
|
||||
serverCrtPath, serverKeyPath string
|
||||
clientCrtPath, clientKeyPath string
|
||||
)
|
||||
JustBeforeEach(func() {
|
||||
ginkgo.JustBeforeEach(func() {
|
||||
generator := &cert.SelfSignedCertGenerator{}
|
||||
artifacts, err := generator.Generate("example.com")
|
||||
framework.ExpectNoError(err)
|
||||
@ -191,12 +192,13 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
serverCrtPath = f.WriteTempFile("server.crt", string(artifacts.Cert))
|
||||
serverKeyPath = f.WriteTempFile("server.key", string(artifacts.Key))
|
||||
generator.SetCA(artifacts.CACert, artifacts.CAKey)
|
||||
generator.Generate("example.com")
|
||||
_, err = generator.Generate("example.com")
|
||||
framework.ExpectNoError(err)
|
||||
clientCrtPath = f.WriteTempFile("client.crt", string(artifacts.Cert))
|
||||
clientKeyPath = f.WriteTempFile("client.key", string(artifacts.Key))
|
||||
})
|
||||
|
||||
It("mutual authentication", func() {
|
||||
ginkgo.It("mutual authentication", func() {
|
||||
runClientServerTest(f, &generalTestConfigures{
|
||||
server: fmt.Sprintf(`
|
||||
tls_cert_file = %s
|
||||
@ -213,7 +215,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
})
|
||||
})
|
||||
|
||||
It("mutual authentication with incorrect server name", func() {
|
||||
ginkgo.It("mutual authentication with incorrect server name", func() {
|
||||
runClientServerTest(f, &generalTestConfigures{
|
||||
server: fmt.Sprintf(`
|
||||
tls_cert_file = %s
|
||||
@ -232,7 +234,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("TLS with disable_custom_tls_first_byte", func() {
|
||||
ginkgo.Describe("TLS with disable_custom_tls_first_byte", func() {
|
||||
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
||||
for _, protocol := range supportProtocols {
|
||||
tmp := protocol
|
||||
@ -250,7 +252,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
||||
}
|
||||
})
|
||||
|
||||
Describe("IPv6 bind address", func() {
|
||||
ginkgo.Describe("IPv6 bind address", func() {
|
||||
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
||||
for _, protocol := range supportProtocols {
|
||||
tmp := protocol
|
||||
|
@ -5,21 +5,21 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
const (
|
||||
ConfigValidStr = "syntax is ok"
|
||||
)
|
||||
|
||||
var _ = Describe("[Feature: Cmd]", func() {
|
||||
var _ = ginkgo.Describe("[Feature: Cmd]", func() {
|
||||
f := framework.NewDefaultFramework()
|
||||
|
||||
Describe("Verify", func() {
|
||||
It("frps valid", func() {
|
||||
ginkgo.Describe("Verify", func() {
|
||||
ginkgo.It("frps valid", func() {
|
||||
path := f.GenerateConfigFile(`
|
||||
[common]
|
||||
bind_addr = 0.0.0.0
|
||||
@ -29,7 +29,7 @@ var _ = Describe("[Feature: Cmd]", func() {
|
||||
framework.ExpectNoError(err)
|
||||
framework.ExpectTrue(strings.Contains(output, ConfigValidStr), "output: %s", output)
|
||||
})
|
||||
It("frps invalid", func() {
|
||||
ginkgo.It("frps invalid", func() {
|
||||
path := f.GenerateConfigFile(`
|
||||
[common]
|
||||
bind_addr = 0.0.0.0
|
||||
@ -39,7 +39,7 @@ var _ = Describe("[Feature: Cmd]", func() {
|
||||
framework.ExpectNoError(err)
|
||||
framework.ExpectTrue(!strings.Contains(output, ConfigValidStr), "output: %s", output)
|
||||
})
|
||||
It("frpc valid", func() {
|
||||
ginkgo.It("frpc valid", func() {
|
||||
path := f.GenerateConfigFile(`
|
||||
[common]
|
||||
server_addr = 0.0.0.0
|
||||
@ -49,7 +49,7 @@ var _ = Describe("[Feature: Cmd]", func() {
|
||||
framework.ExpectNoError(err)
|
||||
framework.ExpectTrue(strings.Contains(output, ConfigValidStr), "output: %s", output)
|
||||
})
|
||||
It("frpc invalid", func() {
|
||||
ginkgo.It("frpc invalid", func() {
|
||||
path := f.GenerateConfigFile(`
|
||||
[common]
|
||||
server_addr = 0.0.0.0
|
||||
@ -62,8 +62,8 @@ var _ = Describe("[Feature: Cmd]", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Single proxy", func() {
|
||||
It("TCP", func() {
|
||||
ginkgo.Describe("Single proxy", func() {
|
||||
ginkgo.It("TCP", func() {
|
||||
serverPort := f.AllocPort()
|
||||
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort))
|
||||
framework.ExpectNoError(err)
|
||||
@ -77,7 +77,7 @@ var _ = Describe("[Feature: Cmd]", func() {
|
||||
framework.NewRequestExpect(f).Port(remotePort).Ensure()
|
||||
})
|
||||
|
||||
It("UDP", func() {
|
||||
ginkgo.It("UDP", func() {
|
||||
serverPort := f.AllocPort()
|
||||
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort))
|
||||
framework.ExpectNoError(err)
|
||||
@ -92,7 +92,7 @@ var _ = Describe("[Feature: Cmd]", func() {
|
||||
Port(remotePort).Ensure()
|
||||
})
|
||||
|
||||
It("HTTP", func() {
|
||||
ginkgo.It("HTTP", func() {
|
||||
serverPort := f.AllocPort()
|
||||
vhostHTTPPort := f.AllocPort()
|
||||
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort), "--vhost_http_port", strconv.Itoa(vhostHTTPPort))
|
||||
|
@ -3,18 +3,18 @@ package basic
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/port"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
var _ = Describe("[Feature: Config]", func() {
|
||||
var _ = ginkgo.Describe("[Feature: Config]", func() {
|
||||
f := framework.NewDefaultFramework()
|
||||
|
||||
Describe("Template", func() {
|
||||
It("render by env", func() {
|
||||
ginkgo.Describe("Template", func() {
|
||||
ginkgo.It("render by env", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
clientConf := consts.DefaultClientConfig
|
||||
|
||||
@ -39,8 +39,8 @@ var _ = Describe("[Feature: Config]", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Includes", func() {
|
||||
It("split tcp proxies into different files", func() {
|
||||
ginkgo.Describe("Includes", func() {
|
||||
ginkgo.It("split tcp proxies into different files", func() {
|
||||
serverPort := f.AllocPort()
|
||||
serverConfigPath := f.GenerateConfigFile(fmt.Sprintf(`
|
||||
[common]
|
||||
|
@ -6,16 +6,16 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
"github.com/fatedier/frp/test/e2e/mock/server/httpserver"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
var _ = Describe("[Feature: HTTP]", func() {
|
||||
var _ = ginkgo.Describe("[Feature: HTTP]", func() {
|
||||
f := framework.NewDefaultFramework()
|
||||
|
||||
getDefaultServerConf := func(vhostHTTPPort int) string {
|
||||
@ -31,7 +31,7 @@ var _ = Describe("[Feature: HTTP]", func() {
|
||||
)
|
||||
}
|
||||
|
||||
It("HTTP route by locations", func() {
|
||||
ginkgo.It("HTTP route by locations", func() {
|
||||
vhostHTTPPort := f.AllocPort()
|
||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||
|
||||
@ -78,7 +78,7 @@ var _ = Describe("[Feature: HTTP]", func() {
|
||||
}
|
||||
})
|
||||
|
||||
It("HTTP route by HTTP user", func() {
|
||||
ginkgo.It("HTTP route by HTTP user", func() {
|
||||
vhostHTTPPort := f.AllocPort()
|
||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||
|
||||
@ -138,7 +138,7 @@ var _ = Describe("[Feature: HTTP]", func() {
|
||||
Ensure()
|
||||
})
|
||||
|
||||
It("HTTP Basic Auth", func() {
|
||||
ginkgo.It("HTTP Basic Auth", func() {
|
||||
vhostHTTPPort := f.AllocPort()
|
||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||
|
||||
@ -176,7 +176,7 @@ var _ = Describe("[Feature: HTTP]", func() {
|
||||
Ensure()
|
||||
})
|
||||
|
||||
It("Wildcard domain", func() {
|
||||
ginkgo.It("Wildcard domain", func() {
|
||||
vhostHTTPPort := f.AllocPort()
|
||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||
|
||||
@ -212,7 +212,7 @@ var _ = Describe("[Feature: HTTP]", func() {
|
||||
Ensure()
|
||||
})
|
||||
|
||||
It("Subdomain", func() {
|
||||
ginkgo.It("Subdomain", func() {
|
||||
vhostHTTPPort := f.AllocPort()
|
||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||
serverConf += `
|
||||
@ -257,7 +257,7 @@ var _ = Describe("[Feature: HTTP]", func() {
|
||||
Ensure()
|
||||
})
|
||||
|
||||
It("Modify headers", func() {
|
||||
ginkgo.It("Modify headers", func() {
|
||||
vhostHTTPPort := f.AllocPort()
|
||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||
|
||||
@ -265,7 +265,7 @@ var _ = Describe("[Feature: HTTP]", func() {
|
||||
localServer := httpserver.New(
|
||||
httpserver.WithBindPort(localPort),
|
||||
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
w.Write([]byte(req.Header.Get("X-From-Where")))
|
||||
_, _ = w.Write([]byte(req.Header.Get("X-From-Where")))
|
||||
})),
|
||||
)
|
||||
f.RunServer("", localServer)
|
||||
@ -290,7 +290,7 @@ var _ = Describe("[Feature: HTTP]", func() {
|
||||
Ensure()
|
||||
})
|
||||
|
||||
It("Host Header Rewrite", func() {
|
||||
ginkgo.It("Host Header Rewrite", func() {
|
||||
vhostHTTPPort := f.AllocPort()
|
||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||
|
||||
@ -298,7 +298,7 @@ var _ = Describe("[Feature: HTTP]", func() {
|
||||
localServer := httpserver.New(
|
||||
httpserver.WithBindPort(localPort),
|
||||
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
w.Write([]byte(req.Host))
|
||||
_, _ = w.Write([]byte(req.Host))
|
||||
})),
|
||||
)
|
||||
f.RunServer("", localServer)
|
||||
@ -322,7 +322,7 @@ var _ = Describe("[Feature: HTTP]", func() {
|
||||
Ensure()
|
||||
})
|
||||
|
||||
It("Websocket protocol", func() {
|
||||
ginkgo.It("Websocket protocol", func() {
|
||||
vhostHTTPPort := f.AllocPort()
|
||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||
|
||||
|
@ -5,19 +5,19 @@ import (
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/port"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||
clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
var _ = Describe("[Feature: Server Manager]", func() {
|
||||
var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
||||
f := framework.NewDefaultFramework()
|
||||
|
||||
It("Ports Whitelist", func() {
|
||||
ginkgo.It("Ports Whitelist", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
clientConf := consts.DefaultClientConfig
|
||||
|
||||
@ -80,7 +80,7 @@ var _ = Describe("[Feature: Server Manager]", func() {
|
||||
}).ExpectError(true).Ensure()
|
||||
})
|
||||
|
||||
It("Alloc Random Port", func() {
|
||||
ginkgo.It("Alloc Random Port", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
clientConf := consts.DefaultClientConfig
|
||||
|
||||
@ -124,7 +124,7 @@ var _ = Describe("[Feature: Server Manager]", func() {
|
||||
framework.NewRequestExpect(f).Protocol("udp").Port(port).Ensure()
|
||||
})
|
||||
|
||||
It("Port Reuse", func() {
|
||||
ginkgo.It("Port Reuse", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
// Use same port as PortServer
|
||||
serverConf += fmt.Sprintf(`
|
||||
@ -145,7 +145,7 @@ var _ = Describe("[Feature: Server Manager]", func() {
|
||||
}).PortName(consts.PortServerName).Ensure()
|
||||
})
|
||||
|
||||
It("healthz", func() {
|
||||
ginkgo.It("healthz", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
dashboardPort := f.AllocPort()
|
||||
|
||||
|
@ -3,12 +3,12 @@ package e2e
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/gomega"
|
||||
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
)
|
||||
|
||||
var _ = ginkgo.SynchronizedBeforeSuite(func() []byte {
|
||||
|
@ -6,15 +6,14 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
_ "github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
// test source
|
||||
_ "github.com/fatedier/frp/test/e2e/basic"
|
||||
_ "github.com/fatedier/frp/test/e2e/features"
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
_ "github.com/fatedier/frp/test/e2e/plugin"
|
||||
|
||||
_ "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
// handleFlags sets up all flags and parses the command line.
|
||||
|
@ -3,17 +3,17 @@ package e2e
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
var _ = Describe("[Feature: Example]", func() {
|
||||
var _ = ginkgo.Describe("[Feature: Example]", func() {
|
||||
f := framework.NewDefaultFramework()
|
||||
|
||||
Describe("TCP", func() {
|
||||
It("Expose a TCP echo server", func() {
|
||||
ginkgo.Describe("TCP", func() {
|
||||
ginkgo.It("Expose a TCP echo server", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
clientConf := consts.DefaultClientConfig
|
||||
|
||||
|
@ -5,18 +5,18 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework"
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
var _ = Describe("[Feature: Bandwidth Limit]", func() {
|
||||
var _ = ginkgo.Describe("[Feature: Bandwidth Limit]", func() {
|
||||
f := framework.NewDefaultFramework()
|
||||
|
||||
It("Proxy Bandwidth Limit", func() {
|
||||
ginkgo.It("Proxy Bandwidth Limit", func() {
|
||||
serverConf := consts.DefaultServerConfig
|
||||
clientConf := consts.DefaultClientConfig
|
||||
|
||||
@ -40,7 +40,7 @@ var _ = Describe("[Feature: Bandwidth Limit]", func() {
|
||||
framework.NewRequestExpect(f).Port(remotePort).RequestModify(func(r *request.Request) {
|
||||
r.Body([]byte(content)).Timeout(30 * time.Second)
|
||||
}).ExpectResp([]byte(content)).Ensure()
|
||||
duration := time.Now().Sub(start)
|
||||
duration := time.Since(start)
|
||||
|
||||
framework.ExpectTrue(duration.Seconds() > 7, "100Kb with 10KB limit, want > 7 seconds, but got %d seconds", duration.Seconds())
|
||||
})
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user