Настройка пакетов UDP для двух разных пунктов назначения с помощью iptables и PREROUTING

Мне ничего не известно о такой утилите. Однако ваш подход несовершенен (, и я согласен, что его очень трудно понять правильно ).

Модификатор :aвычисляет абсолютный путь без доступа к файловой системе. В частности, он заменяет a/b/..на aнезависимо от того, является ли a/bсимволической ссылкой или нет.

Если у вас есть символическая ссылка /a/b ->../foo, это /foo, только если /aне является символической ссылкой. Даже если вы канонизируете $(dirname $1), это все равно не будет работать для символических ссылок, таких как /a/b -> x/../../foo, если xсам по себе является символической ссылкой.

В вашем случае:

/tmp/example/A/B/C/D/symlink-0 ->../../symlink-1/b/c/d/target

разрешается в /tmp/example/A/B/symlink-1/b/c/d/targetтолько потому, что ни /tmp/example/A/B/C/D, ни /tmp/example/A/B/Cне являются символическими ссылками.

Другими словами, чтобы получить абсолютный путь к цели символической ссылки, не содержащей компонентов .., вам может потребоваться разрешить более одной символической ссылки, и вы не можете сделать это в одиночку, комбинируя путь к файлу и цель символической ссылки.

Если вам нужен такой путь, самый простой (и, я бы сказал, единственно разумный и/или полезный )подход — это получить канонический путь этой цели символической ссылки, где все компоненты пути не являются ни .., ., ни символическими ссылками, за исключением, возможно, последнего. Для этого вы можете:

zmodload -F zsh/stat b:zstat
canonicalize1() {
  if [ -L "$1" ]; then
    local link
    zstat -A link +link -- "$1" || return
    case $link in
      (/*) ;;
      (*)
        case $1:h in
          (*/) link=$1:h$link;;
          (*) link=$1:h/$link;;
        esac;;
    esac
    printf '%s\n' $link:h:A/$link:t
  else
    printf '%s\n' $1:A
  fi
}

На ваших символических ссылках /tmp/example/A/B/C/D/symlink-0это по-прежнему дает /tmp/example/a/b/c/d/target, так как цель символической ссылки не является символической ссылкой, но если это не то, что вы хотите,то я спрашивал :, какой результат вы бы хотели получить при выполнении:

canonicalize1 /tmp/x/y

Где /tmp/x/y— символическая ссылка на ../foo, а /tmp/x— символическая ссылка на /a/b/c, а /a, /a/b, /a/b/c— тоже символические ссылки?

1
21.11.2019, 11:18
1 ответ

Простые пользовательские инструменты

Во-первых, я бы порекомендовал использовать специальный инструмент, работающий на сервере D, который прослушивает пакеты UDP и дважды отправляет копию, одну для A и одну для B.Это можно сделать, например, с помощью замены процесса bash + tee + socat(примера, свободно адаптированного изudp-multi-socat.shс его удобным обратным порядком, чтобы tee немедленно запускается ), но я не знаю, может ли некоторая буферизация не происходить в некоторых случаях (лучше создать специальное приложение):

socat -U - udp4-recv:3070 | tee >(socat -u - udp4-datagram:167.111.111.111:5640) | socat -u - udp4-datagram:192.111.111.111:5640

Использование ядра (iptables... -j TEE)

Теперь, когда сказано, что для метода «помощь ядра -» существует цель iptablesTEE , которая может дублировать пакеты. Поскольку дублирование должно обходить обычную обработку маршрутизации, необходимо «эвакуировать» дублированный пакет на другой хост, напрямую доступный (параметр--шлюза ). Без этого, похоже, нет хорошего способа обработки скопированного пакета с помощью TEE .

Достаточно честно, мы можем просто создать этот хост, используя сетевое пространство имен. Затем верните продублированный трафик обратно на хост D через стек маршрутизации и iptables, которые теперь могут использовать для него другую ДНК (, потому что он пришел с другого интерфейса ). Из-за асимметричной маршрутизации и дублирования потока необходимо выполнить некоторые настройки (свободный rp _фильтр на виртуальном интерфейсе и другую зону conntrack (origin )чтобы различать потоки, потому что conntrack знает только об IP-адресах, а не об интерфейсах)

Вот конфигурация для использования на сервере D (возможно, можно было бы избежать некоторого дублирования, но это было бы менее читабельно):

ip netns del dup 2>/dev/null || : # to remove previous instance, if needed
ip netns add dup

ip link add name dup1 type veth peer netns dup name eth0
ip link set dup1 up
ip -n dup link set eth0 up
ip address add 10.10.10.1/24 dev dup1
ip -n dup address add 10.10.10.2/24 dev eth0
ip -n dup route add default via 10.10.10.1
sysctl -q -w net.ipv4.conf.dup1.rp_filter=2
ip netns exec dup sysctl -q -w net.ipv4.conf.eth0.forwarding=1
iptables -t mangle -A PREROUTING -i eth0 -p udp --dport 3070 -j TEE --gateway 10.10.10.2
iptables -t raw -A PREROUTING -i dup1 -p udp --dport 3070 -j CT --zone-orig 1
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 3070 -j DNAT --to-destination 192.111.111.111:5640
iptables -t nat -A PREROUTING -i dup1 -p udp --dport 3070 -j DNAT --to-destination 167.111.111.111:5640

С помощью этого метода даже ответы от A и B могут быть отправлены обратно на C (, который будет думать, что они оба пришли из одного и того же начального пункта назначения ), если это вообще имеет смысл. Таким образом, если ничего не прослушивается на A или B, источнику C будет отправлено ICMP-порт назначения недостижим .который может прервать :дополнительный брандмауэр, чтобы избежать этого, вероятно, следует где-то добавить.

3
27.01.2020, 23:57

Теги

Похожие вопросы