FTP - один из самых старых сетевых протоколов, и админу до сих пор приходится либо его поднимать, либо чинить, либо грамотно от него отказываться. Задача урока - разобраться, почему FTP ведет себя странно за NAT и фаерволом (два режима, два канала), как поднять vsftpd и Pure-FTPd для анонимного и локального доступа, как запереть пользователей в их каталогах через chroot, как накатить шифрование FTPS и в каком случае честнее выбрать SFTP. Это объект 212.2, и на экзамене спрашивают именно про конфиги и режимы.

Как это работает
Главная странность FTP в том, что он использует два TCP-соединения. Управляющий канал (порт 21) живет всю сессию: по нему летят команды USER, PASS, LIST, RETR и текстовые ответы сервера с трехзначными кодами. А вот сами файлы и листинги каталогов идут по отдельному канале данных, который открывается заново под каждую передачу. Разделение придумали в семидесятых, когда о NAT никто не думал, и сегодня именно оно создает большинство проблем.
Канал данных бывает активным и пассивным, и разница в том, кто кому звонит. В активном режиме (команда PORT) клиент сообщает серверу свой IP и порт, и сервер сам инициирует соединение к клиенту с порта 20. Проблема очевидна: если клиент за NAT или у него включен фаервол, входящее соединение от сервера до него не дойдет. Поэтому по умолчанию почти везде используется пассивный режим (команда PASV): сервер открывает случайный высокий порт, называет его клиенту, и клиент сам подключается к серверу. Теперь за NAT прячется сервер, и забота переносится на админа сервера - надо открыть в фаерволе диапазон пассивных портов и в конфиге его прописать.
Передача может идти в двух типах. Binary (TYPE I) копирует байт в байт - так гоняют все, кроме совсем уж текстовых сценариев. ASCII (TYPE A) переводит концы строк между платформами и легко портит бинарники, поэтому в реальной жизни его держат выключенным.
Теперь про доступ. Анонимный FTP - это вход логином anonymous (или ftp) с любым паролем, обычно для публичной раздачи файлов только на чтение. Локальный доступ - вход под реальной системной учеткой из /etc/passwd. И тут вылезает безопасность: пускать локального юзера гулять по всей файловой системе нельзя, поэтому применяют chroot - подмену корня. После chroot пользователь видит свой домашний каталог как / и физически не может выйти выше. Тонкость vsftpd: каталог, в который делается chroot, по умолчанию не должен быть доступен на запись самому юзеру - иначе сервер ругнется и откажет в логине (защита от подмены символьных ссылок).
Открытый FTP шлет пароль и данные в чистом виде, поэтому добавили FTPS - тот же FTP, но в TLS. Не путайте с SFTP: SFTP это вообще не FTP, а подсистема SSH, один порт 22, один зашифрованный канал, никаких заморочек с режимами. FTPS бывает явный (клиент подключается к 21 и командой AUTH TLS поднимает шифрование, современный вариант, RFC 4217) и неявный (TLS сразу на отдельном порту 990, легаси). Именно из-за двух каналов и плясок с портами FTP в 2026 проиграл: для перекидывания файлов между людьми берут SFTP, а FTP/FTPS остается там, где он зашит в legacy: старые прошивки, промышленные контроллеры, публичные зеркала дистрибутивов, корпоративные интеграции, которые никто не трогает.
Команды и примеры
Установка. В Debian/Ubuntu:
Код: Выделить всё
apt install vsftpd
apt install pure-ftpdКод: Выделить всё
dnf install vsftpd
dnf install epel-release && dnf install pure-ftpdКод: Выделить всё
listen=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
chroot_local_user=YES
allow_writeable_chroot=YES
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100
pasv_address=203.0.113.10Код: Выделить всё
systemctl enable --now vsftpd
systemctl status vsftpdКод: Выделить всё
nft add rule inet filter input tcp dport 21 accept
nft add rule inet filter input tcp dport 40000-40100 acceptКод: Выделить всё
firewall-cmd --permanent --add-service=ftp
firewall-cmd --reloadКод: Выделить всё
ssl_enable=YES
force_local_data_ssl=YES
force_local_logins_ssl=YES
rsa_cert_file=/etc/ssl/certs/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.key
ssl_tlsv1_2=YES
require_ssl_reuse=NOКод: Выделить всё
echo "yes" > /etc/pure-ftpd/conf/ChrootEveryone
echo "40000 40100" > /etc/pure-ftpd/conf/PassivePortRange
systemctl restart pure-ftpdКод: Выделить всё
lftp -u alice ftps://203.0.113.10
ftp> ls
ftp> put report.txt- Пассивный режим висит на этапе LIST или передачи: диапазон pasv_min_port/pasv_max_port не открыт в фаерволе. Управляющий канал по 21 проходит, а данные нет - выглядит как зависание.
- vsftpd за NAT отдает в PASV внутренний IP. Без pasv_address клиент получает адрес из приватной сети и не может подключиться. Прописывайте внешний адрес.
- Ошибка "refusing to run with writable root inside chroot" - забыли allow_writeable_chroot=YES либо, наоборот, домашний каталог зря сделан писываемым. Решайте осознанно, а не копипастой.
- FTPS и трекинг соединений не дружат: модуль nf_conntrack_ftp читает команду PORT/PASV в открытом виде, а в TLS она зашифрована. Фаервол перестает автоматически открывать порты данных - значит, диапазон надо открыть руками.
- Включенный по привычке ASCII-режим бьет бинарные файлы (картинки, архивы) подменой символов перевода строки. Держите передачу в binary.
- Путаница FTPS и SFTP в задании или тикете. Разные протоколы, разные порты, разные демоны (vsftpd против sshd). Уточняйте, что именно просят.
- Поставьте vsftpd на учебный стенд и заведите системного пользателя ftpuser с паролем.
- Включите local_enable, write_enable, chroot_local_user и allow_writeable_chroot, перезапустите сервис через systemctl.
- Задайте пассивный диапазон 40000-40100 и pasv_address (если стенд за NAT - внешний адрес, иначе адрес стенда), откройте порты в nftables или firewalld.
- Подключитесь клиентом lftp под ftpuser, загрузите файл командой put и убедитесь, что попали именно в домашний каталог, а выше / не выходите.
- Сгенерируйте самоподписанный сертификат и включите ssl_enable с force_local_logins_ssl, проверьте вход уже по ftps:// .
- В логе vsftpd (/var/log/vsftpd.log) найдите свою сессию и команды PASV, посмотрите, какой порт данных был выдан.
- Для сравнения подключитесь к тому же юзеру по sftp и прочувствуйте разницу: один порт, шифрование сразу, ноль настроек портов.
- Чем отличается активный режим FTP от пассивного и почему пассивный режим стал стандартом для клиентов за NAT?
- Какие два TCP-соединения использует FTP и какие порты задействованы в активном режиме по умолчанию?
- Что делает директива chroot_local_user в vsftpd и в каком случае понадобится allow_writeable_chroot?
- В чем разница между явным (AUTH TLS) и неявным FTPS и какой порт у неявного варианта?
- Почему FTPS ломает автоматическое открытие портов данных модулем conntrack, тогда как для открытого FTP оно работает?
- Почему SFTP в 2026 предпочтительнее FTP/FTPS для передачи файлов между людьми и где FTP все же остается уместен?