stcp, xtcp, sudp: support allow_users and specified server user (#3472)

This commit is contained in:
fatedier
2023-06-02 16:06:29 +08:00
committed by GitHub
parent cceab7e1b1
commit de85c9455a
17 changed files with 355 additions and 176 deletions

View File

@@ -21,57 +21,69 @@ import (
"sync"
libio "github.com/fatedier/golib/io"
"github.com/samber/lo"
utilnet "github.com/fatedier/frp/pkg/util/net"
"github.com/fatedier/frp/pkg/util/util"
)
type listenerBundle struct {
l *utilnet.InternalListener
sk string
allowUsers []string
}
// Manager for visitor listeners.
type Manager struct {
visitorListeners map[string]*utilnet.InternalListener
skMap map[string]string
listeners map[string]*listenerBundle
mu sync.RWMutex
}
func NewManager() *Manager {
return &Manager{
visitorListeners: make(map[string]*utilnet.InternalListener),
skMap: make(map[string]string),
listeners: make(map[string]*listenerBundle),
}
}
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()
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)
return
}
l = utilnet.NewInternalListener()
vm.visitorListeners[name] = l
vm.skMap[name] = sk
vm.listeners[name] = &listenerBundle{
l: l,
sk: sk,
allowUsers: allowUsers,
}
return
}
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) {
vm.mu.RLock()
defer vm.mu.RUnlock()
if l, ok := vm.visitorListeners[name]; ok {
var sk string
if sk = vm.skMap[name]; util.GetAuthKey(sk, timestamp) != signKey {
if l, ok := vm.listeners[name]; ok {
if util.GetAuthKey(l.sk, timestamp) != signKey {
err = fmt.Errorf("visitor connection of [%s] auth failed", name)
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
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)
return
}
@@ -79,7 +91,7 @@ func (vm *Manager) NewConn(name string, conn net.Conn, timestamp int64, signKey
if useCompression {
rwc = libio.WithCompression(rwc)
}
err = l.PutConn(utilnet.WrapReadWriteCloserToConn(rwc, conn))
err = l.l.PutConn(utilnet.WrapReadWriteCloserToConn(rwc, conn))
} else {
err = fmt.Errorf("custom listener for [%s] doesn't exist", name)
return
@@ -91,6 +103,5 @@ func (vm *Manager) CloseListener(name string) {
vm.mu.Lock()
defer vm.mu.Unlock()
delete(vm.visitorListeners, name)
delete(vm.skMap, name)
delete(vm.listeners, name)
}