opened image

vsftpd: безопасный FTP-сервер с TLS и виртуальными пользователями

 

FTP в открытом виде передаёт логины, пароли и данные в plaintext - любой в той же сети видит всё. FTPS (FTP over TLS) шифрует соединение. В сочетании с виртуальными пользователями, ограниченными chroot, vsftpd становится приемлемым выбором для задач, где SFTP недоступен.

 

В статье установим vsftpd на Ubuntu 24.04, настроим TLS, создадим виртуальных пользователей через PAM и разберём отличия FTP/FTPS/SFTP.

 

 

FTP, FTPS и SFTP: в чём разница

 

FTP (File Transfer Protocol, порты 21/20) - передаёт данные открытым текстом. Использовать без TLS в 2026 году нельзя.

 

FTPS (FTP Secure, порты 21 для explicit, 990 для implicit) - FTP с шифрованием TLS/SSL. Два режима:

  • Explicit FTPS: клиент подключается на порт 21, затем командой AUTH TLS переходит на зашифрованное соединение

  • Implicit FTPS: соединение сразу зашифровано, порт 990

 

SFTP (SSH File Transfer Protocol, порт 22) - не является FTP. Это отдельный протокол поверх SSH. Встроен в OpenSSH, не требует vsftpd. Если задача - безопасная передача файлов, SFTP проще и надёжнее FTPS.

 

vsftpd поддерживает FTPS. SFTP - это openssh-server.

 

 

Установка vsftpd

 

sudo apt update
sudo apt install -y vsftpd libpam-pwdfile apache2-utils
  • libpam-pwdfile - PAM-модуль для аутентификации через htpasswd-файлы

  • apache2-utils - содержит htpasswd для создания файлов паролей

 

Проверьте версию:

vsftpd -v
# vsftpd: version 3.0.5

 

Создайте резервную копию стандартного конфига:

sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.orig

 

 

 

 

Создание TLS-сертификата

 

Для production используйте Let's Encrypt:

sudo apt install -y certbot
sudo certbot certonly --standalone -d ftp.example.com

 

Сертификаты будут в /etc/letsencrypt/live/ftp.example.com/.

 

Для локального использования - самоподписанный сертификат:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/ssl/private/vsftpd.key \
    -out /etc/ssl/certs/vsftpd.pem \
    -subj "/C=UA/ST=Kyiv/L=Kyiv/O=MyCompany/CN=ftp.example.com"

sudo chmod 600 /etc/ssl/private/vsftpd.key
sudo chmod 644 /etc/ssl/certs/vsftpd.pem

 

 

Конфигурация vsftpd с TLS

 

Полностью замените /etc/vsftpd.conf:

sudo nano /etc/vsftpd.conf
# Основные настройки
listen=YES
listen_ipv6=NO
anonymous_enable=NO
local_enable=YES
write_enable=YES
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES

# Виртуальные пользователи
virtual_use_local_privs=YES
pam_service_name=vsftpd_virtual
guest_enable=YES
guest_username=ftpuser

# Chroot - заключить пользователей в их домашние директории
chroot_local_user=YES
allow_writeable_chroot=YES
user_sub_token=$USER
local_root=/srv/ftp/$USER

# Пассивный режим - важно для работы за NAT/firewall
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100
pasv_address=YOUR_SERVER_IP

# TLS
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
require_ssl_reuse=NO
ssl_ciphers=HIGH

rsa_cert_file=/etc/ssl/certs/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.key

# Логирование
log_ftp_protocol=YES
vsftpd_log_file=/var/log/vsftpd.log

 

Параметры:

chroot_local_user=YES - пользователь видит только свою директорию как корень (/). Не может выйти за её пределы.

allow_writeable_chroot=YES - разрешает запись в chroot-директорию. По умолчанию запрещено из соображений безопасности; если директория не принадлежит root, включайте осознанно.

pasv_min_port=40000 и pasv_max_port=40100 - диапазон портов для пассивного режима. Эти порты нужно открыть в firewall.

force_local_data_ssl=YES и force_local_logins_ssl=YES - запрещают подключение без TLS.

require_ssl_reuse=NO - некоторые клиенты (FileZilla) не поддерживают переиспользование SSL-сессии. Отключение решает проблему с подключением.

 

 

Создание системного пользователя ftpuser

 

