Доступ к FTP-серверу за NAT

01.03.2020

Теги: FTPLinuxUbuntuКонфигурацияЛокальнаяСетьНастройкаСервер

Протокол FTP является старейшим сетевым протоколом (создан в 1971 году), но, тем не менее, широко используется по сей день. Важной особенностью протокола является то, что он использует несколько соединений: одно для управляющих команд, остальные для данных. Причем соединений для передачи данных может открываться несколько.

В зависимости от способа установления соединения для передачи данных различают активный и пассивный режимы работы FTP. В активном режиме сервер сам устанавливает соединение передачи данных к клиенту, в пассивном наоборот.

Активный режим

В активном режиме клиент устанавливает управляющее соединение на порт 21 сервера и передает специальную команду PORT, в которой указывает свой адрес и порт для передачи данных. Получив данную команду, сервер устанавливает соединение с 20 порта на указанный в команде порт клиента.

Тут сразу виден недостаток данного метода: для работы в активном режиме клиенту требуется выделенный IP-адрес. Также определенные сложности будут возникать при нахождении клиента за брандмауэром или NAT-ом.

Пассивный режим

В пассивном режиме клиент устанавливает управляющее соединение на порт 21 сервера и передает специальную команду PASV. В ответ сервер передает адрес и порт, на который следует устанавливать соединение для передачи данных. Получив эту информацию, клиент устанавливает подключение к серверу и начинает передачу данных.

Как видим, в пассивном режиме все соединения инициирует клиент и поэтому к нему нет никаких требований, он может находиться за NAT и брандмауэром, а также не иметь выделенного IP-адреса. Поэтому на сегодняшний день основным режимом работы FTP является пассивный.

FTP сервер за NAT

У меня дома компьютер с установленной Windows 10 и VirtualBox. Давайте создадим несколько виртуальных машин: router, pc-1, pc-2, ftp-server и web-server (будет играть роль FTP-клиента). У виртуальной машины router два сетевых интерфейса:

  • enp0s3 (сетевой мост) — смотрит в домашнюю сеть, получает ip-адрес 192.168.110.8 от роутера Keenetic Air
  • enp0s8 (виртуальная сеть) — смотрит в одну сеть с виртуальными машинами pc-1, pc-2 и ftp-server

Виртуальная машина router обеспечивает выход в интренет для pc-1, pc-2 и ftp-server. Все это более подробно можно прочитать здесь. А если совсем коротко, то тогда так

$ sudo nano /etc/sysctl.conf
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
$ sudo sysctl -p
net.ipv4.ip_forward = 1
$ sudo iptables -t nat -A POSTROUTING -o enp0s3 -j SNAT --to-source 192.168.110.8 # SNAT для enp0s3
$ sudo iptables-save > /etc/iptables/rules.v4 # должен быть установлен пакет iptables-persistent

Давайте установим на виртуальную машину ftp-server FTP-сервер vsftpd:

$ sudo apt install vsftpd

Про настройки подробно рассказывать не буду (подробнее можно прочитать здесь), упомяну только важные для нас:

  • pasv_enable=NO — используется только активный режим
  • pasv_enable=YES — можно использовать пассивный режим
  • pasv_address=XXX.XXX.XXX.XXX — этот ip-адрес сервер будет передавать клиенту вместо своего в ответ на PASV
  • pasv_min_port и pasv_max_port — сервер будет отправлять клиенту порт из этого диапазона в ответ на PASV
$ sudo nano /etc/vsftpd.conf
# Слушать и обрабатывать входящие соединения
listen=YES
# Запретить доступ для анонимных пользователей
anonymous_enable=NO
# Использовать для авторизации учётные записи пользователей
local_enable=YES
# Разрешить изменения файловой системы (запись и удаление файлов)
write_enable=YES
# Маска для вновь создаваемых файлов и директорий
local_umask=022
# Запретить пользователям выходить за пределы домашнего каталога
chroot_local_user=YES
# Разрешить запись в домашний каталог (иначе будет ошибка)
allow_writeable_chroot=YES
# Показывать скрытые файлы, которые начинаются с точки
force_dot_files=NO
# При выводе списка файлов показывать локальное время, а не GMT
use_localtime=YES
# Записывать в /var/log/vsftpd.log данные о скачиваниях и загрузках
xferlog_enable=YES
# Включить поддержку ASCII для замены символов переноса строки
ascii_upload_enable=YES
ascii_download_enable=YES
# Использовать кодировку UTF-8 при работе с файловой системой
utf8_filesystem=YES

# Разрешить использование пассивного режима
pasv_enable=NO

# Диапазон портов для работы FTP-сервера в пассивном режиме
#pasv_min_port=60000
#pasv_max_port=60100
# Передавать клиенту этот ip-адрес вместо своего в ответ на PASV
#pasv_address=192.168.110.8
$ sudo systemctl restart vsftpd.service

Теперь на виртуальной машине router настроим перенаправление пакетов, которые приходят на внешней интерфейс enp0s3, порт 21 — это управляющее соединение от клиента к серверу:

$ sudo iptables -t nat -A PREROUTING -i enp0s3 -p tcp --dport 21 \
> -j DNAT --to-destination 192.168.30.254 # управляющее соединение, активный и пассивный режим

И будем перенаправлять пакеты, которые приходят на внешней интерфейс enp0s3, порт 60000-60100, при работе в пассивном режиме — это соединение от клиента к серверу для передачи данных:

$ sudo iptables -t nat -A PREROUTING -i enp0s3 -p tcp --dport 60000:60100 \
> -j DNAT --to-destination 192.168.30.254:60000-60100 # для передачи данных, пассивный режим

Сохраняем новые правила, чтобы они применились после перезагрузки:

