TechNoir писал(а):DNAT: Пакет идет от клиента находящего в интернете. Что происходит с пакетом. В нем достаточно подменить только destination адрес.
В обратном пакете DNAT должен вернуть только измененный адрес и ВСЕ!!!
Не совсем так... Можно подменять и порт
Вот что пишут в man iptables:
Код: Выделить всё
--to-destination ipaddr[-ipaddr][:port-port]
Llama писал(а):В обратном пакете должен быть измене source address. Т.е. должен быть сделан фактически SNAT. Насколько я знаю, DNAT _не_ отслеживает соединение, соответсвенно - если пакет приходит из другой ip-сети то работать не будет без SNAT.
Судя по тому что:
Код: Выделить всё
CONFIG_IP_NF_CONNTRACK
This is required to do Masquerading or other kinds of Network Address Translation (except for Fast NAT).
DNAT все-таки отслеживает соединение. И проблема как раз таки обратная: доступ из другой сети будет, а вот из той же - нет. Привер из iptables howto:
iptables -t nat -A PREROUTING --dst $INET_IP -p tcp --dport 80 -j DNAT --to-destination $HTTP_IP
В соответствии с этим правилом, все пакеты, поступающие на 80-й порт адреса $INET_IP перенаправляются на наш внутренний WEB-сервер. Если теперь обратиться к WEB-серверу из Интернет, то все будет работать прекрасно. Но что же произойдет, если попробовать соединиться с ним из локальной сети? Соединение просто не установится. Давайте посмотрим как маршрутизируются пакеты, идущие из Интернет на наш WEB-сервер. Для простоты изложения примем адрес клиента в Интернет равным $EXT_BOX.
1.Пакет покидает клиентский узел с адресом $EXT_BOX и направляется на $INET_IP
2.Пакет приходит на наш брандмауэр.
3.Брандмауэр, в соответствии с вышеприведенным правилом, подменяет адрес назначения и передает его дальше, в другие цепочки.
4.Пакет передается на $HTTP_IP.
5.Пакет поступает на HTTP сервер и сервер передает ответ через брандмауэр, если в таблице маршрутизации он обозначен как шлюз для $EXT_BOX. Как правило, он назначается шлюзом по-умолчанию для HTTP сервера.
6.Брандмауэр производит обратную подстановку адреса в пакете, теперь все выглядит так, как будто бы пакет был сформирован на брандмауэре.
7.Пакет передается клиенту $EXT_BOX.
А теперь посмотрим, что произойдет, если запрос посылается с узла, расположенного в той же локальной сети. Для простоты изложения примем адрес клиента в локальной сети равным $LAN_BOX.
1.Пакет покидает $LAN_BOX.
2.Поступает на брандмауэр.
3.Производится подстановка адреса назначения, однако адрес отправителя не подменяется, т.е. исходный адрес остается в пакете без изменения.
4.Пакет покидает брандмауэр и отправляется на HTTP сервер.
5.HTTP сервер, готовясь к отправке ответа, обнаруживает, что клиент находится в локальной сети (поскольку пакет запроса содержал оригинальный IP адрес, который теперь превратился в адрес назначения) и поэтому отправляет пакет непосредственно на $LAN_BOX.
6.Пакет поступает на $LAN_BOX. Клиент "путается", поскольку ответ пришел не с того узла, на который отправлялся запрос. Поэтому клиент "сбрасывает" пакет ответа и продолжает ждать "настоящий" ответ.
Проблема решается довольно просто с помощью SNAT. Ниже приводится правило, которое выполняет эту функцию. Это правило вынуждает HTTP сервер передавать ответы на наш брандмауэр, которые затем будут переданы клиенту.
iptables -t nat -A POSTROUTING -p tcp --dst $HTTP_IP --dport 80 -j SNAT --to-source $LAN_IP
цепочка POSTROUTING обрабатывается самой последней и к этому моменту пакет уже прошел процедуру преобразования DNAT, поэтому критерий строится на базе адреса назначения $HTTP_IP.