Linux

Как принудительно направить локальный IP-трафик на внешний интерфейс

У меня есть машина с несколькими интерфейсами, которые я могу настроить как хочу, например:

  • eth1: 192.168.1.1
  • eth2: 192.168.2.2

Я хотел бы перенаправить весь трафик, отправленный на один из этих локальных адресов, через другой интерфейс. Например, все запросы к серверу iperf, ftp, http по адресу 192.168.1.1 должны не только маршрутизироваться внутри, но и перенаправляться через eth2 (а внешняя сеть позаботится о перенаправлении пакета на eth1).

Я попробовал и просмотрел несколько команд, таких как iptables, ip route и т. д., но ничего не сработало.

Самое близкое поведение, которое я мог получить, было сделано с помощью:

ip route change to 192.168.1.1/24 dev eth2

 

который отправляет все с 192.168.1.x на eth2, за исключением 192.168.1.1, который все еще маршрутизируется внутри. Могу ли я тогда выполнить NAT-переадресацию всего трафика, направленного на поддельный 192.168.1.2 на eth1, с внутренним перенаправлением на 192.168.1.1? Я пытался использовать iptables, но для меня это слишком сложно.

Цель этой настройки провести тестирование драйвера интерфейса без использования двух компьютеров.

Внешняя сеть это просто перекрестный кабель между eth1 и eth2. Допустим, у меня на машине есть http-сервер. Теперь я хочу получить доступ к этому серверу с той же машины, но я хочу заставить трафик TCP/IP проходить через этот кабель eth1/eth2. Как мне настроить для этого свои интерфейсы?

 

Ответ 1

Мое решение:

  1. На моем локальном ПК есть сетевые карты в разных подсетях, 192.168.1/24, 192.168.2/24.

  2. Есть внешний маршрутизатор/ПК, у которого есть доступ к обеим подсетям.

  3. Я отправляю двунаправленный трафик через сетевые карты на локальном ПК.

  4. Конфигурация требует двух неиспользуемых IP-адресов для каждой подсети.

Маршруты iptable локального ПК настроены на исходящий трафик SNAT и DNAT на «поддельный» IP.

iptables -t nat -A POSTROUTING -d 192.168.1.100 -s 192.168.2.0/24 -j SNAT --to-source      192.168.2.100

iptables -t nat -A PREROUTING  -d 192.168.1.100 -i eth0           -j DNAT --to-destination 192.168.1.1

iptables -t nat -A POSTROUTING -d 192.168.2.100 -s 192.168.1.0/24 -j SNAT --to-source      192.168.1.100

iptables -t nat -A PREROUTING  -d 192.168.2.100 -i eth1           -j DNAT --to-destination 192.168.2.1

 

То есть:

  1. Перепишите источник 192.168.2.1 на 192.168.2.100 в исходящих пакетах

  2. Перепишите адрес назначения 192.168.1.100 на 192.168.1.1 для входящих пакетов

  3. Перепишите источник 192.168.1.1 на 192.168.1.100 в исходящих пакетах

  4. Перепишите адрес назначения 192.168.2.100 на 192.168.2.1 для входящих пакетов

Подводя итог, теперь локальная система может взаимодействовать с «виртуальной» машиной с адресами 192.168.1.100 и 192.168.2.100.

Затем вы должны заставить свой локальный компьютер использовать внешний маршрутизатор для доступа к вашему поддельному IP-адресу. Вы делаете это, создавая прямой маршрут к IP через маршрутизатор. Вам нужно убедиться, что вы принудительно отправляете пакеты в подсеть, противоположную целевой.

ip route 192.168.1.100 via $ROUTER_2_SUBNET_IP 

ip route 192.168.2.100 via $ROUTER_1_SUBNET_IP

 

Наконец, чтобы все это работало, внешний маршрутизатор должен знать, как получить поддельные IP-адреса на вашем локальном ПК. Вы можете сделать это, включив для своей системы прокси-ARP.

echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/proxy_arp

echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

 

С такой настройкой вы теперь можете рассматривать поддельные IP-адреса как настоящую систему на вашем локальном ПК. При отправке данных в подсеть .1 пакеты будут передаваться через интерфейс .2. При отправке данных в подсеть .2 пакеты будут передаваться через интерфейс .1.

ping 192.168.1.100

ping 192.168.2.100

 

Ответ 2

Я успешно использовал следующее в Linux для проверки пропускной способности новой двухпортовой карты 10 Гбит/c в режиме «обратной связи», то есть когда один порт подключен непосредственно к другому. Здесь совсем немного «магии», чтобы заставить пакеты выйти из сети. Но если вы этого не сделаете, Linux просто закоротит трафик через ядро.

Дайте IP-адреса интерфейсам и поместите их в отдельные сети:

ifconfig eth2 10.50.0.1/24

ifconfig eth3 10.50.1.1/24

 

Далее необходимо настроить сценарий с двойным NAT: две новые поддельные сети используются для доступа к другой. На выходе подключите NAT к вашей фальшивой сети. По пути зафиксируйте пункт назначения. И наоборот для другой сети:

# nat source IP 10.50.0.1 -> 10.60.0.1 when going to 10.60.1.1

iptables -t nat -A POSTROUTING -s 10.50.0.1 -d 10.60.1.1 -j SNAT --to-source 10.60.0.1

