Назад | Перейти на главную страницу

nft config, чтобы сделать общедоступным локальный FTP-сервер с NAT

Все будет в изолированной сети, безопасность не проблема.
eth0 подключен к «публичной» сети. Адрес назначается DHCP.
eth1 подключен к серверу "частной сети", который предоставляет ssh, telnet, "другие" и ftp.
В этом примере у этого сервера будет фиксированный IP-адрес (192.168.1.2).

На шлюзе работает debian buster и ядро ​​Linux 4.19.94

nft используется с NAT
Это моя конфигурация nft "шлюза":

table ip my_nat {
    chain my_prerouting { type nat hook prerouting priority 0;
    tcp dport { 2222 } dnat to :22 # 2222 backdoor for ssh to the gateway
    tcp dport { 1-1023 } dnat to 192.168.1.2
  }
  chain my_postrouting {
    type nat hook postrouting priority 100;
    ip daddr 192.168.1.2  masquerade
  }
}

Что мне нужно добавить, чтобы FTP работал

TL; DR

# nft add ct helper ip my_nat ftp-incoming '{ type "ftp" protocol tcp; }'
# nft add chain ip my_nat my_helpers '{ type filter hook prerouting priority 10; }'
# nft add rule ip my_nat my_helpers iif eth0 ip daddr 192.168.1.2 tcp dport 21 ct helper set ftp-incoming
# modprobe nf_nat_ftp

с более подробной информацией ниже ...

Модули поддержки протокола для проблемных протоколов

FTP - это старый протокол, который не очень удобен для брандмауэра: команды на командном канале FTP (21 / TCP) согласовывают временный порт, который будет использоваться для следующей команды передачи. Из-за этого межсетевой экран с отслеживанием состояния должен отслеживать эти команды и отвечать, чтобы временно предварительно разрешить соответствующий порт, который будет использоваться.

В Linux это обеспечивается вспомогательными модулями для конкретных протоколов, которые являются подключаемыми модулями для Conntrackподсистема Netfilter, отслеживающая соединения для NAT и межсетевого экрана с отслеживанием состояния. С FTP, когда согласование порта (в основном PORT, EPRT, PASV или EPSV) для следующей передачи было замечено на командном порту FTP, помощник добавляет кратковременную запись в специальную Conntrack стол ( ожидание conntrack table), который будет ждать следующего связанного и ожидаемого подключения к данным.

В моем ответе используется современная «безопасная» обработка, описанная в этот блог о iptables для общих слов и в столы вики и man nft для обработки в столы который отличается от iptables.

Безопасное использование правил helper и nftables

Ядро Linux 4.7+ (включая 4.19) по умолчанию использует безопасный подход: наличие загруженного вспомогательного модуля (здесь FTP) больше не позволит ему отслеживать все пакеты, имеющие TCP-порт источника или назначения 21, до тех пор, пока не будет определен конкретный столы (или iptables) операторы говорят ему, в каком (ограниченном) случае он должен отслеживать. Это позволяет избежать ненужного использования ЦП и позволяет в любой момент изменить порт (ы) FTP для отслеживания, просто изменив несколько правил (или наборов).

Первая часть - объявить потоки, которые могут вызвать отслеживание. В столы чем в iptables. Здесь он объявлен с использованием ct helper объект с состоянием, и фильтры для его активации должны быть выполнены после Conntrack (пока iptables требует действий, выполненных ранее). man nft говорит:

В отличие от iptables, назначение помощника должно выполняться после завершения поиска в conntrack, например, с приоритетом ловушки по умолчанию 0.

nft add ct helper ip my_nat ftp-incoming '{ type "ftp" protocol tcp; }'

nft add chain ip my_nat my_helpers '{ type filter hook prerouting priority 10; }'
nft add rule ip my_nat my_helpers iif eth0 ip daddr 192.168.1.2 tcp dport 21 ct helper set ftp-incoming

Я выбрал ту же таблицу, но ее можно было создать в другой таблице, если объявление объекта с сохранением состояния и ссылающееся на него правило находятся в одной таблице.

Конечно, можно выбрать менее строгие правила. Замена последнего правила следующим правилом будет иметь тот же эффект, что и унаследованный режим:

nft add rule ip my_nat my_helpers tcp dport 21 ct helper set ftp-incoming

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

sysctl -w net.netfilter.nf_conntrack_helper=1

Обеспечение nf_nat_ftp загружен

Модуль ядра nf_conntrack_ftp автоматически загружается с зависимостью, созданной ct helper ... type "ftp". Это не так для nf_nat_ftp, однако необходимо также включить изменение пакетов в командном порту, когда NAT выполняется на портах потока данных.

Например, чтобы иметь модуль nf_nat_ftp тянул всякий раз, когда nf_conntrack_ftp загружен, файл /etc/modprobe.d/local-nat-ftp.conf можно добавить с этим контентом:

install nf_conntrack_ftp /sbin/modprobe --ignore-install nf_conntrack_ftp; /sbin/modprobe --ignore-install nf_nat_ftp

или вместо этого просто добавьте, например, /etc/modules-load.d/local-nat-ftp.conf с участием:

nf_nat_ftp

В любом случае, сейчас нужно выполнить эту команду, чтобы убедиться, что она загружена:

modprobe nf_nat_ftp

О межсетевом экране

