Рейтинг:3

Tcpdump показывает другой порт перенаправления после добавления правила REDIRECT в iptables

флаг us

Я пытаюсь направить клиентский трафик на кластер kubernetes, NodePort прослушивает 192.168.1.100.30000.

Потребности клиента сделать запрос на 192.168.1.100.8000 поэтому я добавил следующее правило REDIRECT в iptables:

iptables -t nat -I PREROUTING -p tcp --dst 192.168.1.100 --dport 8000 -j ПЕРЕНАПРАВЛЕНИЕ --на порт 30000

Затем я выдаю завиток 192.168.1.100:8000 однако в tcpdump я вижу другой порт:

# tcpdump -i lo -nnvvv хост 192.168.1.100 и порт 8000
tcpdump: прослушивание на lo, тип канала EN10MB (Ethernet), размер захвата 262144 байта
[Интерфейс: lo] 20:39:22.685968 IP (tos 0x0, ttl 64, id 20590, смещение 0, флаги [DF], proto TCP (6), длина 40)
[Интерфейс: lo] 192.168.1.100.8000 > 192.168.1.100.49816: Flags [R.], cksum 0xacda (правильно), seq 0, ack 3840205844, win 0, длина 0
[Интерфейс: lo] 20:39:37.519256 IP (tos 0x0, ttl 64, id 34221, смещение 0, флаги [DF], proto TCP (6), длина 40)

Я ожидаю, что tcpdump покажет что-то вроде

192.168.1.100.8000 > 192.168.1.100.30000

Тем не менее, он показывает и вызывает ошибку отказа в соединении, поскольку ни один процесс не указан в списке. 192.168.1.100.49816.

192.168.1.100.8000 > 192.168.1.100.49816

Я использую тестовую среду, поэтому у меня нет доступа к удаленным устройствам, поэтому я использую завиток чтобы проверить путь ПЕРЕНАПРАВЛЕНИЯ iptables.

Есть ли причина, по которой добавление правила REDIRECT приводит к тому, что tcpdump перенаправляет трафик на порт, отличный от указанного?

Редактировать:

После того, как @A.B. предложение добавило следующее правило OUTPUT:

iptables -t nat -I ВЫВОД -d 192.168.1.100 -p tcp --dport 8000 -j ПЕРЕНАПРАВЛЕНИЕ --на порт 30000

и curl продолжается дальше, количество пакетов для цепочки OUTPUT действительно увеличивается (хотя пакет цепочки PREROUTING REDIRECT не увеличился):

2 10 600 ПЕРЕНАПРАВЛЕНИЕ tcp -- * * 0.0.0.0/0 192.168.1.100 tcp dpt:8000 перенаправление портов 30000

Тем не менее, получая следующую ошибку:

