iptables DNAT от обратной связи
Я пытаюсь понять ограничения использования iptables DNAT с адресами обратной связи. Предположим, у нас есть приложение, которое может подключаться только к 127.0.0.1; очевидное решение для работы сервера и клиента на разных узлах заключается в использовании NAT следующим образом:
Убедитесь, что все исходящие пакеты имеют IP-адрес главного клиента:
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source <CLIENT_IP>
Теперь давайте попробуем обмануть клиента и DNAT соединиться с внешним миром:
iptables -t nat -A OUTPUT -d 127.0.0.1/32 -p tcp -m tcp --dport <SERVICE_PORT> -j DNAT --to-destination <SERVER_IP>
К сожалению, это просто не работает при попытке подключиться к 127.0.0.1:<SERVICE_PORT>
программа просто висит connect
Системный вызов. Интересно то, что я не вижу никаких пакетов SYN ни на каких интерфейсах (tcpdump -qn -i any port <SERVICE_PORT>
), однако я вижу увеличение счетчиков пакетов при просмотре статистики iptables (iptables -nvL -t nat
).
Погуглил решение Я нашел вариант сборки ядра CONFIG_IP_NF_NAT_LOCAL
, который использовался в ядрах 2.6.0-2.6.10 для решения проблемы использования NAT с локально созданными соединениями. К сожалению, текущее дерево ядра git содержит информацию для версий 2.6.11 и новее, поэтому я зашел в тупик.
Глядя дальше, я наткнулся на эту тему, касающуюся исправлений некоторых DNAT по проблемам обратной петли в 2.6.11; один из патчей удаляет CONFIG_IP_NF_NAT_LOCAL
опция сборки и включает код безоговорочно ( вот фактическая разница).
Однако текущее состояние этой проблемы мне совершенно неясно. Я хотел бы найти некоторые объяснения или ссылки, доказывающие, что это ошибка ядра или не очень хорошо документированная функция. Я знаю, что сетевая маршрутизация 127.0.0.0/8 обрабатывается ядром особым образом, но из документации iptables ясно, что цепочка OUTPUT таблицы nat - это единственное место, которое имеет смысл для правил такого типа и не содержит никаких исключений или любые заметки о сети 127/8.
Пожалуйста, воздержитесь от советов некоторых обходных путей со сторонними инструментами, у меня уже есть некоторые, я просто хочу получить некоторое объяснение, почему эта точная конфигурация не работает и почему она не должна работать. Любые примеры того, как этот DNAT может быть сделан с любыми другими правилами iptables, приветствуются.
Приведенная выше конфигурация была протестирована на Debian squeeze и wheezy с ядрами 2.6.32, 3.1.0, 3.2.0.
1 ответ
Копание немного глубже показывает некоторое подтверждение того, что вышеупомянутое поведение абсолютно правильно.
Согласно RFC 5735, сеть 127.0.0.0/8 не должна маршрутизироваться вне самого хоста:
127.0.0.0/8 - этот блок назначен для использования в качестве петлевого адреса узла Интернета. Датаграмма, отправленная протоколом более высокого уровня на адрес в любом месте этого блока, возвращается обратно в хост. Обычно это реализуется с использованием только 127.0.0.1/32 для обратной петли. Как описано в [RFC1122], раздел 3.2.1.3, адреса внутри всего блока 127.0.0.0/8 нигде законно не появляются ни в одной сети.
RFC 1700, стр. 5 также утверждает, что эти адреса "никогда не должны появляться вне хоста".
RFC 1812, раздел 5.3.7 Марсианская фильтрация адресов заявляет, что "маршрутизатору НЕ СЛЕДУЕТ пересылать, кроме как через петлевой интерфейс, любой пакет, имеющий адрес источника в сети 127", что в точности соответствует моему случаю.
Что касается этих ссылок, я предполагаю, что случай из первого поста действительно является особенностью, а противоположное поведение будет нарушением стандартов.