Linux Netfilter: Как отслеживание соединений отслеживает соединения, измененные NAT?

4

На данный момент я углубляюсь в детали архитектуры 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 изменил его.
Есть ли что-то, что я пропустил?

idlmn89
источник

Ответы:

3

Вы должны установить 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 имеет информацию для «де-SNAT» пакета, и действительно она выглядит как DNAT с первоначально входящим соединением.
  • Обычно нет необходимости искать записи conntrack более одного раза для части пакета существующего соединения, «индекс» присоединяется к пакету после поиска.

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

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

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

A.B
источник
Большое спасибо за хорошее объяснение. Это делает все это очень ясно.
idlmn89