Рейтинг:0

«Передать» общедоступный IP-адрес интерфейса другому хосту с локальным IP-адресом

флаг in

У меня есть машина (под управлением openSUSE Leap 15.3) с несколькими общедоступными IP-адресами, которая служит шлюзом для нескольких дополнительных хостов. Мне нужно, чтобы один из общедоступных IP-адресов на шлюзе действовал так, как будто он принадлежит одной из подключенных к нему машин (трафик перенаправляется прозрачно).

Мой iptables-сохранить вывод в настоящее время выглядит следующим образом (некоторые нерелевантные правила Docker включены, но конфиденциальные части отредактированы):

# Сгенерировано iptables-save v1.8.7
*фильтр
:ВВОД ПРИНЯТЬ [9747976:4527721149]
:ВПЕРЕД ПРИНЯТЬ [12638879:4423560060]
: ВЫВОД ПРИНЯТ [8913992: 2531503118]
:ДОКЕР - [0:0]
:ДОКЕР-ИЗОЛЯЦИЯ-ЭТАП-1 - [0:0]
:ДОКЕР-ИЗОЛЯЦИЯ-ЭТАП-2 - [0:0]
:ДОКЕР-ПОЛЬЗОВАТЕЛЬ - [0:0]
-A FORWARD -j DOCKER-USER
-A ВПЕРЕД -j DOCKER-ИЗОЛЯЦИЯ-ЭТАП-1
-A FORWARD -o docker0 -m conntrack --ctstate СВЯЗАННО, УСТАНОВЛЕНО -j ПРИНЯТЬ
-A ВПЕРЕД -o docker0 -j DOCKER
-A ВПЕРЕД -i docker0 ! -o docker0 -j ПРИНЯТЬ
-A ВПЕРЕД -i docker0 -o docker0 -j ПРИНЯТЬ
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j ВОЗВРАТ
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j ВОЗВРАТ
-A DOCKER-USER -j ВОЗВРАТ
СОВЕРШИТЬ
# Завершенный
# Сгенерировано iptables-save v1.8.7
*натуральный
: ПРЕДВАРИТЕЛЬНОЕ ПРИНЯТИЕ [480085:188100350]
: ВВОД ПРИНЯТЬ [62951:4107383]
: ВЫВОД ПРИНЯТ [150:9857]
:ОТПРАВКА ПРИНЯТИЯ [0:0]
:ДОКЕР - [0:0]
-A PREROUTING -d <EDACTED_FORWARDING_IP>/32 -i eth0 -j DNAT --к месту назначения 10.125.0.2
-A PREROUTING -m тип_адреса --dst-type МЕСТНЫЙ -j DOCKER
- ВЫХОД! -d 127.0.0.0/8 -m тип_адреса --dst-тип ЛОКАЛЬНЫЙ -j DOCKER
-A POSTOUTING -s 172.17.0.0/16 ! -o docker0 -j МАСКАРАД
-A ПОСТРОЙКА -j МАСКАРАД
-A ДОКЕР -i docker0 -j ВОЗВРАТ
СОВЕРШИТЬ
# Завершенный

Единственными значимыми частями этого, насколько я знаю, являются:

-A PREROUTING -d <EDACTED_FORWARDING_IP>/32 -i eth0 -j DNAT --к месту назначения 10.125.0.2
-A ПОСТРОЙКА -j МАСКАРАД

Это все еще имеет ряд проблем:

  • Когда внутренняя машина инициирует исходящее соединение, ее IP-адрес NAT используется как основной адрес шлюза, а не адрес, который я пытаюсь ему дать.
  • При получении соединений кажется, что они исходят от локального IP-адреса шлюза, а не от исходного IP-адреса (должен быть способ обойти это, поскольку это шлюз по умолчанию).
  • Если служба прослушивает 0.0.0.0 на шлюзе соединения на этот порт не перенаправляются, они идут к этой службе.

Я попытался собрать воедино ответы на некоторые другие вопросы, такие как:

Но из-за отсутствия у меня значительного опыта работы с iptables я не мог решить свои проблемы или решал некоторые только для того, чтобы другие появлялись.

Может ли кто-нибудь предложить некоторые правила для достижения этого эффекта? Или, возможно, есть способ сделать это без iptables?

Nikita Kipriyanov avatar
флаг za
Пожалуйста, приложите к вопросу полный вывод `iptables-save`. Все проблемы могут быть связаны с настройкой правил SNAT. Также опишите, как вы устанавливаете соединения, которые отображают проблемы 2 и 3 (что такое исходный адрес, что такое входящий интерфейс). Я подозреваю, что вы слишком много используете SNAT, в то время как совпадения правил DNAT можно было бы сделать менее строгими.
user9123 avatar
флаг in
@NikitaKipriyanov Я приложил вывод `iptables-save`, как и просили. Все соединения, идущие через шлюз, отображают проблемы 2 и 3. Они достигают шлюза на eth0:0, интерфейсе с IP-адресом, который я пытаюсь перенаправить. В любом случае, мое решение, вероятно, очень ошибочно из-за моего вышеупомянутого отсутствия опыта, поэтому, вероятно, лучше не основывать на нем ответы. Я в основном приложил его, чтобы показать, что я пытался сделать это сам.
Рейтинг:1
флаг za

