Принудительно использовать локальный IP-трафик для внешнего интерфейса.

30

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

  • 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, но это слишком сложно для меня.

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

Я использую Linux, но если вы знаете, как это сделать с Windows, я куплю это!

Редактировать:

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

calandoa
источник
Вы хотите сказать, что хотите, чтобы весь трафик отражался через интерфейс 1 и 2, но возвращался только через интерфейс 2 с другого маршрутизатора? Разве это не может сделать довольно странные вещи в сети? Было бы лучше направить зеркальный трафик с интерфейса 2 на другую систему, которая только что отбросила трафик, и затем вы можете отслеживать его или использовать программное обеспечение для виртуализации для захвата трафика? Может быть, я что-то упустил в описании.
Барт Сильверстрим
Похоже, он хочет сгенерировать пакет, скажем, для 192.168.1.1, который является IP-адресом eth1. Но вместо того, чтобы стек Linux получил этот пакет полностью изнутри, он хочет, чтобы пакет вытеснил eth2 (который будет доставлен извне обратно в eth1, а затем в стек Linux). Я не уверен, возможно ли это; как только сетевой уровень обнаружит, что адрес является внутренним интерфейсом, у него будет мало причин для просмотра таблиц маршрутизации. Кто-то может знать лучше.
пп.

Ответы:

14

Я расширил ответ Каладоны, так как не мог видеть ответные пакеты. Для этого примера:

  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
cmcginty
источник
Гораздо лучше ваш путь! Обратите внимание, что мне также нужен ip_forward для работы ARP: echo 1> / proc / sys / net / ipv4 / ip_forward
calandoa
28

Я успешно использовал следующее в Linux для проверки пропускной способности на новой двухпортовой карте 10 Гбит / с в режиме «loopback», то есть один порт подключен непосредственно к другому. Это всего лишь немного вуду, просто чтобы заставить пакеты выходить из сети, но если вы этого не сделаете, Linux просто закоротит трафик через ядро ​​(отсюда и вопрос ОП). В ответе Кейси выше я не уверен, было ли действительно необходимо иметь внешний маршрутизатор или нет, но следующее полностью автономно. Два интерфейса - это eth2 и eth3.

Назначьте 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-адресом вы связываетесь (фальшивый адрес другого конца):

# server
./iperf -B 10.50.1.1 -s

# client: your destination is the other end's fake address
./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

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

Стив Келет
источник
+1 Отличное решение - для этого даже не требуется активировать ip-forwarding! Это как раз то, что мне было нужно прямо сейчас (для тестирования 10 ГБ по шлейфу).
Нильс
16

Как всегда - я немного опоздал - но в настоящее время можно использовать сетевые пространства имен, чтобы изолировать интерфейсы и предотвратить любую локальную пересылку (и возиться с iptables :)).

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

ip netns add ns_server
ip netns add ns_client

Обратите внимание, что к интерфейсам status / config теперь нужно обращаться в контексте назначенного пространства имен - поэтому они не будут отображаться, если вы запускаете голую 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-адреса).

Томас Таннхойзер
источник
Это гораздо проще, чем предлагаемая магия двойного натяжения, и не требует никакой координации со стороны других компьютеров в сети и не предполагает никакой физической топологии. Моя единственная просьба - добавить команды для добавления маршрутов.
Гекл
2

Хорошо, наконец-то мне удалось настроить мой конфиг.

Идея состоит в том, чтобы использовать другой поддельный адрес, чтобы принудительно настроить маршрут этого поддельного адреса к интерфейсу 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.

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

calandoa
источник
если маршрутизатор отправляет $ FAKE_ADDR в $ IF2_ADDR, разве ваше правило DNAT не должно быть «-i $ IF2» вместо «-i $ IF1»?
cmcginty
Вы правы, Кейси, исправление сделано.
Calandoa
1

Ответ, данный выше Томасом Таннхойзером, был точным!

У меня была похожая ситуация: одна машина с двумя интерфейсами enet. Я планировал использовать один интерфейс в качестве сервера (получателя), а другой - в качестве клиента (отправителя). Каждый интерфейс будет подключен к маршрутизатору, а iperf будет направлять трафик через маршрутизатор для измерения пропускной способности, PPS, задержки и т. Д.

К сожалению, подход iptables был не интуитивным и чреват проблемами. После нескольких разочаровывающих часов я отказался от этого плана атаки. Вдохновленный предложением Томаса, я немного поработал над пространствами имен Linux IP и начал ценить простоту и элегантность этого решения.

