Synopsis #
vsftpd (Very Secure FTP Daemon) is an FTP server available through OpenBSD packages. It supports local and anonymous users, chrooted sessions, and FTPS for encrypted transfers.
vsftpd does not include a large module system or its own virtual-user database. It supports:
- Passive and active FTP modes
- Anonymous and local user logins
- Chrooting users
- FTPS encryption
vsftpd is not part of the OpenBSD base system and must be installed from packages.
FTP Server Comparison #
The supported choices documented here are:
| Server | Availability on OpenBSD 8.0 | TLS | Isolation |
|---|---|---|---|
| ftpd | Base system | No | Anonymous home; users selected by /etc/ftpchroot |
| Pure-FTPd | Package | Yes | Configurable chroot and virtual users |
| vsftpd | Package | Yes | Configurable local-user chroot |
ProFTPD is not in the official OpenBSD 8.0 ports tree or amd64 package set. Prefer SFTP for encrypted file access unless FTP compatibility is required.
Installation #
Install vsftpd using the packages system:
doas pkg_add vsftpd
This installs the daemon (vsftpd) and the default configuration file:
/etc/vsftpd.conf
Basic Configuration #
A minimal configuration enabling read-only local user access might look like this:
listen=YES
listen_ipv6=NO
anonymous_enable=NO
local_enable=YES
write_enable=NO
local_umask=022
chroot_local_user=YES
ftpd_banner=Welcome to OpenBSD vsftpd
# Limit passive ports for firewalling
pasv_min_port=49152
pasv_max_port=49200
# Use unprivileged user
nopriv_user=_vsftpd
secure_chroot_dir=/var/empty
# Secure log location
xferlog_enable=YES
vsftpd_log_file=/var/log/vsftpd.log
Set secure_chroot_dir to /var/empty, OpenBSD’s empty, root-owned directory. The default /usr/share/empty does not exist on OpenBSD and causes connections to fail before login.
Anonymous access is disabled in this example. Enabling it also requires an ftp account with an appropriate home, or an explicitly configured ftp_username and anon_root. Keep the anonymous root owned by root and non-writable by clients.
Local logins must satisfy the installed daemon’s shell and user-list policies. Merely selecting /sbin/nologin does not establish a working FTP-only account. With chroot_local_user=YES, keep each chroot root non-writable by the account and put uploads in a separately owned child directory. Set write_enable=YES only if uploads are intended, then test both allowed and denied writes.
Starting the Service #
The package provides an rc script:
doas rcctl enable vsftpd
doas rcctl start vsftpd
doas rcctl check vsftpd
Use doas rcctl restart vsftpd after configuration changes. Do not launch a second daemon from /etc/rc.local.
FTPS (TLS) Support #
vsftpd supports FTPS (FTP over SSL/TLS). To enable it:
- Generate or obtain a certificate and key pair.
doas mkdir -p /etc/ssl/vsftpd
doas openssl req -x509 -nodes -newkey rsa:2048 \
-keyout /etc/ssl/vsftpd/server.key \
-out /etc/ssl/vsftpd/server.crt \
-days 365
- Set ownership and permissions:
doas chmod 600 /etc/ssl/vsftpd/server.key
doas chmod 644 /etc/ssl/vsftpd/server.crt
- Modify the configuration:
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
rsa_cert_file=/etc/ssl/vsftpd/server.crt
rsa_private_key_file=/etc/ssl/vsftpd/server.key
Restart vsftpd and verify the negotiated TLS version and certificate with an FTPS client. Consult the installed vsftpd.conf(5) for the TLS controls supported by that package version; the self-signed example requires explicit client trust.
Use a certificate matching the server hostname and trust its CA. If a TLS 1.3 FTPS login succeeds but the data transfer returns no bytes, retry with TLS 1.2:
curl --ssl-reqd --tlsv1.2 --tls-max 1.2 --cacert /path/to/trusted-ca.pem \
--user ftpuser --output downloaded.txt ftp://server.example.net/test.txt
The client prompts for the password. Check the downloaded content. Keep certificate and hostname checks enabled, and keep the server’s session-reuse requirement.
Passive and Active FTP #
By default, vsftpd supports passive mode, which is recommended for most environments behind firewalls.
To restrict the port range for passive data connections:
pasv_min_port=49152
pasv_max_port=49200
OpenBSD’s pf.conf should be updated to permit control and data ports:
pass in on $int_if proto tcp from any to (self) port 21
pass in on $int_if proto tcp from any to (self) port 49152:49200
Active FTP requires client firewalls to permit incoming connections, which may not be feasible.
Logging and Monitoring #
With xferlog_enable=YES, vsftpd records transfers in its native log format at the path selected by vsftpd_log_file. Standard xferlog format requires xferlog_std_format=YES; use xferlog_file to select its destination.
Example:
doas tail -f /var/log/vsftpd.log
To test access:
ftp localhost
lftp ftp://ftpuser@localhost
Use tcpdump or netstat -an to verify connection attempts and port usage.