Зачем понимать оба
FTP (RFC 959, 1985), древний протокол. На современных серверах его место занял SFTP (часть SSH). Но FTP ещё встречается:
- Старые ISP и hosting-панели (cPanel, Plesk)
- Embedded-устройства (роутеры, прошивки firmware-апдейтов)
- Anonymous FTP-зеркала Linux-distro (
ftp.debian.org→ теперь HTTPS) - Legacy CI/CD pipelines
SFTP, стандарт для нового кода. Один порт, шифрование, аутентификация по ключу, работает через NAT, не требует отдельного сервиса (если есть SSH).
FTP, два соединения
Принципиальная странность FTP: два TCP-соединения на сессию:
Client Server
│ │
│ TCP-соединение к порту 21 (control)
├───────────────────────────────────►│
│ USER alice │
│ PASS secret │
│ (команды и ответы текстом) │
│ │
│ STOR file.bin │
│ ←─── server ОТКРЫВАЕТ data-соединение к клиенту (active)
│ ИЛИ: server говорит "слушаю на N", клиент подключается (passive)
│ │
- Control connection (порт 21), команды текстом:
USER,PASS,LIST,RETR,STOR,QUIT. Ответы, три цифры + текст (220 Welcome,530 Login incorrect,226 Transfer complete). - Data connection, отдельное TCP. Может открываться двумя способами.
Active mode
Клиент шлёт PORT a,b,c,d,p1,p2, "я слушаю на IP a.b.c.d порту
p1*256+p2". Сервер подключается к клиенту.
Проблема: клиент за NAT не имеет публичного IP, не может принять входящий коннект. Active mode на современных клиентах редко работает.
Passive mode (PASV)
Клиент шлёт PASV. Сервер отвечает 227 Entering Passive Mode (a,b,c,d,p1,p2), "подключайся ко мне на этом IP/порту". Клиент
подключается. Клиент-инициированы оба соединения.
Современный default. Но проблема перемещается на сервер: его NAT/firewall должен пробрасывать диапазон портов для PASV-data-каналов.
В vsftpd.conf:
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100
pasv_address=203.0.113.10 # для NAT'а перед сервером
Затем открыть в фаерволе диапазон 40000-40100 + 21.
FTPS, FTP + TLS
Не путать с SFTP! FTPS, это FTP с TLS-обёрткой:
- Implicit FTPS: TLS-handshake сразу при подключении на 990
- Explicit FTPS: подключение на 21 → команда
AUTH TLS→ TLS-handshake
Решает шифрование, но не решает двухсоединительную архитектуру.
Data-канал тоже надо шифровать (PROT P), и фаервол всё равно должен
знать про PASV-диапазон.
В 2026 FTPS, нишевый легаси. Используется в финсекторе для compliance, если "стандарт говорит FTP с шифрованием".
SFTP, это SSH
SFTP (SSH File Transfer Protocol, не путать с simple FTP), подсистема
SSH (RFC 4254). Внутри SSH-соединения запускается sftp-server,
который отвечает на бинарный protocol для файловых операций.
Никакого TCP-21, никакого PASV/active. Один TCP-22 порт, шифрование
и аутентификация, те же, что у ssh.
Включено в openssh-server по дефолту, в /etc/ssh/sshd_config:
Subsystem sftp /usr/lib/openssh/sftp-server
Использование:
sftp user@server # интерактивный shell
sftp> ls
sftp> put localfile remotefile
sftp> get remotefile localfile
sftp> bye
sftp -P 2222 user@server # нестандартный SSH-порт
# batch-режим
echo "put file.bin /upload/" | sftp user@server
SCP vs SFTP
scp file.bin user@server:/upload/
- scp (Secure Copy), простой "rcp поверх SSH"; один файл/директория, без интерактивности.
- sftp, полный shell с
cd,ls,mkdir, glob.
С OpenSSH 9.0 (2022) дефолтный scp использует SFTP под капотом
(legacy-режим через -O). Это закрыло несколько CVE и привело
поведение в порядок (например glob-expansion).
Для простых случаев, scp или rsync -e ssh. Для интерактивной
работы, sftp. Между серверами больших объёмов, [[cmd-rsync|rsync]].
SFTP-only-юзеры (chroot)
Часто хочется дать доступ к загрузке файлов без shell. В sshd_config:
Match Group sftponly
ChrootDirectory /var/sftp/%u
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
Требования к chroot-директории:
- Owner = root, mode 755 (sshd проверяет, иначе отвалится с
bad ownership or modes) - Внутри неё уже владельцем юзера могут быть поддиректории для записи
groupadd sftponly
useradd -G sftponly -s /usr/sbin/nologin alice
mkdir -p /var/sftp/alice/upload
chown root:root /var/sftp/alice
chmod 755 /var/sftp/alice
chown alice:alice /var/sftp/alice/upload
Юзер видит /upload как корень, никакого shell'а, только sftp.
FTP vs SFTP vs FTPS
| Признак | FTP | SFTP | FTPS |
|---|---|---|---|
| Транспорт | 2 TCP (21 + data) | 1 TCP (22) | 2 TCP + TLS |
| Шифрование | нет | да (SSH) | да (TLS) |
| Аутентификация | password в открытую | ключ или пароль | TLS-cert + password |
| NAT-friendly | нет (PASV-диапазон) | да | нет |
| Часть стандартного дистро | vsftpd, proftpd | openssh-server | vsftpd-with-tls |
| Сертификаты PKI | - | можно SSH-CA | да |
| Production-выбор | избегать | стандарт | только legacy |
Anonymous FTP
Историческая фича: подключение под ftp или anonymous без пароля
(либо email-as-password). Использовалось для public-mirror'ов.
Сегодня - мёртвая практика. Linux-mirror'ы перешли на HTTP/HTTPS (rsync под капотом), Anonymous FTP отключают на новых vsftpd:
anonymous_enable=NO
Когда что-то пошло не так
Connection refusedпосле login на FTP, PASV не настроен или диапазон портов не открыт в фаерволе.- FTP "висит" после
LIST, active mode пытается, клиент за NAT.quote PASV(или клиент в passive-only). - FTPS падает на data-канале,
PROT Pне задан, либо TLS-session не переиспользуется. На vsftpd:require_ssl_reuse=NO(или нет). Subsystem request failedна SFTP,Subsystem sftpзакомментирован в sshd_config, либо путь к sftp-server неправильный.bad ownership or modes for chroot directory, chroot должен принадлежать root и иметь mode ≤755. Никаких group-write.scpстал странно работать после OpenSSH 9.0, теперь использует SFTP под капотом.scp -Oдля legacy-протокола.
Альтернативы
- [[cmd-rsync|rsync]] через SSH, для синхронизации (инкрементальная)
- HTTPS + [[cmd-curl|curl]] / wget для public download
- Object storage (S3/MinIO) для приложений
- WebDAV, HTTP-based, иногда удобнее