Вопрос или проблема
Я ищу решение, при котором TCP-пакеты должны быть перенаправлены или вещаться на несколько адресатов. С помощью nftables мне удалось перенаправить пакеты на другой компьютер с помощью следующего правила:
nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
nft add rule ip nat prerouting tcp dport 9000 dnat to 172.19.0.2
nft add rule ip nat postrouting ip daddr 172.19.0.1 masquerade
Я не уверен, как перенаправить тот же пакет на другие адресаты, например, 172.19.0.2. Я пробовал правило nft add rule nat prerouting dport 9000 dup to 172.20.0.2
разными способами, но это не сработало. Может кто-нибудь поможет с этим? Или есть какой-либо аналогичный инструмент в Linux, который я могу использовать для достижения того же результата?
Пометка: я пробовал использовать socat в сочетании с tee. Однако я не рассматриваю это как вариант, так как использование опции fork создает множество дочерних процессов, если один из адресатов не отвечает.
Ответ или решение
Ваша задача заключается в пересылке TCP пакетов на несколько конечных адресов с использованием nftables. Перед тем как углубиться в решение, необходимо понять, что nftables является мощным инструментом для работы с сетевыми пакетами на уровне ядра Linux и предлагает значительные возможности для трансляции сетевых адресов (NAT) и управления трафиком. Однако, существуют ограничения относительно расщепления или «размножения» одного и того же пакета для передачи на несколько адресатов непосредственно через nftables.
Теория
nftables — это подсистема Linux, заменяющая iptables для конфигурации и управления сетевым трафиком. Оно позволяет более гибко создавать правила управления трафиком, обеспечивая при этом улучшенную производительность и более читабельный синтаксис конфигураций.
Основные операции, такие как dnat
и masquerade
, отлично работают для перенаправления пакетов от одного источника к одному получателю. Тем не менее, одна из особенностей nftables заключается в том, что он не поддерживает размножение пакетов для их пересылки на несколько конечных адресов. Этого недостатка нет, например, в multicast протоколах, которые спроектированы специально для подобных задач, но они выходят за рамки непосредственной работы nftables.
Пример
Ранее, вы использовали такой набор команд для перенаправления пакетов:
nft add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
nft add rule ip nat prerouting tcp dport 9000 dnat to 172.19.0.2
nft add rule ip nat postrouting ip daddr 172.19.0.1 masquerade
Этот набор правил перенаправляет пакеты, приходящие на порт 9000, на один конкретный адрес (172.19.0.2
) посредством команды dnat. Однако, если ваше требование заключается в том, чтобы отправлять эти же пакеты на несколько конечных адресов, то здесь вы столкнетесь с проблемой, так как прямой способ размножения пакетов с помощью nftables отсутствует.
Приложение
Прямого решения этой задачи через nftables не существует. Рассмотрим альтернативные подходы:
-
Использование Multicast:
Если приложение и среда поддерживают использование multicast, вы можете настроить источник для отправки данных посредством multicast адреса, что позволит нескольким получателям подписываться на поток данных.
# Включить поддержку IP multicast на уровне операционной системы sysctl -w net.ipv4.ip_forward=1 sysctl -w net.ipv4.conf.all.rp_filter=0
Следует настроить приложении для отправки multicast потока на нужный адрес.
-
Использование специализированных инструментов:
Поскольку вы упомянули проблему с socat, которая создает множество дочерних процессов, есть другие инструменты, такие как netcat, которые могут быть использованы в комбинации со скриптами, чтобы сделать расщепление трафика. Однако, нужно будет тщательно проработать обработку ошибок.
-
Разработка кастомного решения:
Как альтернативу, вы можете написать небольшое сервисное приложение, которое будет слушать на необходимом порту и самостоятельно размножать поступающие пакеты на список получателей. Это может быть реализовано на любом языке программирования, поддерживающем работу с сокетами, например, на Python с использованием библиотек, таких как
socket
иasyncio
.
Посмотреть можно пример на языке Python, который демонстрирует такую концепцию:
import socket
import threading
def forward_packet(destinations, data):
for destination in destinations:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(destination)
s.sendall(data)
s.close()
except Exception as e:
print(f"Ошибка отправки на {destination}: {e}")
def start_server(port, destinations):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', port))
s.listen()
while True:
conn, addr = s.accept()
data = conn.recv(4096)
threading.Thread(target=forward_packet, args=(destinations, data)).start()
destinations = [('172.19.0.2', 9001), ('172.20.0.2', 9001)]
start_server(9000, destinations)
Эта простая программа слушает входящие соединения на порту 9000 и отправляет их сразу на два указанных IP-адреса. Конечно, это решение следует доработать для обработки ошибок и балансировки нагрузки, а также протестировать в вашей конкретной сетевой среде.
Подводя итог, основная проблема состоит в том, что nftables в своей основе не поддерживает множественную рассылку одной копии пакета, и для достижения этой цели придется использовать другие средства и подходы.