Назад | Перейти на главную страницу

Пакеты, передающие правило DNAT на локальный IP, исчезают

На прошлой неделе я столкнулся с довольно странной проблемой, и мне интересно, есть ли у кого-нибудь совет продолжить отладку. У нас есть машина с двумя интерфейсами Ethernet, один из которых служит нашим интернет-соединением (скажем, IP А), а другой имеет подсеть трафика нашей сети (которая включает IP А) отзеркалили через наш роутер; этот интерфейс имеет IP B. У нас есть приложение, которое принимает трафик от зеркального интерфейса и фильтрует его, сбрасывая некоторые пакеты в интерфейсы tun (давайте упростим и скажем здесь только tun0, хотя в реальном приложении у нас есть по одному для каждого ядра, на котором выполняется фильтрация). Затем мы пытаемся вернуть пакеты DNAT, полученные на tun0, на IP. B в порту C чтобы другое приложение могло их принять.

У нас есть правило, установленное в цепочке PREROUTING таблицы nat для выполнения DNAT, как показано ниже:

iptables -t nat -I PREROUTING -p tcp -i tun0 -j DNAT --to <B>:<C>

Я подтвердил, что это правило выполняется, как при трассировке пакетов, так и при просмотре номеров пакетов из iptables. Однако после этого пакеты, кажется, исчезают - я ожидал, что они в следующий раз войдут в цепочку INPUT как IP B это местный адрес (я подтвердил ip route get <B> относится к lo), однако пакеты не попадают во ВХОД или Цепочки FORWARD, что наводит меня на мысль, что они не учитываются при выборе маршрута. Все, что я видел в Интернете, похоже, указывает на то, что это проблема с rp_filter, forwarding или route_localnet, однако я подтвердил все следующее:

net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.tun0.rp_filter = 0
net.ipv4.conf.lo.rp_filter = 0
net.ipv4.ip_forward = 1
net.ipv4.conf.tun0.forwarding = 1
net.ipv4.conf.lo.forwarding = 1
net.ipv4.conf.all.route_localnet = 1
net.ipv4.conf.tun0.route_localnet = 1
net.ipv4.conf.lo.route_localnet = 1

Когда я включаю марсианский каротаж, я вижу следующее:

IPv4: martian source <B> from <A>, on dev tun0

Что, кажется, подтверждает, что DNAT имеет некоторые эффект, но с учетом этого rp_filter=0 это меня смущает.

На данный момент у меня нет идей о том, как продолжить отладку, поскольку пакеты, кажется, исчезают с лица земли после шага DNAT, кроме марсианских журналов, и был бы очень признателен за некоторые рекомендации! Спасибо!

Пакеты, которые подавались на мой зеркальный интерфейс, были с моей локальной машины, и я не знал, что любые пакеты, которые попадут в цепочку INPUT с локальным исходным IP-адресом, будут отброшены. Тот факт, что пакет прошел к нашему маршрутизатору и обратно к нашему другому интерфейсу Ethernet, сделал это менее очевидным (например, «что сделало бы этот компьютер отличным от других в нашей сети, если бы они все прошли через маршрутизатор»), но то же самое исходный IP-адрес (логически) все еще сохраняется. Такое поведение имеет смысл для «нормального» варианта использования, хотя я не смог найти его описанного в какой-либо внешней документации по этому вопросу (это могло быть из-за недостатка знаний, но я могу обещать, что это не было недостатком усилий) ; Я нашел это только во время чтения Исходный код ядра Linux:

/*
 *  NOTE. We drop all the packets that has local source
 *  addresses, because every properly looped back packet
 *  must have correct destination already attached by output routine.
 *

Поскольку мы выгружали пакеты непосредственно на интерфейс tun и сохраняли исходный IP-адрес источника, это противоречит ожиданиям ядра от «нормальной» ситуации, и оно тихо роняет пакет, что затрудняет поиск причины. Также выясняется (из прочтения другого раздела того же файла), что этот марсианский журнал не обязательно указывает на то, что пакет был заблокирован по этой причине - только то, что это было обнаружен как марсианин. В дальнейшем наше решение, вероятно, будет либо «не делать этого» (делать запросы с той же машины), либо найти способ перезаписать исходный IP-адрес до выполнения цепочки INPUT, как обычный шаг SNAT в POSTROUTING цепь будет слишком поздно.