OpenBSD PF - Проблемы с FTP [FAQ PF - На главную]



Режимы FTP

FTP - это протокол, который восходит к тому времени, когда интернет представлял из себя еще небольшую дружную сеть компьютеров, где все друг друга знали. В те времена не было необходимости в фильтрации трафика или строгой безопасности. FTP не предназначен для фильтрации, не предусмотренна работа через Firewall или через NAT.

FTP можно пользоваться одним из двух способов: пассивным или активным. Как правило, выбор активного или пассивного делается для того, чтобы определить, есть ли у кого-то проблем с firewall'ом.

При активном FTP, когда пользователь подключается к удаленному FTP-серверу и запрашивает информацию или файл, FTP-сервер устанавливает новое соединение с клиентом для передачи запрошенных данных. Это называется data connection (подключением к данным). Для начала FTP-клиент выбирает случайный порт для приема соединения, для передачи данных. Клиент отправляет номер выбранного порта FTP-серверу и ожидает входящее соединение на нем. Затем FTP-сервер создает новое соединение на этот порт клиента и начинает передачу данных. Это проблема для пользователей, пытающихся получить доступ к FTP-серверам из-за шлюза NAT. Из-за того, что используется NAT, FTP-сервер создает новое соединение к внешнему адресу, который принадлежит не клиенту, а NAT, и порту, который выбрал клиент для передачи данных. NAT получит запрос, но, поскольку у него нет информации о сопоставлении в своей таблице состояний о выбранном клиентом порте, он отбросит пакет от FTP-сервера, т.е. ответный пакет от сервера клиент не получит.

В пассивном режиме FTP (режим, используемый по умолчанию в клиенте ftp(1) в OpenBSD), клиент запрашивает, чтобы сервер выбирал случайный порт для передачи данных. Сервер сообщает клиенту выбранный порт, а клиент подключается к этому порту. К сожалению, это не всегда возможно или желательно из-за возможностей Firewall-a перед FTP-сервером, блокирующего входящие подключение для передачи данных. Чтобы использовать активный режим FTP, используйте флаг -A для ftp, или установите для пассивного режима значение "off", введя команду «passive off» в приглашении "ftp>".

FTP-клиент за Firewall

Как указывалось ранее, у FTP есть проблемы с работой через NAT и Firewall.

PF предлагает решение этой ситуации, перенаправляя FTP-трафик, через FTP прокси-сервер. Этот процесс используется, чтобы перенаправлять FTP-трафик через NAT firewall, путем активного добавления необходимых правил в PF и удаления их, когда это делается через систему привязки. FTP прокси-сервер, используемый PF: ftp-proxy(8).

Чтобы активировать его, используйте что-то подобное в начале файла с правилами pf.conf:

pass in quick on $int_if inet proto tcp to port 21 divert-to 127.0.0.1 port 8021
Это перенаправляет FTP-трафик от клиентов к программе ftp-proxy, которая прослушивает порт 8021 сервера.

Также нужна привязка/якорь/anchor в разделе правил:

anchor "ftp-proxy/*"
Прокси-сервер должен быть запущен, и добавлен в автозапуск в OpenBSD.
# rcctl enable ftpproxy
# rcctl start  ftpproxy
Для поддержки подключений в активном режиме от определенных (суетливых) клиентов, может потребоваться флаг -r.

PF "самозащита" FTP-сервера

В этом случае PF работает на самом FTP-сервере, а не на отдельном компьютере с firewall-ом. При обслуживании пассивного соединения, FTP будет использовать случайно выбранный высокий TCP порт для входящих соединений. По умолчанию сервер ftpd(8) в OpenBSD использует диапазон портов от 49152 до 65535. Очевидно, они должны быть пропущены через правила фильтрации вместе с портом 21 (порт управления FTP):
pass in on egress proto tcp to port 21
pass in on egress proto tcp to port > 49151
При желании этот диапазон портов можно расширить. В случае ftpd(8), это выполняется с использованием переменных sysctl(8) net.inet.ip.porthifirst и net.inet.ip.porthilast.

FTP-сервер защищен внешним Firewall c NAT

В этом случае, firewall должен дополнительно перенаправлять трафик на FTP-сервер, чтобы не блокировать требуемые порты.

ftp-proxy может быть запущен в режиме, который заставляет его перенаправлять все FTP-соединения на конкретный FTP-сервер. Прокси-сервер будет настроен на прослушивание порта 21 firewall-а, и перенаправить все подключения к внутреннему серверу.

# rcctl set ftpproxy flags -R 10.10.10.1 -p 21 -b 192.168.0.1
Здесь 10.10.10.1 - это IP-адрес фактического FTP-сервера, 21 - это порт ftp-proxy, который будет прослушивать, а 192.168.0.1 - это адрес на firewall, к которому будет привязан прокси.

Теперь о правилах pf.conf:

ext_ip = "192.168.0.1"
ftp_ip = "10.10.10.1"
match out on egress inet from $int_if nat-to (egress)
anchor "ftp-proxy/*"
pass in  on  egress inet proto tcp to $ext_ip port 21
pass out on $int_if inet proto tcp to $ftp_ip port 21 user _ftp_proxy
Здесь входящее соединение на порт 21 разрешено на внешнем интерфейсе, а также соответствующее исходящее соединение с FTP-сервером. Дополнение user _ftp_proxy к правилу исходящего трафика гарантирует, что разрешены будут только соединения, инициированные ftp-proxy.

Дополнительная информация о FTP

Более подробную информацию о фильтрации FTP и о том, как работает FTP в целом, можно найти в этой whitepaper (технической документации).

Проксирование TFTP

Trivial File Transfer Protocol (TFTP) страдает от того же, от чего и FTP, когда дело доходит до работы через firewall. К счастью, у PF есть вспомогательный прокси для TFTP, который называется tftp-proxy(8).

tftp-proxy настраивается почти так же, как ftp-proxy. Смотри FTP-клиент за Firewall-ом.

match out on egress inet from $int_if nat-to (egress)
anchor "tftp-proxy/*"
pass in  quick on $int_if inet proto udp from $lan to port tftp \
    divert-to 127.0.0.1 port 6969
pass out quick on $ext_if inet proto udp from $lan to port tftp \
    group _tftp_proxy divert-reply
Приведенные выше правила разрешают исходящий трафик TFTP из внутренней сети к TFTP-серверу во внешней сети.

Последний шаг - добавить в автозапуск и запустить tftp-proxy.

# rcctl enable tftpproxy
# rcctl start  tftpproxy