For anyone that ever had to setup a secure sFTP server, you’ve undoubtedly had some pains setting up vsftpd service.
This article shows a very nice alternative that may make your life much easier.
vsftpd
Vsftpd is a well known “very secure FTP daemon” application and does its job well when properly configured.
The problem I’ve always had with this application is the sheer amount of config options, the messy integration with SSH daemon, and a myriad of parameters that often contradict each other, making a secure configuration tough to fully understand, especially for a beginner.
One of my biggest problems with vsftpd is that you have create system accounts for users to login. Although there is an alias option (create a user alias instead of actual uid, it never worked properly when I tried setting this up)
Another config parameter that didnt make any sense to me was the “ftpusers” file that blocks access attempts from following users
etting up the service is easysimply run setup command# Users that are not allowed to login via ftp
root
bin
daemon
adm
lp
sync
shutdown
halt
news
uucp
operator
games
nobody
the file must be named “ftpusers”, yet these users arent using FTP, theyre blocked from using it. The naming of parameters isnt obvious and counter intuitive.
I always found vsftpd to be a pain in the ass to configure properly, especially with high degree of trust in its security to secure our customer’s data.
sFTPGo
sFTPGo is a new open source secure FTP application that dramatically eases the deployment and configuration of a secure FTP server.
Installation
sftpgo can be installed by downloading a release from the github repo
In this example, Im using Centos 7 so I installed the RPM version of the software
root@dev:~ $ sudo rpm -i sftpgo-2.0.2-1.x86_64.rpm
2021-03-05T12:32:31.000 INF Initializing provider: "sqlite" config file: "/etc/sftpgo/sftpgo.json"
2021-03-05T12:32:31.000 INF updating database version: 1 -> 2
2021-03-05T12:32:31.000 INF updating database version: 2 -> 3
2021-03-05T12:32:31.000 INF updating database version: 3 -> 4
2021-03-05T12:32:31.000 INF updating database version: 4 -> 5
2021-03-05T12:32:31.000 INF updating database version: 5 -> 6
2021-03-05T12:32:31.000 INF updating database version: 6 -> 7
2021-03-05T12:32:31.000 INF updating database version: 7 -> 8
2021-03-05T12:32:31.000 INF Data provider successfully initialized/updated
on install, the binary creates a folder and config file in /etc/sftpgo
by default it uses SQLite to manage users and other settings, but also supports Postgres
Config
once installed, sftpgo creates a config file in JSON form
{
"common": {
"idle_timeout": 15,
"upload_mode": 0,
"actions": {
"execute_on": [],
"hook": ""
},
"setstat_mode": 0,
"proxy_protocol": 0,
"proxy_allowed": [],
"post_connect_hook": "",
"max_total_connections": 0,
"defender": {
"enabled": false,
"ban_time": 30,
"ban_time_increment": 50,
"threshold": 15,
"score_invalid": 2,
"score_valid": 1,
"observation_time": 30,
"entries_soft_limit": 100,
"entries_hard_limit": 150,
"safelist_file": "",
"blocklist_file": ""
}
},
"sftpd": {
"bindings": [
{
"port": 2022,
"address": "",
"apply_proxy_config": true
}
],
"max_auth_tries": 0,
"banner": "",
"host_keys": [],
"kex_algorithms": [],
"ciphers": [],
"macs": [],
"trusted_user_ca_keys": [],
"login_banner_file": "",
"enabled_ssh_commands": [
"md5sum",
"sha1sum",
"cd",
"pwd",
"scp"
],
"keyboard_interactive_auth_hook": "",
"password_authentication": true
},
"ftpd": {
"bindings": [
{
"port": 0,
"address": "",
"apply_proxy_config": true,
"tls_mode": 0,
"force_passive_ip": "",
"client_auth_type": 0
}
],
"banner": "",
"banner_file": "",
"active_transfers_port_non_20": true,
"passive_port_range": {
"start": 50000,
"end": 50100
},
"disable_active_mode": false,
"enable_site": false,
"hash_support": 0,
"combine_support": 0,
"certificate_file": "",
"certificate_key_file": "",
"ca_certificates": [],
"ca_revocation_lists": []
},
"webdavd": {
"bindings": [
{
"port": 0,
"address": "",
"enable_https": false,
"client_auth_type": 0
}
],
"certificate_file": "",
"certificate_key_file": "",
"ca_certificates": [],
"ca_revocation_lists": [],
"cors": {
"enabled": false,
"allowed_origins": [],
"allowed_methods": [],
"allowed_headers": [],
"exposed_headers": [],
"allow_credentials": false,
"max_age": 0
},
"cache": {
"users": {
"expiration_time": 0,
"max_size": 50
},
"mime_types": {
"enabled": true,
"max_size": 1000
}
}
},
"data_provider": {
"driver": "sqlite",
"name": "/var/lib/sftpgo/sftpgo.db",
"host": "",
"port": 0,
"username": "",
"password": "",
"sslmode": 0,
"connection_string": "",
"sql_tables_prefix": "",
"track_quota": 2,
"pool_size": 0,
"users_base_dir": "/srv/sftpgo/data",
"actions": {
"execute_on": [],
"hook": ""
},
"external_auth_hook": "",
"external_auth_scope": 0,
"credentials_path": "/var/lib/sftpgo/credentials",
"prefer_database_credentials": false,
"pre_login_hook": "",
"post_login_hook": "",
"post_login_scope": 0,
"check_password_hook": "",
"check_password_scope": 0,
"password_hashing": {
"argon2_options": {
"memory": 65536,
"iterations": 1,
"parallelism": 2
}
},
"update_mode": 0
},
"httpd": {
"bindings": [
{
"port": 8080,
"address": "127.0.0.1",
"enable_web_admin": true,
"enable_https": false,
"client_auth_type": 0
}
],
"templates_path": "/usr/share/sftpgo/templates",
"static_files_path": "/usr/share/sftpgo/static",
"backups_path": "/srv/sftpgo/backups",
"certificate_file": "",
"certificate_key_file": "",
"ca_certificates": [],
"ca_revocation_lists": []
},
"telemetry": {
"bind_port": 10000,
"bind_address": "127.0.0.1",
"enable_profiler": false,
"auth_user_file": "",
"certificate_file": "",
"certificate_key_file": ""
},
"http": {
"timeout": 20,
"retry_wait_min": 2,
"retry_wait_max": 30,
"retry_max": 3,
"ca_certificates": [],
"certificates": [],
"skip_tls_verify": false
},
"kms": {
"secrets": {
"url": "",
"master_key_path": ""
}
}
}
Dont worry about all the optoins, the only 2 we care about are the FTP listen port (set to 2022) and the Console web port (set to 127.0.0.1:8080)
if you need to run your FTP service on different ports, or access the console from another server, update the ports and web IP (ie, 0.0.0.0:8080)
once updated, run
sftpgo server
sftpgo will start FTP process and generate SSH keys
sftpgo serve
2021-03-05T12:43:36.114 INF No host keys configured and "id_rsa" does not exist; try to create a new host key
2021-03-05T12:43:37.690 INF No host keys configured and "id_ecdsa" does not exist; try to create a new host key
2021-03-05T12:43:37.701 INF No host keys configured and "id_ed25519" does not exist; try to create a new host key
You can also run it as a systemd service
sytemctl restart sftpgo
Admin Console
you can now access your FTP admin console and create users
https://your-IP-or-hostname:<port defined in config>
default creds:
admin
password
obviously change them once you log in
From here you can create users, shared folders and other settings, the options to control how your users access your FTP server are huge and easy to configure
You can control how the user can authenticate to your FTP server (which protocol, password or ssh key, or some other combination)
You can also define what action the user can take on the files inside their FTP directory, file quotas, and which directory the user will be routed to (in this example I’m using an S3 bucket as FTP home dir)
Client connections
Clients can connect to your SFTP server by running a basic sftp connection command
sftp -P 2022 username@your-IP-or-hostname
you can also see any connected clients on the admin console
SFTPGO is a fantastic modern alternative to vsftpd, written in Golang. Give it a try.