# nat inbound 10.60.0.1 -> 10.50.0.1

iptables -t nat -A PREROUTING -d 10.60.0.1 -j DNAT --to-destination 10.50.0.1

# nat source IP 10.50.1.1 -> 10.60.1.1 when going to 10.60.0.1

iptables -t nat -A POSTROUTING -s 10.50.1.1 -d 10.60.0.1 -j SNAT --to-source 10.60.1.1

# nat inbound 10.60.1.1 -> 10.50.1.1

iptables -t nat -A PREROUTING -d 10.60.1.1 -j DNAT --to-destination 10.50.1.1

 

Теперь укажите системе, как попасть в каждую фальшивую сеть, и предварительно заполните записи arp (обязательно замените MAC-адреса на свои):

ip route add 10.60.1.1 dev eth2

arp -i eth2 -s 10.60.1.1 00:1B:21:C1:F6:0F # eth3's mac address

ip route add 10.60.0.1 dev eth3 

arp -i eth3 -s 10.60.0.1 00:1B:21:C1:F6:0E # eth2's mac address

 

Этого достаточно, чтобы фактически передавать пакеты по сети, «обманывая» Linux. Например:

ping 10.60.1.1

 

выходит из eth2, исходный IP-адрес 10.50.0.1 получает NAT-адрес в 10.60.0.1, а когда он входит в eth3, целевой 10.60.1.1 получает NAT-адрес в 10.50.1.1. И ответ проходит аналогичным образом.

Теперь используйте iperf для проверки пропускной способности. Привяжите к правильным IP-адресам и убедитесь, с каким IP вы связываетесь (поддельный адрес другого источника):

# сервер

./iperf -B 10.50.1.1 -s

# клиент: ваш пункт назначения это поддельный адрес другого конца.

./iperf -B 10.50.0.1 -c 10.60.1.1 -t 60 -i 10

 

Убедитесь, что трафик действительно уходит на кабель:

tcpdump -nn -i eth2 -c 500

 

Можно посмотреть /proc/interrupts, чтобы быть абсолютно уверенным, что сетевая карта используется:

while true ; do egrep 'eth2|eth3' /proc/interrupts ; sleep 1 ; done

 

Ответ 3

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

Создайте пространства имен (все делается с необходимыми разрешениями, например, для root):

ip netns add ns_server

ip netns add ns_client

 

Обратите внимание, что доступ к статусу/конфигурации интерфейсов теперь должен осуществляться в контексте назначенного пространства имен, поэтому они не будут отображаться, если вы запустите чистую IP-ссылку, поскольку она выполняется в контексте пространства имен по умолчанию. Выполнение команды в пространстве имен можно выполнить с помощью:

ip netns exec <namespace-name> <command>

 

Теперь назначьте пространства имен интерфейсам, примените конфигурацию и настройте интерфейсы:

ip link set eth1 netns ns_server

ip netns exec ns_server ip addr add dev eth1 192.168.1.1/24

ip netns exec ns_server ip link set dev eth1 up

ip link set eth2 netns ns_client

ip netns exec ns_client ip addr add dev eth2 192.168.1.2/24

ip netns exec ns_client ip link set dev eth2 up

 

Теперь вы можете запускать приложения в пространстве имен.

Для запуска сервера iperf:

ip netns exec ns_server iperf -s -B 192.168.1.1

 

и клиента:

ip netns exec ns_client iperf -c 192.168.1.1 -B 192.168.1.2

 

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

В завершение просто удалите пространства имен:

ip netns del <namespace-name>

 

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

 

Ответ 4

Идея состоит в том, чтобы использовать другой поддельный адрес, чтобы принудительно направить этот поддельный адрес к интерфейсу 2, а затем преобразовать поддельный адрес в реальный адрес 2 с помощью NAT/iptables.

Моя установка, на самом деле, состоит из одного маршрутизатора, который я могу установить между IF1 (интерфейс 1) и IF2.

В моей настройке FAKE_ADDR и IF1_ADDR находятся в одной подсети.

ifconfig $IF1 $IF1_ADDR netmask 255.255.255.0

ifconfig $IF2 $IF2_ADDR netmask 255.255.255.0

iptables -t nat -A PREROUTING -d $FAKE_ADDR -i $IF2 -j DNAT --to-destination $IF2_ADDR

iptables -t nat -A POSTROUTING -s $IF2_ADDR -d $IF1_ADDR/24 -j SNAT --to-source $FAKE_ADDR

route add $FAKE_ADDR gw $ROUTER_ADDR

 

И на роутере:

route add $FAKE_ADDR gw $IF2_ADDR

 

Если я отправляю что-то в FAKE_ADDR, pkt перенаправляется через IF1 на маршрутизатор, снова перенаправляется в IF2, тогда FAKE_IP заменяется IF2_ADDR. Пакет обрабатывается сервером, результат отправляется обратно в IF1_ADDR из IF2_ADDR, который заменяется на FAKE_ADDR.

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

Схожие статьи

Linux

Как лучше всего послать сигнал всем членам группы процессов

Linux

Как мне запросить ввод Да/Нет/Отмена в сценарии оболочки Linux

Unix shell-переменные и персонализированные установки Unix
Linux

Unix shell-переменные и персонализированные установки Unix

Linux

Что такое «POSIX»?

×