Вкратце: мне нужно перенаправление порта для протокола, ориентированного на соединение, как и для TCP, но мне нужно, чтобы оно работало для UDP. У меня есть собственный протокол, ориентированный на соединение, использующий UDP для транспорта.
В частности:
Для 4, точнее: когда пакет приходит из 10.1.2.10, ему назначается случайный порт, скажем, 52000. Затем ЭТА машина получает пакет на UDP-порт 5005 и пересылает его на 10.1.2.20:5010, имея также несколько случайно- выбранный исходный порт, скажем, 52001. Теперь, когда приходит пакет с порта 5010 10.1.2.20 на порт 52001 ЭТОЙ машины, он должен перенаправить его также на порт 52000 10.1.2.10.
Более того, если на 10.1.2.10 идет пакет из другого порта, также должны применяться назначение порта и соответствующее правило для перенаправления пакетов в обратном направлении. Для любого трафика может быть установлен таймаут 10 секунд, после которого правило обратного отслеживания удаляется.
Если это невозможно сделать с помощью iptables, меня это устраивает - я вернусь к решению для пользовательского пространства. Но с iptables это упростит развертывание.
Таким образом, ваш прокси-сервер выполняет двойной NAT, маскируясь (скрывая другого реального однорангового узла) в обоих направлениях.
Он должен быть настроен как маршрутизатор на своем (единственном) интерфейсе, иначе ничего не будет перенаправлено. Скажем, имя интерфейса - eth0, а его IP - 10.1.2.50:
echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding
Теперь из-за двойного NAT преобразования в PREROUTING
и / или POSTROUTING
предотвратить сопоставление потока, просто используя снова тот же фильтр. Так что в PREROUTING
а CONNMARK
используется для обозначения потока, который затем можно сразу повторно использовать в PREROUTING
(и избегая дублирования конкретного теста для упрощения управления), а затем в POSTROUTING
. Заметка -p udp
все еще нужен, потому что мы просим SNAT
и / или DNAT
для изменения портов UDP. После этого conntrack будет обрабатывать весь будущий обмен до тех пор, пока не истечет время ожидания (обычно 30 секунд для первого ответа, затем 3 минуты)
iptables -t nat -A PREROUTING -s 10.1.2.10 -p udp --dport 5005 -j CONNMARK --set-mark 0x1
iptables -t nat -A PREROUTING -p udp -m connmark --mark 0x1 -j DNAT --to-destination 10.1.2.20:5010
iptables -t nat -A POSTROUTING -m connmark --mark 0x1 -j SNAT --to-source 10.1.2.50
Если действительно требуется, чтобы вы также изменили исходный порт, вместо того, чтобы conntrack делал это только при необходимости, измените третье правило на:
iptables -t nat -A POSTROUTING -p udp -m connmark --mark 0x1 -j SNAT --random-fully --to-source 10.1.2.50:32768-60999
(обычный диапазон взят из /proc/sys/net/ipv4/ip_local_port_range
, и --random-fully
требуется, иначе ничего не будет сделано, потому что исходный порт уже находится в диапазоне).
Вы также можете изменить SNAT
к MASQUERADE
(и не обязательно указывать IP-адрес сервера), а только --random
доступен.
ОБНОВЛЕНИЕ: хотя приведенные выше правила работают по назначению, обычно connmark
матч и CONNMARK
target предназначены для взаимодействия с mark
и MARK
для более сложное использование, как описано в этом блоге. Здесь они не нужны для простого использования. Просто замените их все на соотв. mark
и MARK
. Здесь отслеживание соединений netfilter уже заботится о потоке после обработки первого пакета (создание записи conntrack в NEW
state) без необходимости просить его отметить это в записи conntrack. Отметка просто ставится в (первом) пакете ( nat
таблица видит только пакеты в NEW
штат):
iptables -t nat -A PREROUTING -s 10.1.2.10 -p udp --dport 5005 -j MARK --set-mark 0x1
iptables -t nat -A PREROUTING -p udp -m mark --mark 0x1 -j DNAT --to-destination 10.1.2.20:5010
iptables -t nat -A POSTROUTING -m mark --mark 0x1 -j SNAT --to-source 10.1.2.50
Примеры снимков, включая ошибки (служба не работает и т. Д.):
00:28:36.476453 IP 10.1.2.10.56955 > 10.1.2.50.5005: UDP, length 5
00:28:36.476487 IP 10.1.2.50.35172 > 10.1.2.20.5010: UDP, length 5
00:28:36.476516 IP 10.1.2.20 > 10.1.2.50: ICMP 10.1.2.20 udp port 5010 unreachable, length 41
00:28:36.476522 IP 10.1.2.50 > 10.1.2.10: ICMP 10.1.2.50 udp port 5005 unreachable, length 41
00:32:28.597050 IP 10.1.2.10.35443 > 10.1.2.50.5005: UDP, length 5
00:32:28.597084 IP 10.1.2.50.36842 > 10.1.2.20.5010: UDP, length 5
00:32:32.503709 IP 10.1.2.20.5010 > 10.1.2.50.36842: UDP, length 7
00:32:32.503745 IP 10.1.2.50.5005 > 10.1.2.10.35443: UDP, length 7
00:32:41.704371 IP 10.1.2.20.5010 > 10.1.2.50.36842: UDP, length 4
00:32:41.704404 IP 10.1.2.50.5005 > 10.1.2.10.35443: UDP, length 4
00:32:41.704427 IP 10.1.2.10 > 10.1.2.50: ICMP 10.1.2.10 udp port 35443 unreachable, length 40
00:32:41.704433 IP 10.1.2.50 > 10.1.2.20: ICMP 10.1.2.50 udp port 36842 unreachable, length 40
Обратите внимание, что вы можете заменить все это этой простой строкой socat (и у вас не будет тайм-аута 30 с / 3 мин, но вы потеряете обработку ICMP):
socat UDP4-LISTEN:5005,range=10.1.2.10/32,fork UDP4:10.1.2.20:5010