Когда внутренняя машина инициирует исходящее соединение, ее IP-адрес NAT как основной адрес шлюза, а не адрес, который я пытаюсь дай это.

Это должно быть решено с помощью:

iptables -t nat -I POSTROUTING 1 -s 10.125.0.2 -o eth0 -j SNAT --to-source <FORWARD_IP>

Он добавлен в начало, поэтому он будет срабатывать первым, определять, что пакет исходит из этой системы, и переводить его в указанный IP-адрес, вместо того, чтобы выбирать адрес из интерфейса.

При получении соединений кажется, что они исходят от локальный IP-адрес шлюза, а не исходный IP-адрес (должен быть способ обойти так как это шлюз по умолчанию).

Эта проблема связана со следующим правилом SNAT:

iptables -t nat -A POSTROUTING -j MASQUERADE

это путь слишком широко. Вы используете SNAT все в каждый направлении, которое не является ни эффективным, ни безопасным. Он соответствует всему, включая ваши ДНК-пакеты. Сначала они транслируются по назначению в приватный адрес, затем по этому правилу их источник транслируется в адрес, выбранный из приватного интерфейса, где назначен адрес 10.x.x.x.

Я подозреваю, что вы пытаетесь охватить все общедоступные интерфейсы и все частные сети одним правилом. Хотя в Linux есть списки адресов (наборы IP-адресов), списков интерфейсов нет, поэтому невозможно сделать это правильно с помощью всего лишь одного правила.

Отфильтруйте его с помощью по меньшей мере исходный адрес (например, который адреса для исходного перевода):

iptables -t nat -A POSTROUTING -s 10.125.0.0/24 -j MASQUERADE

Если у вас несколько частных сетей, добавьте больше таких правил.

Я думаю, что лучше создать отдельное правило для каждого общедоступного интерфейса, чтобы пакеты, идущие через частный интерфейс, никогда не могли быть переведены в источник, какой бы адрес источника у них ни был, например. iptables -t nat -A POSTROUTING -s 10.125.0.0/24 -o eth0 -j MASQUERADE и так далее. Таким образом, пакеты от 10.x.x.x до 172.x.x.x тоже не будут транслироваться, и ваши сервисы в обеих сетях будут видеть IP-адреса друг друга напрямую, оставляя возможность выборочной фильтрации их в цепочке фильтров FORWARD.

Если служба прослушивает 0.0.0.0 на шлюзе, соединения на этот порт не перенаправляется, они идут к этому сервису.

И, наконец, я не совсем понимаю этот момент.Я спросил в комментарии, вы не ответили. Какие соединения, откуда, какой исходный IP?

Обработка DNAT происходит до принятия решения о маршрутизации, поэтому цепочка называется «PREROUTING». Он никогда не проверяет, прослушивает ли какой-либо локальный процесс этот порт. Единственный способ, с помощью которого локальная служба может ответить, — это передать пакету цепочку INPUT. Для этого код маршрутизации должен решить, что он предназначен для локальной машины, поэтому он должен быть либо вообще не транслирован, либо транслирован в какой-то адрес, назначенный этой системой.

Согласно текущим правилам, пакеты, отправленные из частных сетей на общедоступные IP-адреса, должны нет получить перевод, потому что они не приходят через eth0. Поэтому их должны обслуживать местные службы. Но это не зависит от того, запущена локальная служба или нет; если это не так, у вас будет «отказ в соединении».

Если вам нужно, чтобы пакеты из локальной сети на <FORWARD_IP> транслировались по одному и тому же правилу DNAT, отбросьте это -я eth0 соответствовать:

iptables -A PREROUTING -d <REDACTED_FORWARDING_IP>/32 -j DNAT --назначение 10.125.0.2

Однако я против такого широкого правила. На мой взгляд, лучше иметь как можно более жесткие правила DNAT, поэтому вам лучше фильтровать протоколы (tcp/udp) и порты сервисов, которые вы запускаете на 10.125.0.2. Если это веб-сервер, пересылайте только tcp/80 и tcp/443, например: iptables -A PREROUTING -d <EDACTED_FORWARDING_IP>/32 -p tcp -m multiport --dports 80,443 -j DNAT --назначение 10.125.0.2.

В чем проблема? Скажем, вы что-то проверяете пингом. Этот результат пинга будет зависеть от этого внутреннего состояния системы, это система, которую вы пингуете в действительности. Это смущает. Это не то поведение, которое большинство системных администраторов ожидают увидеть при проверке связи с маршрутизатором. Так что лучше оставить пинг для ответа хосту.

user9123 avatar
флаг in
Большое спасибо за подробный ответ и извините за задержку, только что получил возможность опробовать ваше решение. Я рад сообщить, что все проблемы решены, что меня очень радует, потому что это вызвало у меня значительное раздражение. Что касается части 3, после очистки правил брандмауэра и их настройки в соответствии с вашим ответом это, похоже, больше не имеет места. Я тоже был очень озадачен тем, почему это могло быть, но, возможно, мое исчерпание правил брандмауэра взяло верх надо мной, и мое тестирование было неправильным. Еще раз спасибо, вы очень помогли :D

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

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