Все виртуальные пользователи будут работать от имени одного системного пользователя ftpuser:

sudo useradd --no-create-home --shell /bin/false --home /srv/ftp ftpuser
sudo mkdir -p /srv/ftp
sudo chown root:root /srv/ftp

Директория /srv/ftp принадлежит root - это требование vsftpd при включённом chroot.

 

 

Виртуальные пользователи через PAM

 

Создание файла паролей

# Создать файл с первым пользователем
sudo htpasswd -c /etc/vsftpd/virtual_users admin

# Добавить следующих пользователей
sudo htpasswd /etc/vsftpd/virtual_users alice
sudo htpasswd /etc/vsftpd/virtual_users bob

sudo mkdir -p /etc/vsftpd
sudo chmod 640 /etc/vsftpd/virtual_users
sudo chown root:root /etc/vsftpd/virtual_users

htpasswd создаёт файл с хешированными паролями (MD5 или bcrypt).

 

Настройка PAM

 

Создайте /etc/pam.d/vsftpd_virtual:

auth    required    pam_pwdfile.so    pwdfile=/etc/vsftpd/virtual_users
account required    pam_permit.so

Проверьте, что стандартный /etc/pam.d/vsftpd не конфликтует - он используется для системных пользователей.

 

 

 

 

Создание домашних директорий для пользователей

 

sudo mkdir -p /srv/ftp/admin /srv/ftp/alice /srv/ftp/bob
sudo chown ftpuser:ftpuser /srv/ftp/admin /srv/ftp/alice /srv/ftp/bob
sudo chmod 750 /srv/ftp/admin /srv/ftp/alice /srv/ftp/bob

 

Структура:

/srv/ftp/
├── admin/     ← chroot для пользователя admin
├── alice/     ← chroot для alice
└── bob/       ← chroot для bob

Каждый пользователь видит только свою директорию как /.

 

 

Запуск vsftpd

 

sudo systemctl restart vsftpd
sudo systemctl enable vsftpd
sudo systemctl status vsftpd

 

 

Настройка firewall

 

# UFW
sudo ufw allow 21/tcp comment "FTP"
sudo ufw allow 990/tcp comment "FTPS Implicit"
sudo ufw allow 40000:40100/tcp comment "FTP Passive"

# iptables
sudo iptables -A INPUT -p tcp --dport 21 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 990 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 40000:40100 -j ACCEPT

 

 

Тестирование через curl

 

# Листинг директории
curl -v --user "admin:password" "ftps://ftp.example.com/" --ssl-reqd -k

# Загрузка файла
curl -v --user "admin:password" "ftps://ftp.example.com/" \
    --ssl-reqd -k \
    --upload-file /tmp/test.txt

# Скачивание
curl --user "admin:password" "ftps://ftp.example.com/test.txt" \
    --ssl-reqd -k \
    -o /tmp/downloaded.txt

Флаг -k отключает проверку сертификата (для самоподписанного). В production уберите его.

 

 

 

 

Ограничение по IP через tcp_wrappers или hosts.allow

 

Дополнительная защита через /etc/hosts.allow:

vsftpd: 192.168.1.0/24 10.0.0.0/8

 

И /etc/hosts.deny:

vsftpd: ALL

 

Разрешаем только указанные сети, блокируем остальных.

 

 

Изоляция пользователей по доступу

 

Если нужно дать пользователю только read-only доступ, создайте для него отдельный конфиг в /etc/vsftpd/user_conf/:

sudo mkdir -p /etc/vsftpd/user_conf

 

Добавьте в vsftpd.conf:

user_config_dir=/etc/vsftpd/user_conf

 

Создайте /etc/vsftpd/user_conf/readonly_user:

write_enable=NO

vsftpd применит этот конфиг при подключении пользователя readonly_user.

 

 

Итог

 

vsftpd с TLS и виртуальными пользователями - рабочее решение для задач передачи файлов, где клиент не поддерживает SFTP. Ключевые моменты: force_local_logins_ssl=YES запрещает подключение без TLS, chroot_local_user=YES изолирует пользователей, pasv_min_port/pasv_max_port упрощают настройку firewall.

 

Если у вас нет жёстких требований к FTP-протоколу, предпочтите SFTP через OpenSSH - он работает через единый порт 22 без дополнительного ПО.