Как использовать разные сетевые интерфейсы для разных процессов?

59

У меня есть два сетевых интерфейса на ПК с Linux, и мне нужно вручную установить интерфейс, который будет использовать данный процесс.

Программа (софтфон Twinkle) не имеет подобной опции, поэтому я считаю, что она должна быть установлена ​​внешне.

Как я могу это сделать?

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

Андреа Спадаччини
источник
клиенты также используют bind / connect, посмотрите документацию bind.c.txt о том, как принудительно заставить ircII (программу irc-client) для данного ip: 'Пример в bash, чтобы использовать ваш виртуальный IP в качестве исходящего адреса источника для ircII: BIND_ADDR = "your-virt-ip" LD_PRELOAD =. / Bind.so ircII '
Акира
Здесь я нашел другой подход, надеюсь, он будет полезен (я уверен, что в настоящее время описанная маршрутизация политики ядра включена по умолчанию): kindlund.wordpress.com/2007/11/19/…
Savvas Radevic

Ответы:

48

Вы можете заменить код во время выполнения с помощью LD_PRELOAD (@windows вы можете использовать аналогичную технику, называемую обходными путями , довольно необычно). для этого нужно сообщить динамическому компоновщику, что сначала нужно загрузить все библиотеки в процесс, который вы хотите запустить, а затем добавить еще один к нему. вы обычно используете это так:

% LD_PRELOAD=./mylib.so ls

и тем самым вы меняете то, что lsделает.

для вашей проблемы я бы попробовал http://www.ryde.net/code/bind.c.txt , который вы можете использовать как:

% BIND_ADDR="ip_of_ethX" LD_PRELOAD=./bind.so twinkle

вот как вы это строите:

% wget http://www.ryde.net/code/bind.c.txt -O bind.c
% gcc -nostartfiles -fpic -shared bind.c -o bind.so -ldl -D_GNU_SOURCE

более длинная инструкция http://daniel-lange.com/archives/53-Binding-applications-to-a-specific-IP.html

похожие хаки и инструменты:

Акира
источник
7
Вау, какого черта. +1
sinni800
1
Привет, это действительно хороший трюк, но он не работает для меня. У меня есть два 3G модема, которые при подключении открывают два интерфейса (ppp0 и ppp1). Если я пытаюсь форсировать один из двух IP-адресов, я всегда получаю один и тот же интерфейс (я вижу это, потому что у меня есть два экземпляра wireshark, по одному для каждого интерфейса). Я также удалил отладочные отпечатки из bind.c и действительно вижу, что «перегруженная» библиотека загружена, поэтому я не знаю, почему она не работает.
Андреа Спадаччини
3
LD_PRELOAD игнорируется, если ваш эффективный UID не совпадает с вашим реальным UID.
Матиас Крулл
force_bindПроект Каталин М. Boie поддерживает ipv6
BurnsBA
Прекрасно работает, но пришлось добавить #include <arpa / inet.h> для успешной компиляции.
Anno
31

ip netns может сделать это.

TL; DR: создайте сетевые пространства имен, свяжите с ними интерфейсы и запустите «ip netns exec NAME cmd ...»

Просто проверьте, поддерживает ли ваш дистрибутив ip netns ... (Backtrack 5r3 не поддерживает, а Kali поддерживает;))

ПОДРОБНЕЕ:

#create netns
ip netns add myNamespace
#link iface to netns
ip link set eth0 netns myNamespace
#set ip address in namespace
ip netns exec myNamespace ifconfig eth0 192.168.0.10/24 up
#set loopback (may be needed by process run in this namespace)
ip netns exec myNamespace ifconfig lo 127.0.0.1/8 up
#set route in namespace
ip netns exec myNamespace route add default gw 192.168.0.1
#force firefox to run inside namespace (using eth0 as outgoing interface and the route)
ip netns exec myNamespace firefox

Почему это лучше, чем привязка ip через LD_PRELOAD? Потому что LD_PRELOAD не контролирует маршрут, используемый процессами. Он будет использовать первый маршрут.

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

olivervbk
источник
2
Пожалуйста, попробуйте добавить больше деталей к вашему ответу.
Рэндзю Чандран Чингат
4
не делайте этого на удаленном сервере, если eth0 - это общедоступный сетевой интерфейс ..
ygrek
1
последняя строка должна бытьip netns exec myNamespace firefox
meuh
1
Используйте «sudo ip netns del <namespace-name>» для удаления пространства имен при необходимости!
Эдуардо Лусио
1
@EduardoLucio должно быть возможно выполнить это как: sudo ip netns exec myNamespace su -u someUser -c firefox
olivervbk
2

Я не думаю, что можно заставить процесс использовать определенный интерфейс.

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

Полезное руководство: http://tldp.org/HOWTO/IPCHAINS-HOWTO.html

thetarro
источник
2
Два поста с более высоким рейтингом доказывают обратное.
Пол Гир
2

Исходя из @olivervbk ответ ниже мой!

Запустите все команды как «root».

Используйте команду ...

ip a

... чтобы узнать название сетевого интерфейса, который вы хотите использовать.

Запустите команды ниже как шаблон ...

