5

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

Я пытаюсь объяснить мою проблему с небольшим примером SNAT. В этом примере я буду игнорировать транспортный уровень, потому что я думаю, что нет необходимости понимать мою проблему. Пожалуйста, поправьте меня, если я ошибаюсь!

В локальной сети есть клиентский компьютер с IP-адресом 192.168.2.55 и NAT-шлюз с внешним IP-адресом 193.157.56.3. Теперь Клиент хочет общаться с сервером и IP-адресом 217.254.1.76 в Интернете.
Таким образом, клиент отправляет пакет с src = 192.168.2.55/dst = 217.254.1.76 на NAT-шлюз, который также является шлюзом по умолчанию. Отслеживание соединения отслеживает это новое соединение и создает два новых кортежа:

IP_CT_DIR_ORIGINAL: src = 192.168.2.55, dst = 217.254.1.76
IP_CT_DIR_REPLY: src = 217.254.1.76, dst = 192.168.2.55

IP_CT_DIR_ORIGINAL и IP_CT_DIR_REPLY являются макросами для доступа к массиву из двух кортежей.

На ловушке POSTROUTING NAT запрашивает отслеживание соединения для существующего соединения и, если это успешно, изменяет адрес источника в заголовке пакета. Он также автоматически создает правило DNAT для возврата адреса назначения ответов.
Теперь я дошел до точки моей проблемы. NAT изменяет адрес назначения в IP_CT_DIR_REPLY на свой внешний IP-адрес 193.157.56.3. Итак, кортежи выглядят так:

IP_CT_DIR_ORIGINAL: src = 192.168.2.55, dst = 217.254.1.76
IP_CT_DIR_REPLY: src = 217.254.1.76, dst = 193.157.56.3

Вот почему отслеживание соединения может отслеживать ответы в ловушке PREROUTING, поскольку для ответа существует кортеж. Но после отслеживания пакета NAT меняет адрес назначения на адрес клиента, 192.168.2.55.
Теперь мой вопрос: как отслеживание соединения может отслеживать этот пакет в хуке POSTROUTING? Нет ответного кортежа с src = 217.254.1.76/dst = 192.168.2.55, потому что NAT изменил его.
Есть ли что-то, что я пропустил?

1 ответ1

4

Вы должны установить команду conntrack обычно упакованную как conntrack или conntrack-tools, с http://conntrack-tools.netfilter.org/ . Он будет в основном отображать тот же контент, что и /proc/net/nf_conntrack но может делать больше.

Запустите conntrack в режиме событий на шлюзе NAT: conntrack -E (или вы можете выбрать conntrack -E --proto tcp --orig-port-dst 443 для ограничения HTTPS). Теперь ваш предыдущий пример с запросом HTTPS даст что-то похожее на это:

    [NEW] tcp      6 120 SYN_SENT src=192.168.2.55 dst=217.254.1.76 sport=50798 dport=443 [UNREPLIED] src=217.254.1.76 dst=193.157.56.3 sport=443 dport=50798
 [UPDATE] tcp      6 60 SYN_RECV src=192.168.2.55 dst=217.254.1.76 sport=50798 dport=443 src=217.254.1.76 dst=193.157.56.3 sport=443 dport=50798
 [UPDATE] tcp      6 432000 ESTABLISHED src=192.168.2.55 dst=217.254.1.76 sport=50798 dport=443 src=217.254.1.76 dst=193.157.56.3 sport=443 dport=50798 [ASSURED]
 [UPDATE] tcp      6 120 FIN_WAIT src=192.168.2.55 dst=217.254.1.76 sport=50798 dport=443 src=217.254.1.76 dst=193.157.56.3 sport=443 dport=50798 [ASSURED]
 [UPDATE] tcp      6 60 CLOSE_WAIT src=192.168.2.55 dst=217.254.1.76 sport=50798 dport=443 src=217.254.1.76 dst=193.157.56.3 sport=443 dport=50798 [ASSURED]
 [UPDATE] tcp      6 30 LAST_ACK src=192.168.2.55 dst=217.254.1.76 sport=50798 dport=443 src=217.254.1.76 dst=193.157.56.3 sport=443 dport=50798 [ASSURED]
 [UPDATE] tcp      6 120 TIME_WAIT src=192.168.2.55 dst=217.254.1.76 sport=50798 dport=443 src=217.254.1.76 dst=193.157.56.3 sport=443 dport=50798 [ASSURED]
[DESTROY] tcp      6 src=192.168.2.55 dst=217.254.1.76 sport=50798 dport=443 src=217.254.1.76 dst=193.157.56.3 sport=443 dport=50798 [ASSURED]

Таблица nat является особенной в том смысле, что она используется только один раз на поток *, когда создается состояние [NEW] . Все остальное короткое замыкание найденной записи conntrack. Правило SNAT в POSTROUTING не "тихо создает правило DNAT" для ответа. Он изменил запись conntrack, чтобы получить ответ dst = 193.157.56.3, и сказал netfilter «Я что-то изменил», вот и все. Все остальное (включая изменение исходного IP-адреса) обрабатывается conntrack (модули nf_conntrack, nf_conntrack_ipv4) и nat (модули nf_nat, nf_nat_ipv4 и, возможно, еще несколько здесь), а не iptables. Рассмотрим записи, являющиеся базой данных состояний соединений.

Когда ответный пакет получен, пакет, не имеющий сохраненной ассоциации, просматривается в записях conntrack (на самом деле поиск ассоциации выполняется в обоих направлениях, либо в исходной части, либо в ответной части, это не имеет значения), и совпадение найдено, поскольку запись была создана ранее. Затем упакованная информация обновляется с помощью этой связи соединения. Больше нет необходимости искать этот пакет, хотя записи больше не отображаются, даже если некоторые его свойства (источник или назначение ...) изменены, информация доступна напрямую. Некоторые из макро / встроенных функций, обрабатывающих это, определены в skbuff.h . Ищите _nfct и nfct . Пакет (он же skbuff) после поиска получает это значение в skb->_nfct .

Итак, несколько вещей, которые вы могли пропустить:

  • iptables не является сетевым фильтром. Это пользователь netfilter. nftables - другой пользователь netfilter. conntrack и nat (например, модуль nf_nat) являются частью netfilter.
  • хук POSTROUTING никогда не увидит ответный пакет, потому что соединение не NEW: таблица nat больше не вызывается для этого потока, а пакеты идентифицируются как часть этого потока.
  • большая часть обработки conntrack и nat выполняется ... conntrack и nat, а не iptables. iptables может использовать ресурсы conntrack (например: -m conntrack --ctstate ESTABLISHED) или nat (что угодно в таблице nat должно). Для приведенного выше примера, одна запись conntrack имеет информацию для «de-SNAT» пакета, и действительно она выглядит как DNAT с первоначально входящим соединением.
  • Обычно нет необходимости искать записи conntrack более одного раза для части пакета существующего соединения, "индекс" прикрепляется к пакету после поиска.

Вы можете убедиться, что таблица nat не видит другие пакеты после первого, запустив несколько раз iptables-save -c и посмотрев, как увеличиваются счетчики для правил в таблице nat: только для первого пакета.

* посмотрите на часть NAT:

Эта таблица немного отличается от таблицы `filter 'тем, что только первый пакет нового соединения будет проходить через таблицу: результат этого обхода затем применяется ко всем будущим пакетам в том же соединении.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .