disable self connections by default

now that the event manager can create files, self connections may create
even more issues than before

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino 2022-10-12 18:12:12 +02:00
parent aa1e73326f
commit 4b4edef0ad
No known key found for this signature in database
GPG key ID: 935D2952DEC4EECF
13 changed files with 37 additions and 4 deletions

View file

@ -78,6 +78,7 @@ The configuration file contains the following sections:
- `max_total_connections`, integer. Maximum number of concurrent client connections. 0 means unlimited. Default: 0.
- `max_per_host_connections`, integer. Maximum number of concurrent client connections from the same host (IP). If the defender is enabled, exceeding this limit will generate `score_limit_exceeded` events and thus hosts that repeatedly exceed the max allowed connections can be automatically blocked. 0 means unlimited. Default: 20.
- `whitelist_file`, string. Path to a file containing a list of IP addresses and/or networks to allow. Only the listed IPs/networks can access the configured services, all other client connections will be dropped before they even try to authenticate. The whitelist must be a JSON file with the same structure documented for the [defenders's list](./defender.md). The whitelist can be reloaded on demand sending a `SIGHUP` signal on Unix based systems and a `paramchange` request to the running service on Windows. Default: "".
- `allow_self_connections`, integer. Allow users on this instance to use other users/virtual folders on this instance as storage backend. Enable this setting if you know what you are doing. Set to `1` to enable. Default: `0`.
- `defender`, struct containing the defender configuration. See [Defender](./defender.md) for more details.
- `enabled`, boolean. Default `false`.
- `driver`, string. Supported drivers are `memory` and `provider`. The `provider` driver will use the configured data provider to store defender events and it is supported for `MySQL`, `PostgreSQL` and `CockroachDB` data providers. Using the `provider` driver you can share the defender events among multiple SFTPGO instances. For a single instance the `memory` driver will be much faster. Default: `memory`.

View file

@ -212,6 +212,8 @@ func Initialize(c Configuration, isShared int) error {
}
vfs.SetTempPath(c.TempPath)
dataprovider.SetTempPath(c.TempPath)
vfs.SetAllowSelfConnections(c.AllowSelfConnections)
dataprovider.SetAllowSelfConnections(c.AllowSelfConnections)
transfersChecker = getTransfersChecker(isShared)
return nil
}
@ -504,6 +506,9 @@ type Configuration struct {
// Only the listed IPs/networks can access the configured services, all other client connections
// will be dropped before they even try to authenticate.
WhiteListFile string `json:"whitelist_file" mapstructure:"whitelist_file"`
// Allow users on this instance to use other users/virtual folders on this instance as storage backend.
// Enable this setting if you know what you are doing.
AllowSelfConnections int `json:"allow_self_connections" mapstructure:"allow_self_connections"`
// Defender configuration
DefenderConfig DefenderConfig `json:"defender" mapstructure:"defender"`
// Rate limiter configurations

View file

@ -93,6 +93,7 @@ func TestMain(m *testing.M) {
logger.InitLogger(logFilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
os.Setenv("SFTPGO_COMMON__ALLOW_SELF_CONNECTIONS", "1")
os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")
os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")
err := config.LoadConfig(configDir, "")

View file

@ -208,6 +208,7 @@ func Init() {
MaxTotalConnections: 0,
MaxPerHostConnections: 20,
WhiteListFile: "",
AllowSelfConnections: 0,
DefenderConfig: common.DefenderConfig{
Enabled: false,
Driver: common.DefenderDriverMemory,
@ -1862,6 +1863,7 @@ func setViperDefaults() {
viper.SetDefault("common.max_total_connections", globalConf.Common.MaxTotalConnections)
viper.SetDefault("common.max_per_host_connections", globalConf.Common.MaxPerHostConnections)
viper.SetDefault("common.whitelist_file", globalConf.Common.WhiteListFile)
viper.SetDefault("common.allow_self_connections", globalConf.Common.AllowSelfConnections)
viper.SetDefault("common.defender.enabled", globalConf.Common.DefenderConfig.Enabled)
viper.SetDefault("common.defender.driver", globalConf.Common.DefenderConfig.Driver)
viper.SetDefault("common.defender.ban_time", globalConf.Common.DefenderConfig.BanTime)

View file

@ -195,6 +195,7 @@ var (
lastLoginMinDelay = 10 * time.Minute
usernameRegex = regexp.MustCompile("^[a-zA-Z0-9-_.~]+$")
tempPath string
allowSelfConnections int
fnReloadRules FnReloadRules
fnRemoveRule FnRemoveRule
fnHandleRuleForProviderEvent FnHandleRuleForProviderEvent
@ -804,6 +805,11 @@ type Provider interface {
resetDatabase() error
}
// SetAllowSelfConnections sets the desired behaviour for self connections
func SetAllowSelfConnections(value int) {
allowSelfConnections = value
}
// SetTempPath sets the path for temporary files
func SetTempPath(fsPath string) {
tempPath = fsPath

View file

@ -497,6 +497,9 @@ func (u *User) GetPermissionsForPath(p string) []string {
}
func (u *User) getForbiddenSFTPSelfUsers(username string) ([]string, error) {
if allowSelfConnections == 0 {
return nil, nil
}
sftpUser, err := UserExists(username)
if err == nil {
err = sftpUser.LoadAndApplyGroupSettings()

View file

@ -277,6 +277,7 @@ func TestMain(m *testing.M) {
// work in non atomic mode too
os.Setenv("SFTPGO_COMMON__UPLOAD_MODE", "2")
os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
os.Setenv("SFTPGO_COMMON__ALLOW_SELF_CONNECTIONS", "1")
os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")
os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")
err = config.LoadConfig(configDir, "")

View file

@ -296,6 +296,7 @@ func TestMain(m *testing.M) {
logger.InitLogger(logfilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
os.Setenv("SFTPGO_COMMON__UPLOAD_MODE", "2")
os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
os.Setenv("SFTPGO_COMMON__ALLOW_SELF_CONNECTIONS", "1")
os.Setenv("SFTPGO_DATA_PROVIDER__NAMING_RULES", "0")
os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")
os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")

View file

@ -189,6 +189,7 @@ func TestMain(m *testing.M) {
}
os.Setenv("SFTPGO_COMMON__UPLOAD_MODE", "2")
os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
os.Setenv("SFTPGO_COMMON__ALLOW_SELF_CONNECTIONS", "1")
os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")
os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")
err = config.LoadConfig(configDir, "")

View file

@ -843,8 +843,12 @@ func (fs *SFTPFs) createConnection() error {
HostKeyCallback: func(_ string, _ net.Addr, key ssh.PublicKey) error {
fp := ssh.FingerprintSHA256(key)
if util.Contains(sftpFingerprints, fp) {
if allowSelfConnections == 0 {
fsLog(fs, logger.LevelError, "SFTP self connections not allowed")
return ErrSFTPLoop
}
if util.Contains(fs.config.forbiddenSelfUsernames, fs.config.Username) {
fsLog(fs, logger.LevelError, "SFTP loop or nested local SFTP folders detected, mount path %#v, username %#v, forbidden usernames: %+v",
fsLog(fs, logger.LevelError, "SFTP loop or nested local SFTP folders detected, mount path %q, username %q, forbidden usernames: %+v",
fs.mountPath, fs.config.Username, fs.config.forbiddenSelfUsernames)
return ErrSFTPLoop
}

View file

@ -45,11 +45,17 @@ var (
// ErrStorageSizeUnavailable is returned if the storage backend does not support getting the size
ErrStorageSizeUnavailable = errors.New("unable to get available size for this storage backend")
// ErrVfsUnsupported defines the error for an unsupported VFS operation
ErrVfsUnsupported = errors.New("not supported")
tempPath string
sftpFingerprints []string
ErrVfsUnsupported = errors.New("not supported")
tempPath string
sftpFingerprints []string
allowSelfConnections int
)
// SetAllowSelfConnections sets the desired behaviour for self connections
func SetAllowSelfConnections(value int) {
allowSelfConnections = value
}
// SetTempPath sets the path for temporary files
func SetTempPath(fsPath string) {
tempPath = fsPath

View file

@ -268,6 +268,7 @@ func TestMain(m *testing.M) {
logFilePath = filepath.Join(configDir, "sftpgo_webdavd_test.log")
logger.InitLogger(logFilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
os.Setenv("SFTPGO_COMMON__ALLOW_SELF_CONNECTIONS", "1")
os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")
os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")
err := config.LoadConfig(configDir, "")

View file

@ -18,6 +18,7 @@
"max_total_connections": 0,
"max_per_host_connections": 20,
"whitelist_file": "",
"allow_self_connections": 0,
"defender": {
"enabled": false,
"driver": "memory",