Вот дополнительное примечание по брандмауэру. Также могут быть правила брандмауэра с некоторыми ограничениями вместо разрешения любого нового потока, помеченного как Связанный по Conntrack.

Например, хотя вспомогательный модуль FTP обрабатывает как пассивный, так и активный режимы, если по какой-то причине кто-то хочет разрешить только пассивный режим (с подключением данных от клиента к серверу), а не «активный» ftp (подключение данных от порта источника сервера 20 к client) можно, например, использовать эти правила в части набора правил брандмауэра вместо обычных ct state established,related accept:

ct state established accept
ct state related ct helper "ftp" iif eth0 oif eth1 tcp sport 1024-65535 accept
ct state related ct helper "ftp" drop
ct state related accept 

Другой вид Связанный потоки, не связанные с FTP, остаются принятыми (или могут быть дополнительно разделены отдельно)


Пример обращения помощником

Здесь (в смоделированной среде) два Conntrack списки событий, измеренных на ожидание стол и Conntrack таблица с правилами OP + дополнительные правила выше с интернет-клиентом 203.0.113.101, выполняющим FTP в пассивном режиме с общедоступным IP-адресом маршрутизатора 192.0.2.2 и с помощью команды LIST после входа в систему:

# conntrack -E expect
    [NEW] 300 proto=6 src=203.0.113.101 dst=192.0.2.2 sport=0 dport=37157 mask-src=0.0.0.0 mask-dst=0.0.0.0 sport=0 dport=65535 master-src=203.0.113.101 master-dst=192.0.2.2 sport=50774 dport=21 class=0 helper=ftp
[DESTROY] 300 proto=6 src=203.0.113.101 dst=192.0.2.2 sport=0 dport=37157 mask-src=0.0.0.0 mask-dst=0.0.0.0 sport=0 dport=65535 master-src=203.0.113.101 master-dst=192.0.2.2 sport=50774 dport=21 class=0 helper=ftp

одновременно:

# conntrack -E
    [NEW] tcp      6 120 SYN_SENT src=203.0.113.101 dst=192.0.2.2 sport=50774 dport=21 [UNREPLIED] src=192.168.1.2 dst=192.168.1.1 sport=21 dport=50774 helper=ftp
 [UPDATE] tcp      6 60 SYN_RECV src=203.0.113.101 dst=192.0.2.2 sport=50774 dport=21 src=192.168.1.2 dst=192.168.1.1 sport=21 dport=50774 helper=ftp
 [UPDATE] tcp      6 432000 ESTABLISHED src=203.0.113.101 dst=192.0.2.2 sport=50774 dport=21 src=192.168.1.2 dst=192.168.1.1 sport=21 dport=50774 [ASSURED] helper=ftp
    [NEW] tcp      6 120 SYN_SENT src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 [UNREPLIED] src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835
 [UPDATE] tcp      6 60 SYN_RECV src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835
 [UPDATE] tcp      6 432000 ESTABLISHED src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]
 [UPDATE] tcp      6 120 FIN_WAIT src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]
 [UPDATE] tcp      6 30 LAST_ACK src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]
 [UPDATE] tcp      6 120 TIME_WAIT src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]

Начало ожидания proto=6 src=203.0.113.101 dst=192.0.2.2 sport=0 dport=37157 сообщает, что следующее TCP-соединение от 203.0.113.101:* до 192.0.2.2:37157 будет связано (состояние Связанный) с FTP-соединением. Непосредственно не виден, но поскольку вспомогательный модуль NAT FTP также загружен, фактические данные, отправленные сервером в ответ на команду PASV / EPSV, были перехвачены и переведены, поэтому клиент подключается к 192.0.2.2 вместо 192.168.1.2, который имел бы конечно провалился на клиенте.

Несмотря на второй поток (второй НОВАЯ line), не имеющий явного правила в my_prerouting, он был успешно подключен к серверу за маршрутизатором.


Ноты

  • если порт управления FTP зашифрован (AUTH TLS ...), то вспомогательный модуль больше не может отслеживать согласованный порт, и это не может работать. Приходится прибегать к настройке зарезервированного диапазона портов как в конфигурации FTP-сервера, так и в брандмауэре / NAT-маршрутизаторе, а также настраивать сервер так, чтобы он отправлял правильный (общедоступный) IP-адрес при согласовании вместо своего собственного. И активный режим FTP не может быть использован, если у сервера нет маршрута к Интернету (как, похоже, здесь).

  • придирки: приоритет предварительной маршрутизации 10 гарантирует, что даже для ядер <4.18 NAT уже выполняется для новых потоков (OP выбрал приоритет предварительной маршрутизации обработчика 0 вместо обычного -100, поскольку это редко имеет значение в nftables), поэтому использование daddr 192.168.1.2 возможно. Если приоритет был 0 (или ниже 0), возможно (не проверено) правило увидит, что первый пакет все еще не имеет NAT с общедоступным IP-адресом назначения, но перехватит следующие пакеты того же потока, поскольку они обрабатываются непосредственно Conntrack при приоритете -200. Лучше оставайтесь в безопасности и используйте 10. На самом деле это не актуально, начиная с ядра 4.18 (см. совершить ссылка в этот ожидающий патч), где приоритет NAT важен только для сравнения между несколькими цепочками nat (и позволяет смешивать NAT в устаревших iptables и nftables).