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

Как выбрать, какой Apache MPM использовать?

Linux

Какой самый простой способ отправить зашифрованное письмо?

Linux

Как распаковать tar bz2 xz gz архивы в Linux? Как открыть файл bz2?

×