# curl -vk https://192.168.1.100:8000/v1/api
* О подключении() к порту 192.168.1.100 8000 (#0)
* Попытка 192.168.1.100...
* Подключено к порту 192.168.1.100 (192.168.1.100) 8000 (#0)
* Инициализация NSS с помощью certpath: sql:/etc/pki/nssdb
* Ошибка NSS -12263 (SSL_ERROR_RX_RECORD_TOO_LONG)
* SSL получил запись, длина которой превышает максимально допустимую.
* Закрытие соединения 0
curl: (35) SSL получил запись, длина которой превышает максимально допустимую.

Кроме того, попытался добавить сеть удаленной системы, на этот раз количество пакетов PREROUTING REDIRECT CHAIN ​​увеличивается после выполнения завиток удаленной системы... (но ВЫХОДНАЯ ЦЕПЬ не увеличивается):

2 34 2040 ПЕРЕНАПРАВЛЕНИЕ tcp -- * * 0.0.0.0/0 172.16.128.1 tcp dpt:8000 перенаправление портов 30000

Ошибка:

# ip netns exec remotesystem curl -vk https://192.168.1.100:8000/v1/api
* О подключении() к порту 192.168.1.100 8000 (#0)
* Попытка 192.168.1.100...
* Время соединения истекло
* Не удалось подключиться к 192.168.1.100:8000; Время соединения истекло
* Закрытие соединения 0
curl: (7) Не удалось подключиться к 192.168.1.100:8000; Время соединения истекло
A.B avatar
флаг cl
A.B
Ваше правило не будет работать с тестом от хоста. Протестируйте еще раз из удаленной системы, а не из системы к самой себе.
tiger_groove avatar
флаг us
Почему не работает, не могли бы вы объяснить? Есть ли способ заставить его работать с хоста с петлевым интерфейсом?
A.B avatar
флаг cl
A.B
Пожалуйста, сначала добавьте контекст к вопросу: вы рассказываете, что вы делаете, но я хотел бы сначала узнать, почему вы это делаете (чтобы решить, какая практическая проблема заставила вас использовать это?)
tiger_groove avatar
флаг us
Добавил в пост
A.B avatar
флаг cl
A.B
Не могу сказать, почему объяснена причина использования локальной системы (а не удаленной), но ответ в конце концов не понадобится.
tiger_groove avatar
флаг us
Я использую тестовую среду, поэтому у меня нет доступа к удаленным устройствам, поэтому я использую `curl` для проверки пути ПЕРЕНАПРАВЛЕНИЯ iptables. Что вы имеете в виду, что ответ все равно не понадобится?
jcaron avatar
флаг co
Обратите внимание, что «192.168.1.100.8000 > 192.168.1.100.49816» не означает «перенаправление с порта 8000 на порт 49816», это означает «пакет был отправлен с порта 8000 на порт 49816», что является просто используемым портом. вашим (локальным) клиентом, а пакетом является TCP RST ("отказ в соединении"). Перед этим у вас должен быть предыдущий пакет с 49816 по 8000 (запрос на подключение, TCP SYN). И соединение отказало не потому, что на 49816 ничего не прослушивается, а на 8000.
Рейтинг:4
флаг cl
A.B

Чтобы было ясно: тест OP выполняется из системы 192.168.1.100 на себя, а не из удаленной системы, и это причина проблемы. В этом случае порт не был изменен, потому что не совпало правило NAT, в то время как он совпал бы, если бы это было сделано из удаленной системы.

На схеме ниже показано, как выполняется порядок операций над пакетом:

Поток пакетов в Netfilter и General Networking

Причина в том, как работает NAT в Linux: iptables видит пакет в нат table только для первого пакета нового потока conntrack (который, таким образом, находится в состоянии NEW).

Это правило отлично работает из удаленной системы. В этом случае первым увиденным пакетом будет входящий пакет:

на порт 8000 --> AF_PACKET (tcpdump) --> conntrack --> nat/PREROUTING (iptables REDIRECT): на порт 30000
--> решение о маршрутизации --> ... --> получение локального процесса на порту 30000

Все последующие пакеты в том же потоке будут иметь conntrack, непосредственно обрабатывающий изменение порта (или реверсию порта для ответов) и пропускающее любое правило iptables в нат таблица (как написано на схеме: нат Таблица используется только для НОВЫЙ связи). Итак, (пропустив часть ответного пакета), вместо этого следующий входящий пакет будет подвергнут этому:

на порт 8000 --> AF_PACKET (tcpdump) --> conntrack: на порт 30000
--> решение о маршрутизации --> ... --> получение локального процесса на порту 30000

Для проверки самой системы первый пакет не является входящим, а исходящим. Это происходит вместо этого, используя исходящий вот интерфейс:

локальный клиентский процесс curl --> решение о маршрутизации --> conntrack --> nat/OUTPUT (здесь нет правил)
--> проверка перенаправления --> AF_PACKET (tcpdump) --> на порт 8000

И теперь этот пакет зацикливается на вот интерфейса, он снова появляется как пакет, который больше не является первым пакетом в соединении, поэтому следует второй случай, как указано выше: только conntrack заботится о NAT и не вызывает физ/PREOUTING. За исключением того, что на предыдущем шаге не было указано выполнять какой-либо NAT:

на порт 8000 --> AF_PACKET (tcpdump) --> conntrack
--> решение о маршрутизации --> ... -->нетполучение локального процесса на порту8000

поскольку на порту 8000 ничего не прослушивается, ОС отправляет обратно TCP RST.

Чтобы это работало в локальной системе, ПЕРЕНАПРАВЛЕНИЕ правило также должно быть помещено в нат/выход цепь:

iptables -t nat -I ВЫВОД -d 192.168.1.100 -p tcp --dport 8000 -j ПЕРЕНАПРАВЛЕНИЕ --на порт 30000

Дополнительные примечания

  • если кейс предназначен для удаленного использования, не тестируйте из локальной системы: правила, пройденные тестом, не совпадают. Это делает тест не отражающим реальность.

    Просто используйте сетевое пространство имен для создания карманной удаленной системы на тот случай, если никакая другая система недоступна. Пример, который должен работать с системой, имеющей только OP физ/PREOUTING правило и делать завиток http://192.168.1.100/ (который не требует DNS):

    ip netns добавить удаленную систему
    ip link add name vethremote up type veth peer netns имя удаленной системы eth0
    IP-адрес добавить 192.0.2.1/24 dev vethremote
    ip -n адрес удаленной системы добавить 192.0.2.2/24 dev eth0
    ip -n ссылка на удаленную систему установила eth0 вверх
    ip -n маршрут удаленной системы добавить 192.168.1.100 через 192.0.2.1
    ip netns exec remotesystem curl http://192.168.1.100:8000/
    
  • tcpdump и NAT

    tcpdump происходит в AF_PACKET шаги на схеме выше: очень рано для входа и очень поздно для выхода. Это означает, что для случая удаленной системы он никогда не захватит порт 30000, даже если он работает. Для случая локальной системы, как только нат/выход добавлено правило, оно будет захватывать порт 30000.

    Просто не доверяйте слепо адресу/порту, отображаемому tcpdump при выполнении NAT: это зависит от случая и от того, где происходит захват.

tiger_groove avatar
флаг us
Большое спасибо за подробное объяснение, у меня все еще есть некоторые проблемы, и я добавил дополнительную информацию в свой пост. Кажется, что все идет дальше, чем раньше, но кажется, что что-то все еще блокирует.
A.B avatar
флаг cl
A.B
Я подозреваю, что 1/ локальный процесс является не локальным процессом, а контейнером/модулем (поскольку речь идет о Kubernetes), поэтому он также маршрутизируется или дополнительно фильтруется (=> нет связи с новым сетевым пространством имен). Я основывал свой ответ на единственном правиле iptables, присутствующем в вопросе, и ничего не было доступно. Более того, я успешно попробовал то, что я представил, прежде чем дать ответ 2/, как объяснено, счетчик в таблице nat увеличивается только для первого пакета (в состоянии NEW): он будет увеличиваться либо в nat/OUTPUT, либо в nat/PREROUTING, а не в обоих. таблица фильтров увидит все пакеты. 3/ первоначальный вопрос был не о https
A.B avatar
флаг cl
A.B
Я больше не буду менять этот ответ. Вам нужно будет создать новый вопрос с заранее заданным ВСЕМ контекстом.И желательно воспроизвести проблему, которая не будет зависеть от этого текущего Q/A (сохраните использование с правилом OUTPUT или с удаленной системой, которая, как известно, подключается)
tiger_groove avatar
флаг us
Это нормально, я создам новый вопрос. Очень ценю вашу помощь!
tiger_groove avatar
флаг us
Я создал новый вопрос, пожалуйста, дайте мне знать, если это имеет смысл для вас https://serverfault.com/questions/1097511/iptables-redirect-to-kubernetes-nodeport-causes-request-to-hang
A.B avatar
флаг cl
A.B
Ваша новая проблема связана с выполнением запроса curl к вашему API, а не с тайм-аутом, потому что я предложил метод замены удаленной системы, которая не работала в вашей конкретной настройке. iptables вообще не должен участвовать в новом вопросе. Извините, я не правильно объяснил, как должен был быть новый вопрос
tiger_groove avatar
флаг us
Это странно, потому что, когда я выполняю завиток, подобный этому `ip netns exec remotesystem curl -vk https://192.168.1.100:30000/v1/flight`, он работает нормально, и я получаю ответ, только когда я меняю его на `192.168 .1.100:8000` зависает, не совсем понимаю почему, но похоже что-то не нравится в правиле REDIRECT iptables.
A.B avatar
флаг cl
A.B
Я говорил о случае с SSL_ERROR_RX_RECORD_TOO_LONG, который не завис.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.