$ sudo iptables-save > /etc/iptables/rules.v4

Активный режим

В реальной ситуации FTP-клиент и маршрутизатор должны иметь белые ip-адреса. Но мы здесь моделируем ситуацию, как будто бы у них белые ip-адреса. Просто потому, что у нас маршртузатор и FTP-клиент находятся в одной сети 192.168.110.0/24 и видят друг друга. Когда FTP-клиент устанавливает управляющее соединение с FTP-сервером — он отправляет пакеты на внешний интерфейс маршрутизатора, на порт 21. А маршрутизатор отправляет эти пакеты внутрь сети 192.168.30.0/24 — на ip-адрес 192.168.30.254 FTP-сервера (DNAT, первое правило).

Вроде все готово для испытаний, файл конфигурации FTP-сервера разрешает использовать только активный режим. Пробуем из сети 192.168.110.0/24 подключиться к FTP-серверу за NAT с виртуальной машины web-server (ip-адрес 192.168.110.12).

$ ftp
> open 192.168.110.8
Connected to 192.168.110.8.
220 (vsFTPd 3.0.3)
Name (192.168.110.8:evgeniy): evgeniy
331 Please specify the password.
Password: пароль
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
> pwd
257 "/" is the current directory
> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwx---    1 0        999             0 Feb 28 13:59 share
drwx------    2 1000     1000         4096 Feb 24 14:53 test
226 Directory send OK.
> exit
221 Goodbye.

Сервер получил от клиента команду PORT и успешно ее обработал — PORT command successful. Сервер устанавливает соединение с 20 порта на указанный в команде PORT ip-адрес и порт клиента и отправляет листинг директории. Адрес клиента — это 192.168.110.12, сервер отправит данные в шлюз 192.168.30.1 (по дефолтному маршруту), маршрутизатор перебросит пакеты с интерфейса enp0s8 на enp0s3 и отправит дальше — FTP-клиенту web-server.

В активном режиме клиент сообщает серверу свой ip-адрес и порт, чтобы сервер мог установить соединение для передачи данных. Это должен быть белый ip-адрес, иначе сервер не сможет установить соединение.

Пассивный режим

Теперь изменим настройки сервера, чтобы разрешить работу в пассивном режиме:

$ sudo nano /etc/vsftpd.conf
# Слушать и обрабатывать входящие соединения
listen=YES
# Запретить доступ для анонимных пользователей
anonymous_enable=NO
# Использовать для авторизации учётные записи пользователей
local_enable=YES
# Разрешить изменения файловой системы (запись и удаление файлов)
write_enable=YES
# Маска для вновь создаваемых файлов и директорий
local_umask=022
# Запретить пользователям выходить за пределы домашнего каталога
chroot_local_user=YES
# Разрешить запись в домашний каталог (иначе будет ошибка)
allow_writeable_chroot=YES
# Показывать скрытые файлы, которые начинаются с точки
force_dot_files=NO
# При выводе списка файлов показывать локальное время
use_localtime=YES
# Записывать в /var/log/vsftpd.log данные о скачиваниях и загрузках
xferlog_enable=YES
# Включить поддержку ASCII для замены символов переноса строки
ascii_upload_enable=YES
ascii_download_enable=YES
# Использовать кодировку UTF-8 при работе с файловой системой
utf8_filesystem=YES

# Разрешить использование пассивного режима
pasv_enable=YES

# Диапазон портов для работы FTP-сервера в пассивном режиме
pasv_min_port=60000
pasv_max_port=60100
# Передавать клиенту этот ip-адрес вместо своего в ответ на PASV
pasv_address=192.168.110.8
$ sudo systemctl restart vsftpd.service

Пробуем подключиться к серверу

$ ftp
> open 192.168.110.8
Connected to 192.168.110.8.
220 (vsFTPd 3.0.3)
Name (192.168.110.8:evgeniy): evgeniy
331 Please specify the password.
Password: пароль
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
> passive
Passive mode on.
> dir
227 Entering Passive Mode (192,168,110,8,234,149).
150 Here comes the directory listing.
drwxrwx---    1 0        999             0 Feb 28 13:59 share
drwx------    2 1000     1000         4096 Feb 24 14:53 test
226 Directory send OK.
> exit
221 Goodbye.

После команды passive (PASV, пассивный режим), сервер сообщает клиенту ip-адрес 192.168.110.8 из директивы pasv_address (вместо своего 192.168.30.254) и порт — 60053 (порт вычисляется как 234*256+149=60053). А клиент устанавливает еще одно соединение с сервером — уже для передачи данных.

Тут важно то, что FTP-сервер сообщает FTP-клиенту не свой серый ip-адрес, а белый ip-адрес внешнего интерфейса шлюза (который на самом деле серый, но мы только моделируем реальную ситуацию). И сообщает порт из диапазона 60000-60100, который мы задали в настройках FTP-сервера. FTP-клиент отправляет пакеты с данными на белый ip-адрес маршрутизатора (который на самом деле серый), на порт 60053. А маршрутизатор отправляет эти пакеты внутрь сети 192.168.30.0/24 — на ip-адрес 192.168.30.254 FTP-сервера (DNAT, второе правило).

В пассивном режиме сервер сообщает клиенту свой ip-адрес и порт, чтобы клиент мог установить соединение для передачи данных. Это должен быть белый ip-адрес, иначе клиент не сможет установить соединение. Но когда сервер находится за NAT, нужно чтобы сервер отправлял не свой ip-адрес, а внешний ip-адрес шлюза. И порт отправлял не любой, а из того диапазона, который шлюз пробрасывает.

Поиск: Linux • Ubuntu • FTP • Конфигурация • Настройка • Сервер • iptables • Активный режим • Пассивный режим • Порт • NAT • Локальная сеть

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.