Как перенаправить трафик из контейнера А в контейнер Б при использовании адреса внешнего интерфейса

Следуя краткой/упрощенной схеме моей установки (извините за заголовок):

      Internet ----- eth0 (1.2.3.4) --- br0 (10.0.0.1)
                                      |
                      +---------------+---------------+
                      |                               |
                veth0 (10.0.0.2)                veth1 (10.0.0.3)
                    httpd                            app

Я перенаправляю внешний трафик через обычный DNAT/SNAT (с использованием nftables) от eth0 к подходящей службе (например, к , если кто-то обращается к порту 443 на eth0). Я также могу общаться между контейнерами (например, из в ) или между контейнерами и «хостом» (через br0), если они используют внутренние IP-адреса (10.0.0.X). Все работает без включенияroute_localnet.

Кажется, я не могу заставить себя работать, если, например, контейнер пытается связаться с использованием внешнего адреса (1.2.3.4). Например, если отправляется запрос на адрес 1.2.3.4:443. То, что он использует 1.2.3.4, а не внутренний 10.0.0.2, находится вне моего контроля (я мог бы исправить некоторые случаи, добавив представление разделенного DNS, но, конечно, не все, так что оно того не стоит).

Когда я пытаюсь поговорить из контейнера с использованием внешнего адреса, например, с помощью socat (socat -4 - TCP4:1.2.3.4:443), я получаю EHOSTUNREACH («Нет маршрута к хосту»).

Я попытался добавить отдельный DNAT для этого случая, например:nft add rule ip contBr prerouting iif "br0" ip daddr 1.2.3.4 tcp dport { 80, 443 } dnat to 10.0.0.2. Идея заключалась в том, что, поскольку он меняет адрес назначения только перед маршрутизацией, он будет знать, куда отправить его во время маршрутизации, а исходный адрес остается 10.0.0.3, поэтому возврат ответа должен быть в порядке. Однако не работает. Теперь при попытке поговорить сhttpdотapp, я получаю ETIMEDOUT («Тайм-аут соединения истек»), что не должно быть для меня каким-либо фильтром, поскольку я отклоняю все, что мне не нужно, а не просто удаляю.

Не знаю, что именно искать в Интернете или здесь.

1 ответ

После полезного комментария Престона на мой вопрос я узнал, что термин/метод, который я ищу, называетсяHairpinning/Hairpin NAT( https://en.wikipedia.org/wiki/Hairpinning , https://newspaint.wordpress.com/2018/09/13/hairpin-for-lxc-containers-using-iptables/).

Причина, по которой мое единственное правилоnft add rule ip contBr prerouting iif "br0" ip daddr 1.2.3.4 tcp dport { 80, 443 } dnat to 10.0.0.2не сработало, заключается в том, что при изменении адреса назначения на правильный ответ тоже пойдет обратно к ожидаемому источнику (, 10.0.0.3); запущенное приложение будет ожидать ответа от хоста с адресом 1.2.3.4, а не 10.0.0.2 - но это произойдет из-за DNAT.

Решение - пометить соединение, и при отправке ответа обратно наappнам нужно либо добавить SNAT, либо MASQUERADE; чтобы пакет ответов получил ожидаемый адрес источника 1.2.3.4.

Что работает для меня:

      nft add rule ip contBr prerouting iif "br0" ip daddr 1.2.3.4 tcp dport { 80, 443 } ct mark set 0x61687269
nft add rule ip contBr prerouting iif "br0" ip daddr 1.2.3.4 tcp dport { 80, 443 } dnat to 10.0.0.2
nft add rule ip contBr postrouting oif "br0" ct mark 0x61687269 snat to 1.2.3.4
                         /------------------------------------\
                  /                                      \
  RESP 10.0.0.3  /              REQ  1.2.3.4:443          \
  SNAT  1.2.3.4 /               SRC 10.0.0.3               \
                |  /------------------------------------\   \
                |  |                                     \  |
Internet ----- eth0 (1.2.3.4) --- br0 (10.0.0.1)         |  |
                |  |                  |                  |  |
                |  | DNAT 10.0.0.2    |                  |  |
                |  |  SRC 10.0.0.3    |                  |  |
                |  |                  |                  |  |
  RESP 10.0.0.3 |  |  +---------------+---------------+  |  |
   SRC 10.0.0.2 |  |  |                               |  |  |
                |  |  |                               |  |  |
                |  |  |                               |  |  |
                ^  v  |                               |  ^  v
                veth0 (10.0.0.2)                veth1 (10.0.0.3)
                    httpd                            app
Другие вопросы по тегам