Ниже приведен список точных команд, которые я использовал для настройки своего Fedora FC26 для работы в этом качестве. Два интерфейса - это enp1s0 и enp3s0. Маршрутизатор имеет два интерфейса с адресами 192.168.2.112 и 172.16.16.2. Каждый разъем FC26 ENET напрямую подключен к соответствующему интерфейсу маршрутизатора.

# How to configure the IP Namespaces
ip netns add iperf-server
ip netns add iperf-client
ip link set enp1s0 netns iperf-server
ip link set enp3s0 netns iperf-client
ip netns exec iperf-server ip addr add dev enp1s0 192.168.2.139/20
ip netns exec iperf-client ip addr add dev enp3s0 172.16.16.2/24
ip netns exec iperf-client ip link set dev enp3s0 up
ip netns exec iperf-server ip link set dev enp1s0 up
ip netns exec iperf-server route add default gw 192.168.2.112
ip netns exec iperf-client route add default gw 172.16.16.1

# Test the interfaces and network using ping
ip netns exec iperf-client ping -c1 172.16.16.1
ip netns exec iperf-server ping -c1 192.168.2.112
ip netns exec iperf-server ping -c1 172.16.16.2
ip netns exec iperf-client ping -c1 192.168.2.139

# Start Iperf Server for UDP test
ip netns exec iperf-server iperf -u -s
# Run Client against Iperf server for UDP test
ip netns exec iperf-client iperf -u -c 192.168.2.139
RarkyMan
источник
0

Звучит так, будто вы хотите превратить свой Linux-блок в типовой маршрутизатор / мост / шлюз / брандмауэр. Следующие ресурсы могут быть тем, что вы ищете:

Проект Linux Router

Список дистрибутивов маршрутизаторов или брандмауэров

Linux LiveCD Router

Linux Journal - Маршрутизатор Linux

Обновление на основе дополнительной информации:

Я не думаю, что вы сможете делать то, что вы хотите. Операционная система всегда собирается просматривать свою внутреннюю таблицу маршрутизации и «видеть» оба IP-адреса локально. Затем он будет маршрутизировать трафик внутри ОС и никогда не подключать его к сети. Вам понадобится вторая машина или две виртуальные машины (посмотрите Xen ).

Питер
источник
0

Здесь многое предстоит пройти, поэтому я не могу полностью гарантировать свою точность, но первоначальный вопрос, похоже, исходит из того, что известно как техника «отправить себе» . Связанный поиск показывает, что я считаю лучшим поддерживаемым патчем ядра, как top link + обсуждения и патчи с другими подходами в различных списках рассылки, esp. LKML.

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

Комментарии, безусловно, приветствуются, если кто-то найдет что-то полезное с этим - как, что, где о вашей реализации

lkraav
источник
0

Проверьте эту статью. Здесь подробно описаны шаги для включения доступа в интернет к virtualbox vm с использованием переадресации NAT.

http://jackal777.wordpress.com/2012/02/13/virtualbox-host-only-networking-nat-for-internet-access/

Рейнольд
источник
Хотя это может теоретически ответить на вопрос, было бы предпочтительным включить здесь основные части ответа и предоставить ссылку для справки.
Скотт Пак
-1

вот как у меня это работает на IPV6

назначенные статические ips

/sbin/ifconfig eth1 inet6 add 2001:db8::1/127 
/sbin/ifconfig eth3 inet6 add 2001:db8::2/127 

настроить маршруты только для хоста на адреса "FAKE"

ip -6 route add 2001:db8::2/128 dev eth1 metric 1
ip -6 route add 2001:db8::1/128 dev eth3 metric 1

заселил соседский стол ... как арп

ip -6 neighbor add 2001:db8::1 lladdr 90:e2:ba:0d:75:e8 dev eth3 # eth1's mac address
ip -6 neighbor add 2001:db8::2 lladdr 90:e2:ba:0d:75:e9 dev eth1 # eth3's mac address

добавил записи ip6tables

ip6tables -t nat -A POSTROUTING -s 2001:db8::1 -d 2013::2 -j SNAT --to-source 2001:db8::1
ip6tables -t nat -A PREROUTING -d 2001:db8::1 -j DNAT --to-destination 2001:db8::1
ip6tables -t nat -A POSTROUTING -s 2001:db8::2 -d 2013::1 -j SNAT --to-source 2001:db8::2
ip6tables -t nat -A PREROUTING -d 2001:db8::2 -j DNAT --to-destination 2001:db8::2
robm
источник
Какой дистрибутив вы используете? В прошлый раз, когда я проверял, у ядра нет таблицы NAT для IPv6.
fukawi2