ip netns add [INTERFACE_NAME]_ns
ip link set dev [INTERFACE_NAME] netns [INTERFACE_NAME]_ns
ip netns exec [INTERFACE_NAME]_ns ifconfig [INTERFACE_NAME] 10.1.1.10/24 up
ip netns exec [INTERFACE_NAME]_ns ifconfig lo 127.0.0.1/8 up
ip netns exec [INTERFACE_NAME]_ns route add default gw 10.1.1.1
ip netns exec [INTERFACE_NAME]_ns dhcpcd [INTERFACE_NAME]
ip netns exec [INTERFACE_NAME]_ns sudo -b -u [YOUR_USER] [APP_NAME] 2> /dev/null 1> /dev/null &
  • [INTERFACE_NAME] - заменить имя выбранного сетевого интерфейса.
  • [YOUR_USER] - замените своим именем пользователя.
  • [APP_NAME] - имя приложения, которое будет выполняться в пространстве имен "[INTERFACE_NAME] _ns". Например: "Firefox".

ПРИМЕЧАНИЕ I: Флаги «-b -u» ​​в команде «sudo» позволяют приложению запускаться с использованием вашего пользователя (не «root») и в фоновом режиме освобождают терминал. 2> /dev/null 1> /dev/null &Фрагмент кода, чтобы предотвратить выходы из «[APP_NAME]» печатается на терминале.
ПРИМЕЧАНИЕ II: значения ip "10.1.1.10" и "10.1.1.1" являются произвольными.
ПРИМЕЧАНИЕ III: Чтобы работать на меня, я должен был запустить dhcpcd [INTERFACE_NAME]команду.

Чтобы удалить пространство имен, используйте ...

ip netns del [INTERFACE_NAME]_ns

... или же...

ip -all netns delete

... чтобы удалить все, что существует.

Эдуардо Лучио
источник
1

Обычно, если программа не имеет возможности настройки интерфейса прослушивания, она прослушивает ВСЕ интерфейсы. (Вы можете проверить это с помощью lsof -i).

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

LawrenceC
источник
1

Альтернатива I:

Использование ld_preload для принудительной настройки шлюза интерфейса https://github.com/Intika-Linux-Network/App-Route-Jail

Заставить приложение использовать определенный сетевой интерфейс

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

  • Как найти интерфейсный шлюз (есть много решений для поиска шлюза, здесь приведены некоторые команды, позволяющие найти используемый шлюз)
$ route
$ route -n
$ ip rule list
$ ip route show
$ netstat -rn
$ cat /etc/network/interfaces
$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
$ traceroute www.google.com
$ ip route show 0.0.0.0/0 dev eth0

На шлюз приложения

  • Построить App-Route-Jail
git clone https://github.com/Intika-Linux-Network/App-Route-Jail.git
cd Approute-Utils
chown 755 make.sh
./make.sh
  • Добавление маршрута для будущих помеченных пакетов (для заключенного в тюрьму приложения) в этом примере 192.168.1.1используется в качестве принудительного шлюза, это правило маршрута не повлияет на другие приложения, например, эту манипуляцию нужно выполнять только один раз при загрузке системы, если вы хотите используйте это решение ежедневно
ip rule add fwmark 10 table 100
ip route add default via 192.168.1.1 table 100
  • Запустите приложение, которое вы хотите заключить в тюрьму
MARK=10 LD_PRELOAD=./mark.so firefox
  • Тестирование wan IP-адреса
MARK=10 LD_PRELOAD=./mark.so wget -qO- ifconfig.me

Альтернатива II:

Firejail https://firejail.wordpress.com/ может заставить приложение использовать определенную сеть, но совместимость ограничена.

firejail --dns=8.8.8.8 --net=eth0 --ip=192.168.1.1
intika
источник
Обратите внимание, что отметка невозможна для обычных пользователей, вы должны запускаться от имени пользователя root.
jornane
-2

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

Разные серверы в IP-сетях имеют разные IP-адреса. Ядро должно знать, какой интерфейс использовать для достижения определенного IP-адреса на основе таблицы маршрутизации. Если вы пытаетесь установить связь с двумя разными серверами с одинаковым IP-адресом, система будет сбита с толку (поскольку, помимо прочего, она индексирует соединения только по внутреннему адресу). Вы можете сделать это, но это исправление на уровне системы, включающее помещение одного сервера в отдельную логическую сеть, которая подключена к компьютеру только через программный NAT.

Поэтому, если у них разные IP-адреса, используйте маршруты, чтобы выбрать правильный интерфейс. Если у них одинаковый IP-адрес, вам нужно использовать NAT, чтобы они имели разные IP-адреса для системы.

Дэвид Шварц
источник
3
Во-первых, между клиентом и сервером может быть несколько действительных маршрутов, но с разными характеристиками, подходящими для разных типов трафика; например, UMTS (сотовая связь) может стоить денег, но имеет больший радиус действия, чем WiFi, но оба они медленнее, чем оптоволоконные соединения. Если вышестоящие провайдеры выполняют фильтрацию источников (или NAT), у вас нет выбора, кроме как отправить «правильный» интерфейс. Во-вторых, влияние на маршрутизацию - не единственная причина выбора исходного адреса. Даже если оба адреса находятся на одном и том же интерфейсе, может быть полезно управлять тем, с
Один случай, если у вас разные публичные IP-адреса и вы хотите запустить новый процесс в каждом из них для исходящих соединений.
Rfraile