mirror of
https://github.com/fatedier/frp.git
synced 2024-11-24 02:59:19 +08:00
stcp, xtcp, sudp: support allow_users and specified server user (#3472)
This commit is contained in:
parent
cceab7e1b1
commit
de85c9455a
1
.gitignore
vendored
1
.gitignore
vendored
@ -29,6 +29,7 @@ packages/
|
|||||||
release/
|
release/
|
||||||
test/bin/
|
test/bin/
|
||||||
vendor/
|
vendor/
|
||||||
|
lastversion/
|
||||||
dist/
|
dist/
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
15
Makefile
15
Makefile
@ -46,8 +46,23 @@ e2e:
|
|||||||
e2e-trace:
|
e2e-trace:
|
||||||
DEBUG=true LOG_LEVEL=trace ./hack/run-e2e.sh
|
DEBUG=true LOG_LEVEL=trace ./hack/run-e2e.sh
|
||||||
|
|
||||||
|
e2e-compatibility-last-frpc:
|
||||||
|
if [ ! -d "./lastversion" ]; then \
|
||||||
|
TARGET_DIRNAME=lastversion ./hack/download.sh; \
|
||||||
|
fi
|
||||||
|
FRPC_PATH="`pwd`/lastversion/frpc" ./hack/run-e2e.sh
|
||||||
|
rm -r ./lastversion
|
||||||
|
|
||||||
|
e2e-compatibility-last-frps:
|
||||||
|
if [ ! -d "./lastversion" ]; then \
|
||||||
|
TARGET_DIRNAME=lastversion ./hack/download.sh; \
|
||||||
|
fi
|
||||||
|
FRPS_PATH="`pwd`/lastversion/frps" ./hack/run-e2e.sh
|
||||||
|
rm -r ./lastversion
|
||||||
|
|
||||||
alltest: vet gotest e2e
|
alltest: vet gotest e2e
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f ./bin/frpc
|
rm -f ./bin/frpc
|
||||||
rm -f ./bin/frps
|
rm -f ./bin/frps
|
||||||
|
rm -rf ./lastversion
|
||||||
|
63
hack/download.sh
Executable file
63
hack/download.sh
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
OS="$(go env GOOS)"
|
||||||
|
ARCH="$(go env GOARCH)"
|
||||||
|
|
||||||
|
if [ "${TARGET_OS}" ]; then
|
||||||
|
OS="${TARGET_OS}"
|
||||||
|
fi
|
||||||
|
if [ "${TARGET_ARCH}" ]; then
|
||||||
|
ARCH="${TARGET_ARCH}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine the latest version by version number ignoring alpha, beta, and rc versions.
|
||||||
|
if [ "${FRP_VERSION}" = "" ] ; then
|
||||||
|
FRP_VERSION="$(curl -sL https://github.com/fatedier/frp/releases | \
|
||||||
|
grep -o 'releases/tag/v[0-9]*.[0-9]*.[0-9]*"' | sort -V | \
|
||||||
|
tail -1 | awk -F'/' '{ print $3}')"
|
||||||
|
FRP_VERSION="${FRP_VERSION%?}"
|
||||||
|
FRP_VERSION="${FRP_VERSION#?}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${FRP_VERSION}" = "" ] ; then
|
||||||
|
printf "Unable to get latest frp version. Set FRP_VERSION env var and re-run. For example: export FRP_VERSION=1.0.0"
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
SUFFIX=".tar.gz"
|
||||||
|
if [ "${OS}" = "windows" ] ; then
|
||||||
|
SUFFIX=".zip"
|
||||||
|
fi
|
||||||
|
NAME="frp_${FRP_VERSION}_${OS}_${ARCH}${SUFFIX}"
|
||||||
|
DIR_NAME="frp_${FRP_VERSION}_${OS}_${ARCH}"
|
||||||
|
URL="https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/${NAME}"
|
||||||
|
|
||||||
|
download_and_extract() {
|
||||||
|
printf "Downloading %s from %s ...\n" "$NAME" "${URL}"
|
||||||
|
if ! curl -o /dev/null -sIf "${URL}"; then
|
||||||
|
printf "\n%s is not found, please specify a valid FRP_VERSION\n" "${URL}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
curl -fsLO "${URL}"
|
||||||
|
filename=$NAME
|
||||||
|
|
||||||
|
if [ "${OS}" = "windows" ]; then
|
||||||
|
unzip "${filename}"
|
||||||
|
else
|
||||||
|
tar -xzf "${filename}"
|
||||||
|
fi
|
||||||
|
rm "${filename}"
|
||||||
|
|
||||||
|
if [ "${TARGET_DIRNAME}" ]; then
|
||||||
|
mv "${DIR_NAME}" "${TARGET_DIRNAME}"
|
||||||
|
DIR_NAME="${TARGET_DIRNAME}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
download_and_extract
|
||||||
|
|
||||||
|
printf ""
|
||||||
|
printf "\nfrp %s Download Complete!\n" "$FRP_VERSION"
|
||||||
|
printf "\n"
|
||||||
|
printf "frp has been successfully downloaded into the %s folder on your system.\n" "$DIR_NAME"
|
||||||
|
printf "\n"
|
@ -1,20 +1,30 @@
|
|||||||
#!/usr/bin/env bash
|
#!/bin/sh
|
||||||
|
|
||||||
ROOT=$(unset CDPATH && cd $(dirname "${BASH_SOURCE[0]}")/.. && pwd)
|
SCRIPT=$(readlink -f "$0")
|
||||||
|
ROOT=$(unset CDPATH && cd "$(dirname "$SCRIPT")/.." && pwd)
|
||||||
|
|
||||||
which ginkgo &> /dev/null
|
ginkgo_command=$(which ginkgo 2>/dev/null)
|
||||||
if [ $? -ne 0 ]; then
|
if [ -z "$ginkgo_command" ]; then
|
||||||
echo "ginkgo not found, try to install..."
|
echo "ginkgo not found, try to install..."
|
||||||
go install github.com/onsi/ginkgo/v2/ginkgo@v2.8.3
|
go install github.com/onsi/ginkgo/v2/ginkgo@v2.8.3
|
||||||
fi
|
fi
|
||||||
|
|
||||||
debug=false
|
debug=false
|
||||||
if [ x${DEBUG} == x"true" ]; then
|
if [ "x${DEBUG}" = "xtrue" ]; then
|
||||||
debug=true
|
debug=true
|
||||||
fi
|
fi
|
||||||
logLevel=debug
|
logLevel=debug
|
||||||
if [ x${LOG_LEVEL} != x"" ]; then
|
if [ "${LOG_LEVEL}" ]; then
|
||||||
logLevel=${LOG_LEVEL}
|
logLevel="${LOG_LEVEL}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ginkgo -nodes=8 --poll-progress-after=30s ${ROOT}/test/e2e -- -frpc-path=${ROOT}/bin/frpc -frps-path=${ROOT}/bin/frps -log-level=${logLevel} -debug=${debug}
|
frpcPath=${ROOT}/bin/frpc
|
||||||
|
if [ "${FRPC_PATH}" ]; then
|
||||||
|
frpcPath="${FRPC_PATH}"
|
||||||
|
fi
|
||||||
|
frpsPath=${ROOT}/bin/frps
|
||||||
|
if [ "${FRPS_PATH}" ]; then
|
||||||
|
frpsPath="${FRPS_PATH}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
ginkgo -nodes=8 --poll-progress-after=60s ${ROOT}/test/e2e -- -frpc-path=${frpcPath} -frps-path=${frpsPath} -log-level=${logLevel} -debug=${debug}
|
||||||
|
@ -352,7 +352,7 @@ func LoadAllProxyConfsFromIni(
|
|||||||
case "visitor":
|
case "visitor":
|
||||||
newConf, newErr := NewVisitorConfFromIni(prefix, name, section)
|
newConf, newErr := NewVisitorConfFromIni(prefix, name, section)
|
||||||
if newErr != nil {
|
if newErr != nil {
|
||||||
return nil, nil, newErr
|
return nil, nil, fmt.Errorf("failed to parse visitor %s, err: %v", name, newErr)
|
||||||
}
|
}
|
||||||
visitorConfs[prefix+name] = newConf
|
visitorConfs[prefix+name] = newConf
|
||||||
default:
|
default:
|
||||||
|
@ -178,6 +178,16 @@ func (cfg *RoleServerCommonConf) setDefaultValues() {
|
|||||||
cfg.Role = "server"
|
cfg.Role = "server"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cfg *RoleServerCommonConf) marshalToMsg(m *msg.NewProxy) {
|
||||||
|
m.Sk = cfg.Sk
|
||||||
|
m.AllowUsers = cfg.AllowUsers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg *RoleServerCommonConf) unmarshalFromMsg(m *msg.NewProxy) {
|
||||||
|
cfg.Sk = m.Sk
|
||||||
|
cfg.AllowUsers = m.AllowUsers
|
||||||
|
}
|
||||||
|
|
||||||
// HTTP
|
// HTTP
|
||||||
type HTTPProxyConf struct {
|
type HTTPProxyConf struct {
|
||||||
BaseProxyConf `ini:",extends"`
|
BaseProxyConf `ini:",extends"`
|
||||||
@ -260,7 +270,7 @@ func NewProxyConfFromIni(prefix, name string, section *ini.Section) (ProxyConf,
|
|||||||
|
|
||||||
conf := DefaultProxyConf(proxyType)
|
conf := DefaultProxyConf(proxyType)
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
return nil, fmt.Errorf("proxy %s has invalid type [%s]", name, proxyType)
|
return nil, fmt.Errorf("invalid type [%s]", proxyType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := conf.UnmarshalFromIni(prefix, name, section); err != nil {
|
if err := conf.UnmarshalFromIni(prefix, name, section); err != nil {
|
||||||
@ -274,17 +284,17 @@ func NewProxyConfFromIni(prefix, name string, section *ini.Section) (ProxyConf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Proxy loaded from msg
|
// Proxy loaded from msg
|
||||||
func NewProxyConfFromMsg(pMsg *msg.NewProxy, serverCfg ServerCommonConf) (ProxyConf, error) {
|
func NewProxyConfFromMsg(m *msg.NewProxy, serverCfg ServerCommonConf) (ProxyConf, error) {
|
||||||
if pMsg.ProxyType == "" {
|
if m.ProxyType == "" {
|
||||||
pMsg.ProxyType = consts.TCPProxy
|
m.ProxyType = consts.TCPProxy
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := DefaultProxyConf(pMsg.ProxyType)
|
conf := DefaultProxyConf(m.ProxyType)
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
return nil, fmt.Errorf("proxy [%s] type [%s] error", pMsg.ProxyName, pMsg.ProxyType)
|
return nil, fmt.Errorf("proxy [%s] type [%s] error", m.ProxyName, m.ProxyType)
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.UnmarshalFromMsg(pMsg)
|
conf.UnmarshalFromMsg(m)
|
||||||
|
|
||||||
err := conf.ValidateForServer(serverCfg)
|
err := conf.ValidateForServer(serverCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -341,35 +351,35 @@ func (cfg *BaseProxyConf) decorate(prefix string, name string, section *ini.Sect
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *BaseProxyConf) marshalToMsg(pMsg *msg.NewProxy) {
|
func (cfg *BaseProxyConf) marshalToMsg(m *msg.NewProxy) {
|
||||||
pMsg.ProxyName = cfg.ProxyName
|
m.ProxyName = cfg.ProxyName
|
||||||
pMsg.ProxyType = cfg.ProxyType
|
m.ProxyType = cfg.ProxyType
|
||||||
pMsg.UseEncryption = cfg.UseEncryption
|
m.UseEncryption = cfg.UseEncryption
|
||||||
pMsg.UseCompression = cfg.UseCompression
|
m.UseCompression = cfg.UseCompression
|
||||||
pMsg.BandwidthLimit = cfg.BandwidthLimit.String()
|
m.BandwidthLimit = cfg.BandwidthLimit.String()
|
||||||
// leave it empty for default value to reduce traffic
|
// leave it empty for default value to reduce traffic
|
||||||
if cfg.BandwidthLimitMode != "client" {
|
if cfg.BandwidthLimitMode != "client" {
|
||||||
pMsg.BandwidthLimitMode = cfg.BandwidthLimitMode
|
m.BandwidthLimitMode = cfg.BandwidthLimitMode
|
||||||
}
|
}
|
||||||
pMsg.Group = cfg.Group
|
m.Group = cfg.Group
|
||||||
pMsg.GroupKey = cfg.GroupKey
|
m.GroupKey = cfg.GroupKey
|
||||||
pMsg.Metas = cfg.Metas
|
m.Metas = cfg.Metas
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *BaseProxyConf) unmarshalFromMsg(pMsg *msg.NewProxy) {
|
func (cfg *BaseProxyConf) unmarshalFromMsg(m *msg.NewProxy) {
|
||||||
cfg.ProxyName = pMsg.ProxyName
|
cfg.ProxyName = m.ProxyName
|
||||||
cfg.ProxyType = pMsg.ProxyType
|
cfg.ProxyType = m.ProxyType
|
||||||
cfg.UseEncryption = pMsg.UseEncryption
|
cfg.UseEncryption = m.UseEncryption
|
||||||
cfg.UseCompression = pMsg.UseCompression
|
cfg.UseCompression = m.UseCompression
|
||||||
if pMsg.BandwidthLimit != "" {
|
if m.BandwidthLimit != "" {
|
||||||
cfg.BandwidthLimit, _ = NewBandwidthQuantity(pMsg.BandwidthLimit)
|
cfg.BandwidthLimit, _ = NewBandwidthQuantity(m.BandwidthLimit)
|
||||||
}
|
}
|
||||||
if pMsg.BandwidthLimitMode != "" {
|
if m.BandwidthLimitMode != "" {
|
||||||
cfg.BandwidthLimitMode = pMsg.BandwidthLimitMode
|
cfg.BandwidthLimitMode = m.BandwidthLimitMode
|
||||||
}
|
}
|
||||||
cfg.Group = pMsg.Group
|
cfg.Group = m.Group
|
||||||
cfg.GroupKey = pMsg.GroupKey
|
cfg.GroupKey = m.GroupKey
|
||||||
cfg.Metas = pMsg.Metas
|
cfg.Metas = m.Metas
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *BaseProxyConf) validateForClient() (err error) {
|
func (cfg *BaseProxyConf) validateForClient() (err error) {
|
||||||
@ -482,11 +492,11 @@ func preUnmarshalFromIni(cfg ProxyConf, prefix string, name string, section *ini
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TCP
|
// TCP
|
||||||
func (cfg *TCPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
|
func (cfg *TCPProxyConf) UnmarshalFromMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.unmarshalFromMsg(pMsg)
|
cfg.BaseProxyConf.unmarshalFromMsg(m)
|
||||||
|
|
||||||
// Add custom logic unmarshal if exists
|
// Add custom logic unmarshal if exists
|
||||||
cfg.RemotePort = pMsg.RemotePort
|
cfg.RemotePort = m.RemotePort
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *TCPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
func (cfg *TCPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
||||||
@ -500,11 +510,11 @@ func (cfg *TCPProxyConf) UnmarshalFromIni(prefix string, name string, section *i
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *TCPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
func (cfg *TCPProxyConf) MarshalToMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.marshalToMsg(pMsg)
|
cfg.BaseProxyConf.marshalToMsg(m)
|
||||||
|
|
||||||
// Add custom logic marshal if exists
|
// Add custom logic marshal if exists
|
||||||
pMsg.RemotePort = cfg.RemotePort
|
m.RemotePort = cfg.RemotePort
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *TCPProxyConf) ValidateForClient() (err error) {
|
func (cfg *TCPProxyConf) ValidateForClient() (err error) {
|
||||||
@ -536,28 +546,28 @@ func (cfg *TCPMuxProxyConf) UnmarshalFromIni(prefix string, name string, section
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *TCPMuxProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
|
func (cfg *TCPMuxProxyConf) UnmarshalFromMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.unmarshalFromMsg(pMsg)
|
cfg.BaseProxyConf.unmarshalFromMsg(m)
|
||||||
|
|
||||||
// Add custom logic unmarshal if exists
|
// Add custom logic unmarshal if exists
|
||||||
cfg.CustomDomains = pMsg.CustomDomains
|
cfg.CustomDomains = m.CustomDomains
|
||||||
cfg.SubDomain = pMsg.SubDomain
|
cfg.SubDomain = m.SubDomain
|
||||||
cfg.Multiplexer = pMsg.Multiplexer
|
cfg.Multiplexer = m.Multiplexer
|
||||||
cfg.HTTPUser = pMsg.HTTPUser
|
cfg.HTTPUser = m.HTTPUser
|
||||||
cfg.HTTPPwd = pMsg.HTTPPwd
|
cfg.HTTPPwd = m.HTTPPwd
|
||||||
cfg.RouteByHTTPUser = pMsg.RouteByHTTPUser
|
cfg.RouteByHTTPUser = m.RouteByHTTPUser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *TCPMuxProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
func (cfg *TCPMuxProxyConf) MarshalToMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.marshalToMsg(pMsg)
|
cfg.BaseProxyConf.marshalToMsg(m)
|
||||||
|
|
||||||
// Add custom logic marshal if exists
|
// Add custom logic marshal if exists
|
||||||
pMsg.CustomDomains = cfg.CustomDomains
|
m.CustomDomains = cfg.CustomDomains
|
||||||
pMsg.SubDomain = cfg.SubDomain
|
m.SubDomain = cfg.SubDomain
|
||||||
pMsg.Multiplexer = cfg.Multiplexer
|
m.Multiplexer = cfg.Multiplexer
|
||||||
pMsg.HTTPUser = cfg.HTTPUser
|
m.HTTPUser = cfg.HTTPUser
|
||||||
pMsg.HTTPPwd = cfg.HTTPPwd
|
m.HTTPPwd = cfg.HTTPPwd
|
||||||
pMsg.RouteByHTTPUser = cfg.RouteByHTTPUser
|
m.RouteByHTTPUser = cfg.RouteByHTTPUser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *TCPMuxProxyConf) ValidateForClient() (err error) {
|
func (cfg *TCPMuxProxyConf) ValidateForClient() (err error) {
|
||||||
@ -610,18 +620,18 @@ func (cfg *UDPProxyConf) UnmarshalFromIni(prefix string, name string, section *i
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *UDPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
|
func (cfg *UDPProxyConf) UnmarshalFromMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.unmarshalFromMsg(pMsg)
|
cfg.BaseProxyConf.unmarshalFromMsg(m)
|
||||||
|
|
||||||
// Add custom logic unmarshal if exists
|
// Add custom logic unmarshal if exists
|
||||||
cfg.RemotePort = pMsg.RemotePort
|
cfg.RemotePort = m.RemotePort
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *UDPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
func (cfg *UDPProxyConf) MarshalToMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.marshalToMsg(pMsg)
|
cfg.BaseProxyConf.marshalToMsg(m)
|
||||||
|
|
||||||
// Add custom logic marshal if exists
|
// Add custom logic marshal if exists
|
||||||
pMsg.RemotePort = cfg.RemotePort
|
m.RemotePort = cfg.RemotePort
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *UDPProxyConf) ValidateForClient() (err error) {
|
func (cfg *UDPProxyConf) ValidateForClient() (err error) {
|
||||||
@ -653,32 +663,32 @@ func (cfg *HTTPProxyConf) UnmarshalFromIni(prefix string, name string, section *
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *HTTPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
|
func (cfg *HTTPProxyConf) UnmarshalFromMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.unmarshalFromMsg(pMsg)
|
cfg.BaseProxyConf.unmarshalFromMsg(m)
|
||||||
|
|
||||||
// Add custom logic unmarshal if exists
|
// Add custom logic unmarshal if exists
|
||||||
cfg.CustomDomains = pMsg.CustomDomains
|
cfg.CustomDomains = m.CustomDomains
|
||||||
cfg.SubDomain = pMsg.SubDomain
|
cfg.SubDomain = m.SubDomain
|
||||||
cfg.Locations = pMsg.Locations
|
cfg.Locations = m.Locations
|
||||||
cfg.HostHeaderRewrite = pMsg.HostHeaderRewrite
|
cfg.HostHeaderRewrite = m.HostHeaderRewrite
|
||||||
cfg.HTTPUser = pMsg.HTTPUser
|
cfg.HTTPUser = m.HTTPUser
|
||||||
cfg.HTTPPwd = pMsg.HTTPPwd
|
cfg.HTTPPwd = m.HTTPPwd
|
||||||
cfg.Headers = pMsg.Headers
|
cfg.Headers = m.Headers
|
||||||
cfg.RouteByHTTPUser = pMsg.RouteByHTTPUser
|
cfg.RouteByHTTPUser = m.RouteByHTTPUser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *HTTPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
func (cfg *HTTPProxyConf) MarshalToMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.marshalToMsg(pMsg)
|
cfg.BaseProxyConf.marshalToMsg(m)
|
||||||
|
|
||||||
// Add custom logic marshal if exists
|
// Add custom logic marshal if exists
|
||||||
pMsg.CustomDomains = cfg.CustomDomains
|
m.CustomDomains = cfg.CustomDomains
|
||||||
pMsg.SubDomain = cfg.SubDomain
|
m.SubDomain = cfg.SubDomain
|
||||||
pMsg.Locations = cfg.Locations
|
m.Locations = cfg.Locations
|
||||||
pMsg.HostHeaderRewrite = cfg.HostHeaderRewrite
|
m.HostHeaderRewrite = cfg.HostHeaderRewrite
|
||||||
pMsg.HTTPUser = cfg.HTTPUser
|
m.HTTPUser = cfg.HTTPUser
|
||||||
pMsg.HTTPPwd = cfg.HTTPPwd
|
m.HTTPPwd = cfg.HTTPPwd
|
||||||
pMsg.Headers = cfg.Headers
|
m.Headers = cfg.Headers
|
||||||
pMsg.RouteByHTTPUser = cfg.RouteByHTTPUser
|
m.RouteByHTTPUser = cfg.RouteByHTTPUser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *HTTPProxyConf) ValidateForClient() (err error) {
|
func (cfg *HTTPProxyConf) ValidateForClient() (err error) {
|
||||||
@ -722,20 +732,20 @@ func (cfg *HTTPSProxyConf) UnmarshalFromIni(prefix string, name string, section
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *HTTPSProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
|
func (cfg *HTTPSProxyConf) UnmarshalFromMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.unmarshalFromMsg(pMsg)
|
cfg.BaseProxyConf.unmarshalFromMsg(m)
|
||||||
|
|
||||||
// Add custom logic unmarshal if exists
|
// Add custom logic unmarshal if exists
|
||||||
cfg.CustomDomains = pMsg.CustomDomains
|
cfg.CustomDomains = m.CustomDomains
|
||||||
cfg.SubDomain = pMsg.SubDomain
|
cfg.SubDomain = m.SubDomain
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *HTTPSProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
func (cfg *HTTPSProxyConf) MarshalToMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.marshalToMsg(pMsg)
|
cfg.BaseProxyConf.marshalToMsg(m)
|
||||||
|
|
||||||
// Add custom logic marshal if exists
|
// Add custom logic marshal if exists
|
||||||
pMsg.CustomDomains = cfg.CustomDomains
|
m.CustomDomains = cfg.CustomDomains
|
||||||
pMsg.SubDomain = cfg.SubDomain
|
m.SubDomain = cfg.SubDomain
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *HTTPSProxyConf) ValidateForClient() (err error) {
|
func (cfg *HTTPSProxyConf) ValidateForClient() (err error) {
|
||||||
@ -784,18 +794,18 @@ func (cfg *SUDPProxyConf) UnmarshalFromIni(prefix string, name string, section *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only for role server.
|
// Only for role server.
|
||||||
func (cfg *SUDPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
|
func (cfg *SUDPProxyConf) UnmarshalFromMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.unmarshalFromMsg(pMsg)
|
cfg.BaseProxyConf.unmarshalFromMsg(m)
|
||||||
|
|
||||||
// Add custom logic unmarshal if exists
|
// Add custom logic unmarshal if exists
|
||||||
cfg.Sk = pMsg.Sk
|
cfg.RoleServerCommonConf.unmarshalFromMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *SUDPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
func (cfg *SUDPProxyConf) MarshalToMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.marshalToMsg(pMsg)
|
cfg.BaseProxyConf.marshalToMsg(m)
|
||||||
|
|
||||||
// Add custom logic marshal if exists
|
// Add custom logic marshal if exists
|
||||||
pMsg.Sk = cfg.Sk
|
cfg.RoleServerCommonConf.marshalToMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *SUDPProxyConf) ValidateForClient() (err error) {
|
func (cfg *SUDPProxyConf) ValidateForClient() (err error) {
|
||||||
@ -838,18 +848,18 @@ func (cfg *STCPProxyConf) UnmarshalFromIni(prefix string, name string, section *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only for role server.
|
// Only for role server.
|
||||||
func (cfg *STCPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
|
func (cfg *STCPProxyConf) UnmarshalFromMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.unmarshalFromMsg(pMsg)
|
cfg.BaseProxyConf.unmarshalFromMsg(m)
|
||||||
|
|
||||||
// Add custom logic unmarshal if exists
|
// Add custom logic unmarshal if exists
|
||||||
cfg.Sk = pMsg.Sk
|
cfg.RoleServerCommonConf.unmarshalFromMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *STCPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
func (cfg *STCPProxyConf) MarshalToMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.marshalToMsg(pMsg)
|
cfg.BaseProxyConf.marshalToMsg(m)
|
||||||
|
|
||||||
// Add custom logic marshal if exists
|
// Add custom logic marshal if exists
|
||||||
pMsg.Sk = cfg.Sk
|
cfg.RoleServerCommonConf.marshalToMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *STCPProxyConf) ValidateForClient() (err error) {
|
func (cfg *STCPProxyConf) ValidateForClient() (err error) {
|
||||||
@ -892,18 +902,18 @@ func (cfg *XTCPProxyConf) UnmarshalFromIni(prefix string, name string, section *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only for role server.
|
// Only for role server.
|
||||||
func (cfg *XTCPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
|
func (cfg *XTCPProxyConf) UnmarshalFromMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.unmarshalFromMsg(pMsg)
|
cfg.BaseProxyConf.unmarshalFromMsg(m)
|
||||||
|
|
||||||
// Add custom logic unmarshal if exists
|
// Add custom logic unmarshal if exists
|
||||||
cfg.Sk = pMsg.Sk
|
cfg.RoleServerCommonConf.unmarshalFromMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *XTCPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
func (cfg *XTCPProxyConf) MarshalToMsg(m *msg.NewProxy) {
|
||||||
cfg.BaseProxyConf.marshalToMsg(pMsg)
|
cfg.BaseProxyConf.marshalToMsg(m)
|
||||||
|
|
||||||
// Add custom logic marshal if exists
|
// Add custom logic marshal if exists
|
||||||
pMsg.Sk = cfg.Sk
|
cfg.RoleServerCommonConf.marshalToMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *XTCPProxyConf) ValidateForClient() (err error) {
|
func (cfg *XTCPProxyConf) ValidateForClient() (err error) {
|
||||||
|
@ -94,16 +94,16 @@ func NewVisitorConfFromIni(prefix string, name string, section *ini.Section) (Vi
|
|||||||
visitorType := section.Key("type").String()
|
visitorType := section.Key("type").String()
|
||||||
|
|
||||||
if visitorType == "" {
|
if visitorType == "" {
|
||||||
return nil, fmt.Errorf("visitor [%s] type shouldn't be empty", name)
|
return nil, fmt.Errorf("type shouldn't be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := DefaultVisitorConf(visitorType)
|
conf := DefaultVisitorConf(visitorType)
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
return nil, fmt.Errorf("visitor [%s] type [%s] error", name, visitorType)
|
return nil, fmt.Errorf("type [%s] error", visitorType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := conf.UnmarshalFromIni(prefix, name, section); err != nil {
|
if err := conf.UnmarshalFromIni(prefix, name, section); err != nil {
|
||||||
return nil, fmt.Errorf("visitor [%s] type [%s] error", name, visitorType)
|
return nil, fmt.Errorf("type [%s] error", visitorType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := conf.Validate(); err != nil {
|
if err := conf.Validate(); err != nil {
|
||||||
|
@ -110,8 +110,9 @@ type NewProxy struct {
|
|||||||
Headers map[string]string `json:"headers,omitempty"`
|
Headers map[string]string `json:"headers,omitempty"`
|
||||||
RouteByHTTPUser string `json:"route_by_http_user,omitempty"`
|
RouteByHTTPUser string `json:"route_by_http_user,omitempty"`
|
||||||
|
|
||||||
// stcp
|
// stcp, sudp, xtcp
|
||||||
Sk string `json:"sk,omitempty"`
|
Sk string `json:"sk,omitempty"`
|
||||||
|
AllowUsers []string `json:"allow_users,omitempty"`
|
||||||
|
|
||||||
// tcpmux
|
// tcpmux
|
||||||
Multiplexer string `json:"multiplexer,omitempty"`
|
Multiplexer string `json:"multiplexer,omitempty"`
|
||||||
|
@ -43,9 +43,10 @@ func NewTransactionID() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ClientCfg struct {
|
type ClientCfg struct {
|
||||||
name string
|
name string
|
||||||
sk string
|
sk string
|
||||||
sidCh chan string
|
allowUsers []string
|
||||||
|
sidCh chan string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
@ -120,11 +121,12 @@ func (c *Controller) CleanWorker(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ListenClient(name string, sk string) chan string {
|
func (c *Controller) ListenClient(name string, sk string, allowUsers []string) chan string {
|
||||||
cfg := &ClientCfg{
|
cfg := &ClientCfg{
|
||||||
name: name,
|
name: name,
|
||||||
sk: sk,
|
sk: sk,
|
||||||
sidCh: make(chan string),
|
allowUsers: allowUsers,
|
||||||
|
sidCh: make(chan string),
|
||||||
}
|
}
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
@ -144,14 +146,18 @@ func (c *Controller) GenSid() string {
|
|||||||
return fmt.Sprintf("%d%s", t, id)
|
return fmt.Sprintf("%d%s", t, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) HandleVisitor(m *msg.NatHoleVisitor, transporter transport.MessageTransporter) {
|
func (c *Controller) HandleVisitor(m *msg.NatHoleVisitor, transporter transport.MessageTransporter, visitorUser string) {
|
||||||
if m.PreCheck {
|
if m.PreCheck {
|
||||||
_, ok := c.clientCfgs[m.ProxyName]
|
cfg, ok := c.clientCfgs[m.ProxyName]
|
||||||
if !ok {
|
if !ok {
|
||||||
_ = transporter.Send(c.GenNatHoleResponse(m.TransactionID, nil, fmt.Sprintf("xtcp server for [%s] doesn't exist", m.ProxyName)))
|
_ = transporter.Send(c.GenNatHoleResponse(m.TransactionID, nil, fmt.Sprintf("xtcp server for [%s] doesn't exist", m.ProxyName)))
|
||||||
} else {
|
return
|
||||||
_ = transporter.Send(c.GenNatHoleResponse(m.TransactionID, nil, ""))
|
|
||||||
}
|
}
|
||||||
|
if !lo.Contains(cfg.allowUsers, visitorUser) && !lo.Contains(cfg.allowUsers, "*") {
|
||||||
|
_ = transporter.Send(c.GenNatHoleResponse(m.TransactionID, nil, fmt.Sprintf("xtcp visitor user [%s] not allowed for [%s]", visitorUser, m.ProxyName)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ = transporter.Send(c.GenNatHoleResponse(m.TransactionID, nil, ""))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,7 +524,7 @@ func (ctl *Control) manager() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ctl *Control) HandleNatHoleVisitor(m *msg.NatHoleVisitor) {
|
func (ctl *Control) HandleNatHoleVisitor(m *msg.NatHoleVisitor) {
|
||||||
ctl.rc.NatHoleController.HandleVisitor(m, ctl.msgTransporter)
|
ctl.rc.NatHoleController.HandleVisitor(m, ctl.msgTransporter, ctl.loginMsg.User)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctl *Control) HandleNatHoleClient(m *msg.NatHoleClient) {
|
func (ctl *Control) HandleNatHoleClient(m *msg.NatHoleClient) {
|
||||||
@ -537,7 +537,7 @@ func (ctl *Control) HandleNatHoleReport(m *msg.NatHoleReport) {
|
|||||||
|
|
||||||
func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err error) {
|
func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err error) {
|
||||||
var pxyConf config.ProxyConf
|
var pxyConf config.ProxyConf
|
||||||
// Load configures from NewProxy message and check.
|
// Load configures from NewProxy message and validate.
|
||||||
pxyConf, err = config.NewProxyConfFromMsg(pxyMsg, ctl.serverCfg)
|
pxyConf, err = config.NewProxyConfFromMsg(pxyMsg, ctl.serverCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -550,8 +550,8 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
|
|||||||
RunID: ctl.runID,
|
RunID: ctl.runID,
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProxy will return a interface Proxy.
|
// NewProxy will return an interface Proxy.
|
||||||
// In fact it create different proxies by different proxy type, we just call run() here.
|
// In fact, it creates different proxies based on the proxy type. We just call run() here.
|
||||||
pxy, err := proxy.NewProxy(ctl.ctx, userInfo, ctl.rc, ctl.poolCount, ctl.GetWorkConn, pxyConf, ctl.serverCfg, ctl.loginMsg)
|
pxy, err := proxy.NewProxy(ctl.ctx, userInfo, ctl.rc, ctl.poolCount, ctl.GetWorkConn, pxyConf, ctl.serverCfg, ctl.loginMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return remoteAddr, err
|
return remoteAddr, err
|
||||||
|
@ -27,7 +27,12 @@ type STCPProxy struct {
|
|||||||
|
|
||||||
func (pxy *STCPProxy) Run() (remoteAddr string, err error) {
|
func (pxy *STCPProxy) Run() (remoteAddr string, err error) {
|
||||||
xl := pxy.xl
|
xl := pxy.xl
|
||||||
listener, errRet := pxy.rc.VisitorManager.Listen(pxy.GetName(), pxy.cfg.Sk)
|
allowUsers := pxy.cfg.AllowUsers
|
||||||
|
// if allowUsers is empty, only allow same user from proxy
|
||||||
|
if len(allowUsers) == 0 {
|
||||||
|
allowUsers = []string{pxy.GetUserInfo().User}
|
||||||
|
}
|
||||||
|
listener, errRet := pxy.rc.VisitorManager.Listen(pxy.GetName(), pxy.cfg.Sk, allowUsers)
|
||||||
if errRet != nil {
|
if errRet != nil {
|
||||||
err = errRet
|
err = errRet
|
||||||
return
|
return
|
||||||
|
@ -27,8 +27,12 @@ type SUDPProxy struct {
|
|||||||
|
|
||||||
func (pxy *SUDPProxy) Run() (remoteAddr string, err error) {
|
func (pxy *SUDPProxy) Run() (remoteAddr string, err error) {
|
||||||
xl := pxy.xl
|
xl := pxy.xl
|
||||||
|
allowUsers := pxy.cfg.AllowUsers
|
||||||
listener, errRet := pxy.rc.VisitorManager.Listen(pxy.GetName(), pxy.cfg.Sk)
|
// if allowUsers is empty, only allow same user from proxy
|
||||||
|
if len(allowUsers) == 0 {
|
||||||
|
allowUsers = []string{pxy.GetUserInfo().User}
|
||||||
|
}
|
||||||
|
listener, errRet := pxy.rc.VisitorManager.Listen(pxy.GetName(), pxy.cfg.Sk, allowUsers)
|
||||||
if errRet != nil {
|
if errRet != nil {
|
||||||
err = errRet
|
err = errRet
|
||||||
return
|
return
|
||||||
|
@ -35,11 +35,15 @@ func (pxy *XTCPProxy) Run() (remoteAddr string, err error) {
|
|||||||
xl := pxy.xl
|
xl := pxy.xl
|
||||||
|
|
||||||
if pxy.rc.NatHoleController == nil {
|
if pxy.rc.NatHoleController == nil {
|
||||||
xl.Error("udp port for xtcp is not specified.")
|
|
||||||
err = fmt.Errorf("xtcp is not supported in frps")
|
err = fmt.Errorf("xtcp is not supported in frps")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sidCh := pxy.rc.NatHoleController.ListenClient(pxy.GetName(), pxy.cfg.Sk)
|
allowUsers := pxy.cfg.AllowUsers
|
||||||
|
// if allowUsers is empty, only allow same user from proxy
|
||||||
|
if len(allowUsers) == 0 {
|
||||||
|
allowUsers = []string{pxy.GetUserInfo().User}
|
||||||
|
}
|
||||||
|
sidCh := pxy.rc.NatHoleController.ListenClient(pxy.GetName(), pxy.cfg.Sk, allowUsers)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -587,6 +587,15 @@ func (svr *Service) RegisterWorkConn(workConn net.Conn, newMsg *msg.NewWorkConn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (svr *Service) RegisterVisitorConn(visitorConn net.Conn, newMsg *msg.NewVisitorConn) error {
|
func (svr *Service) RegisterVisitorConn(visitorConn net.Conn, newMsg *msg.NewVisitorConn) error {
|
||||||
|
visitorUser := ""
|
||||||
|
// TODO: Compatible with old versions, can be without runID, user is empty. In later versions, it will be mandatory to include runID.
|
||||||
|
if newMsg.RunID != "" {
|
||||||
|
ctl, exist := svr.ctlManager.GetByID(newMsg.RunID)
|
||||||
|
if !exist {
|
||||||
|
return fmt.Errorf("no client control found for run id [%s]", newMsg.RunID)
|
||||||
|
}
|
||||||
|
visitorUser = ctl.loginMsg.User
|
||||||
|
}
|
||||||
return svr.rc.VisitorManager.NewConn(newMsg.ProxyName, visitorConn, newMsg.Timestamp, newMsg.SignKey,
|
return svr.rc.VisitorManager.NewConn(newMsg.ProxyName, visitorConn, newMsg.Timestamp, newMsg.SignKey,
|
||||||
newMsg.UseEncryption, newMsg.UseCompression)
|
newMsg.UseEncryption, newMsg.UseCompression, visitorUser)
|
||||||
}
|
}
|
||||||
|
@ -21,57 +21,69 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
libio "github.com/fatedier/golib/io"
|
libio "github.com/fatedier/golib/io"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
|
||||||
utilnet "github.com/fatedier/frp/pkg/util/net"
|
utilnet "github.com/fatedier/frp/pkg/util/net"
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type listenerBundle struct {
|
||||||
|
l *utilnet.InternalListener
|
||||||
|
sk string
|
||||||
|
allowUsers []string
|
||||||
|
}
|
||||||
|
|
||||||
// Manager for visitor listeners.
|
// Manager for visitor listeners.
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
visitorListeners map[string]*utilnet.InternalListener
|
listeners map[string]*listenerBundle
|
||||||
skMap map[string]string
|
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager() *Manager {
|
func NewManager() *Manager {
|
||||||
return &Manager{
|
return &Manager{
|
||||||
visitorListeners: make(map[string]*utilnet.InternalListener),
|
listeners: make(map[string]*listenerBundle),
|
||||||
skMap: make(map[string]string),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *Manager) Listen(name string, sk string) (l *utilnet.InternalListener, err error) {
|
func (vm *Manager) Listen(name string, sk string, allowUsers []string) (l *utilnet.InternalListener, err error) {
|
||||||
vm.mu.Lock()
|
vm.mu.Lock()
|
||||||
defer vm.mu.Unlock()
|
defer vm.mu.Unlock()
|
||||||
|
|
||||||
if _, ok := vm.visitorListeners[name]; ok {
|
if _, ok := vm.listeners[name]; ok {
|
||||||
err = fmt.Errorf("custom listener for [%s] is repeated", name)
|
err = fmt.Errorf("custom listener for [%s] is repeated", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l = utilnet.NewInternalListener()
|
l = utilnet.NewInternalListener()
|
||||||
vm.visitorListeners[name] = l
|
vm.listeners[name] = &listenerBundle{
|
||||||
vm.skMap[name] = sk
|
l: l,
|
||||||
|
sk: sk,
|
||||||
|
allowUsers: allowUsers,
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *Manager) NewConn(name string, conn net.Conn, timestamp int64, signKey string,
|
func (vm *Manager) NewConn(name string, conn net.Conn, timestamp int64, signKey string,
|
||||||
useEncryption bool, useCompression bool,
|
useEncryption bool, useCompression bool, visitorUser string,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
vm.mu.RLock()
|
vm.mu.RLock()
|
||||||
defer vm.mu.RUnlock()
|
defer vm.mu.RUnlock()
|
||||||
|
|
||||||
if l, ok := vm.visitorListeners[name]; ok {
|
if l, ok := vm.listeners[name]; ok {
|
||||||
var sk string
|
if util.GetAuthKey(l.sk, timestamp) != signKey {
|
||||||
if sk = vm.skMap[name]; util.GetAuthKey(sk, timestamp) != signKey {
|
|
||||||
err = fmt.Errorf("visitor connection of [%s] auth failed", name)
|
err = fmt.Errorf("visitor connection of [%s] auth failed", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !lo.Contains(l.allowUsers, visitorUser) && !lo.Contains(l.allowUsers, "*") {
|
||||||
|
err = fmt.Errorf("visitor connection of [%s] user [%s] not allowed", name, visitorUser)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var rwc io.ReadWriteCloser = conn
|
var rwc io.ReadWriteCloser = conn
|
||||||
if useEncryption {
|
if useEncryption {
|
||||||
if rwc, err = libio.WithEncryption(rwc, []byte(sk)); err != nil {
|
if rwc, err = libio.WithEncryption(rwc, []byte(l.sk)); err != nil {
|
||||||
err = fmt.Errorf("create encryption connection failed: %v", err)
|
err = fmt.Errorf("create encryption connection failed: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -79,7 +91,7 @@ func (vm *Manager) NewConn(name string, conn net.Conn, timestamp int64, signKey
|
|||||||
if useCompression {
|
if useCompression {
|
||||||
rwc = libio.WithCompression(rwc)
|
rwc = libio.WithCompression(rwc)
|
||||||
}
|
}
|
||||||
err = l.PutConn(utilnet.WrapReadWriteCloserToConn(rwc, conn))
|
err = l.l.PutConn(utilnet.WrapReadWriteCloserToConn(rwc, conn))
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("custom listener for [%s] doesn't exist", name)
|
err = fmt.Errorf("custom listener for [%s] doesn't exist", name)
|
||||||
return
|
return
|
||||||
@ -91,6 +103,5 @@ func (vm *Manager) CloseListener(name string) {
|
|||||||
vm.mu.Lock()
|
vm.mu.Lock()
|
||||||
defer vm.mu.Unlock()
|
defer vm.mu.Unlock()
|
||||||
|
|
||||||
delete(vm.visitorListeners, name)
|
delete(vm.listeners, name)
|
||||||
delete(vm.skMap, name)
|
|
||||||
}
|
}
|
||||||
|
@ -282,8 +282,9 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
|
|||||||
proxyType := t
|
proxyType := t
|
||||||
ginkgo.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
|
serverConf := consts.DefaultServerConfig
|
||||||
clientServerConf := consts.DefaultClientConfig
|
clientServerConf := consts.DefaultClientConfig + "\nuser = user1"
|
||||||
clientVisitorConf := consts.DefaultClientConfig
|
clientVisitorConf := consts.DefaultClientConfig + "\nuser = user1"
|
||||||
|
clientUser2VisitorConf := consts.DefaultClientConfig + "\nuser = user2"
|
||||||
|
|
||||||
localPortName := ""
|
localPortName := ""
|
||||||
protocol := "tcp"
|
protocol := "tcp"
|
||||||
@ -312,7 +313,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
|
|||||||
`+extra, proxyName, proxyType, correctSK, localPortName)
|
`+extra, proxyName, proxyType, correctSK, localPortName)
|
||||||
}
|
}
|
||||||
getProxyVisitorConf := func(proxyName string, portName, visitorSK, extra string) string {
|
getProxyVisitorConf := func(proxyName string, portName, visitorSK, extra string) string {
|
||||||
return fmt.Sprintf(`
|
out := fmt.Sprintf(`
|
||||||
[%s]
|
[%s]
|
||||||
type = %s
|
type = %s
|
||||||
role = visitor
|
role = visitor
|
||||||
@ -320,14 +321,22 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
|
|||||||
sk = %s
|
sk = %s
|
||||||
bind_port = {{ .%s }}
|
bind_port = {{ .%s }}
|
||||||
`+extra, proxyName, proxyType, proxyName, visitorSK, portName)
|
`+extra, proxyName, proxyType, proxyName, visitorSK, portName)
|
||||||
|
if proxyType == "xtcp" {
|
||||||
|
// Set keep_tunnel_open to reduce testing time.
|
||||||
|
out += "\nkeep_tunnel_open = true"
|
||||||
|
}
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
proxyName string
|
proxyName string
|
||||||
bindPortName string
|
bindPortName string
|
||||||
visitorSK string
|
visitorSK string
|
||||||
extraConfig string
|
commonExtraConfig string
|
||||||
expectError bool
|
proxyExtraConfig string
|
||||||
|
visitorExtraConfig string
|
||||||
|
expectError bool
|
||||||
|
user2 bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
proxyName: "normal",
|
proxyName: "normal",
|
||||||
@ -335,22 +344,22 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
|
|||||||
visitorSK: correctSK,
|
visitorSK: correctSK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
proxyName: "with-encryption",
|
proxyName: "with-encryption",
|
||||||
bindPortName: port.GenName("WithEncryption"),
|
bindPortName: port.GenName("WithEncryption"),
|
||||||
visitorSK: correctSK,
|
visitorSK: correctSK,
|
||||||
extraConfig: "use_encryption = true",
|
commonExtraConfig: "use_encryption = true",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
proxyName: "with-compression",
|
proxyName: "with-compression",
|
||||||
bindPortName: port.GenName("WithCompression"),
|
bindPortName: port.GenName("WithCompression"),
|
||||||
visitorSK: correctSK,
|
visitorSK: correctSK,
|
||||||
extraConfig: "use_compression = true",
|
commonExtraConfig: "use_compression = true",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
proxyName: "with-encryption-and-compression",
|
proxyName: "with-encryption-and-compression",
|
||||||
bindPortName: port.GenName("WithEncryptionAndCompression"),
|
bindPortName: port.GenName("WithEncryptionAndCompression"),
|
||||||
visitorSK: correctSK,
|
visitorSK: correctSK,
|
||||||
extraConfig: `
|
commonExtraConfig: `
|
||||||
use_encryption = true
|
use_encryption = true
|
||||||
use_compression = true
|
use_compression = true
|
||||||
`,
|
`,
|
||||||
@ -361,22 +370,53 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
|
|||||||
visitorSK: wrongSK,
|
visitorSK: wrongSK,
|
||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
proxyName: "allowed-user",
|
||||||
|
bindPortName: port.GenName("AllowedUser"),
|
||||||
|
visitorSK: correctSK,
|
||||||
|
proxyExtraConfig: "allow_users = another, user2",
|
||||||
|
visitorExtraConfig: "server_user = user1",
|
||||||
|
user2: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
proxyName: "not-allowed-user",
|
||||||
|
bindPortName: port.GenName("NotAllowedUser"),
|
||||||
|
visitorSK: correctSK,
|
||||||
|
proxyExtraConfig: "allow_users = invalid",
|
||||||
|
visitorExtraConfig: "server_user = user1",
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
proxyName: "allow-all",
|
||||||
|
bindPortName: port.GenName("AllowAll"),
|
||||||
|
visitorSK: correctSK,
|
||||||
|
proxyExtraConfig: "allow_users = *",
|
||||||
|
visitorExtraConfig: "server_user = user1",
|
||||||
|
user2: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// build all client config
|
// build all client config
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
clientServerConf += getProxyServerConf(test.proxyName, test.extraConfig) + "\n"
|
clientServerConf += getProxyServerConf(test.proxyName, test.commonExtraConfig+"\n"+test.proxyExtraConfig) + "\n"
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
clientVisitorConf += getProxyVisitorConf(test.proxyName, test.bindPortName, test.visitorSK, test.extraConfig) + "\n"
|
config := getProxyVisitorConf(
|
||||||
|
test.proxyName, test.bindPortName, test.visitorSK, test.commonExtraConfig+"\n"+test.visitorExtraConfig,
|
||||||
|
) + "\n"
|
||||||
|
if test.user2 {
|
||||||
|
clientUser2VisitorConf += config
|
||||||
|
} else {
|
||||||
|
clientVisitorConf += config
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// run frps and frpc
|
// run frps and frpc
|
||||||
f.RunProcesses([]string{serverConf}, []string{clientServerConf, clientVisitorConf})
|
f.RunProcesses([]string{serverConf}, []string{clientServerConf, clientVisitorConf, clientUser2VisitorConf})
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
framework.NewRequestExpect(f).
|
framework.NewRequestExpect(f).
|
||||||
RequestModify(func(r *request.Request) {
|
RequestModify(func(r *request.Request) {
|
||||||
r.Timeout(10 * time.Second)
|
r.Timeout(3 * time.Second)
|
||||||
}).
|
}).
|
||||||
Protocol(protocol).
|
Protocol(protocol).
|
||||||
PortName(test.bindPortName).
|
PortName(test.bindPortName).
|
||||||
|
@ -56,7 +56,7 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
|
|||||||
ExpectNoError(err)
|
ExpectNoError(err)
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
}
|
}
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
return currentServerProcesses, currentClientProcesses
|
return currentServerProcesses, currentClientProcesses
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user