Теперь усложним задачу: попробуем «прокинуть порт» внутрь. Или другими словами, анонсировать какой-нибудь сервис наружу МСЭ. Для этого нам понадобится 2 конструкции:
1. Трансляция адреса назначения при обращении снаружи
2. Разрешение инициирования трафика снаружи внутрь МСЭ
Как уже отмечал выше, на Vyatta реализовано 2 основных вида сетевых трансляций: трансляция адреса источника, когда идём наружу МСЭ (inside), и трансляция адреса назначения, когда идём снаружи МСЭ (destination). Разница в том, с какой стороны можно инициировать сессии. В первом случае – изнутри, а во втором – снаружи МСЭ. При этом нам нет необходимости описывать ответные пакеты: при прохождении первого пакета мы запоминаем (кэшируем) трансляцию и ответные пакеты уходят, используя эту запись в кэше.
Итак, для примера попробуем анонсировать наружу web-сервер 10.4.4.100 по порту 80 адреса интерфейса.
Опишем трансляцию адреса назначения. Для этого надо указать, на какой интерфейс мы обращаемся (eth0), на какой адрес и порт, и какой адрес и порт ему соответствует внутри МСЭ:
[edit]
edit service nat rule 10
[edit service nat rule 10]
set type destination
[edit service nat rule 10]
set protocol tcp
[edit service nat rule 10]
set inbound-interface eth0
[edit service nat rule 10]
set destination address 192.168.4.1
[edit service nat rule 10]
set destination port 80
[edit service nat rule 10]
set inside-address address 10.4.4.100
[edit service nat rule 10]
set inside-address port 80
[edit service nat rule 10]
commit
Вот такая трансляция получится:
nat {
rule 10 {
destination {
address 192.168.4.1
port 80
}
inbound-interface eth0
inside-address {
address 10.4.4.100
port 80
}
protocol tcp
type destination
}
К сожалению, я не нашел способа статически связывать порт адреса интерфейса, если этот самый адрес заранее неизвестен (например, получен по DHCP). Т.е. надо явно указывать глобальный адрес сервера.
Теперь надо пропустить снаружи трафик, направленный на 80 порт нашего сервера. Напомню, что сначала отработает трансляция от назначения, и только потом правило МСЭ. Поэтому описывая разрешение не ошибитесь, указывая адрес сервера: это должен быть уже частный адрес (10.4.4.100)
[edit]
set firewall name FROMOUT rule 50
[set firewall name FROMOUT rule 50]
set protocol tcp
[set firewall name FROMOUT rule 50]
set action accept
[set firewall name FROMOUT rule 50]
set state new enable
[set firewall name FROMOUT rule 50]
set destination address 10.4.4.100
[set firewall name FROMOUT rule 50]
set destination port 80
[set firewall name FROMOUT rule 50]
commit
Замечание: если не указывать явно адреса источника, то считаются все адреса источника. Аналогично записи
set source address 0.0.0.0/0
А вот теперь мы добрались до самого интересного: а как vyatta обрабатывает сложные протоколы? Те, которым необходимо нечто большее, чем одна TCP/UDP сессия?
Попробуем на примере FTP разрешить клиентам из внутренней сети 10.4.4.0/24 ходить на внешние сервера.
Сложность заключается в том, что когда клиенты обращаются наружу МСЭ по FTP, то в рамках первичной сессии (на 21 порт ТСР) идёт согласование динамических портов для передачи данных (команда PORT в active FTP). В любом случае, если не используется режим passive (это когда обе сессии: служебную и для данных, открывает клиент из-под МСЭ), то сессия для данных открывается cнаружи внутрь МСЭ. Но наш МСЭ не пропускает эту новую сессию (мы же настроили, что только установленные сессии пройдут).
Вторая сложность заключается в том, что мы используем динамическую РАТ трансляцию в адрес интерфейса и сервер ответит на адрес интерфейса. Надо дополнительно создать трансляцию снаружи внутрь (destination) для новой сессии. А портов мы не знаем 🙂
Остается надеяться на ум разработчиков. Попробуем применить их тайное оружие: состояние сессии «related». Заявлено, что это волшебное слово снимет все эти препоны.
Если размышлять как настройщик cisco, я бы написал правило, которое подслушивает порт TCP/21 и открывает порт, передаваемый командой PORT протокола FTP, а заодно создает DNAT трансляцию. Однако, такой подход здесь не работает. Здесь нужно во внешнем правиле к состоянию сессии «established» добавить состояние «related», тогда снаружи пройдут не только установленные, но новые сессии сложных протоколов.
Итак, добавляем:
[edit]
edit firewall name FROMOUT rule 10
[edit firewall name FROMOUT rule 10]
set state related enable
[edit firewall name FROMOUT rule 10]
commit
и о чудо: трафик пошел 🙂
Оставим пока за скобками список этих сложных протоколов. Этими изысканиями займусь позже.
Теперь попробуем анонсировать наружу FTP с нашего сервера 10.4.4.100
Ясно, что для этого нам придётся анонсировать служебный порт ТСР/21 (ровно так же, как мы это сделали для порта 80). Также, надо будет сделать разрешение на инициирование сессии на 21 порт во входящем фильтре. Если используется активный режим, то сессия для передачи данных откроется изнутри МСЭ, создастся сессия SNAT и ничего специально разрешать не надо (почему-то возникла проблема при работе FTP из командной строки Windows. TotalCommander отработал нормально). Если же используется пассивный режим, то все за нас сделает то же волшебное слово related в правиле межсетевого экрана, а трансляцию DNAT vyatta сделает для вас сама.
Замечание: надо следить, чтобы в активном режиме сессия на передачу данных получала тот же адрес, что и служебная сессия. Иначе связи не будет.
Метки: vyatta, анонс сервиса, сложные протоколы
Опубликовано: Vyatta
«К сожалению, я не нашел способа статически связывать порт адреса интерфейса, если этот самый адрес заранее неизвестен (например, получен по DHCP). Т.е. надо явно указывать глобальный адрес сервера»
Всё оказалось просто:
ethernet eth0 {
address dhcp
description [—OUTSIDE_INTERFACE—]
rule 20 {
destination {
port 80
}
inbound-interface eth0
inside-address {
address 10.4.4.100
}
protocol tcp
type destination
Т.е. если мы не указываем глобальный IP — то по идее порт прокидывается для всех IP, которые есть на интерфейсе Vyatta (а это как раз адрес, полученный по DHCP).
Если порт «сохраняется» — то команду port для inside тоже можно не указывать.
Проверил, потому и пишу…