Jak korzystać z różnych interfejsów sieciowych dla różnych procesów?

59

Mam dwa interfejsy sieciowe na komputerze z systemem Linux i muszę ręcznie ustawić interfejs, z którego będzie korzystał dany proces.

Program (Twinkle softphone) nie ma podobnej opcji, więc uważam, że należy go ustawić zewnętrznie.

Jak mogę to zrobić?

Edycja: Nie próbuję powiązać procesu serwera z określonym interfejsem, ale raczej skłonić program klienta do skontaktowania się z serwerem za pomocą określonego interfejsu.

Andrea Spadaccini
źródło
klienci używają również bind / connect, spójrz do dokumentacji bind.c.txt, w jaki sposób zmusić ircII (program klienta irc) do danego adresu IP: „Przykład w bash, aby użyć wirtualnego adresu IP jako wychodzącego adresu źródłowego dla ircII: BIND_ADDR = "twoja-virt-ip" LD_PRELOAD =. / Bind.so ircII '
akira
Znalazłem tutaj inne podejście, mam nadzieję, że jest pomocne (mam nadzieję, że opisane routing zasad jądra jest obecnie domyślnie włączony): kindlund.wordpress.com/2007/11/19/…
Savvas Radevic

Odpowiedzi:

48

możesz zastąpić kod w czasie wykonywania za pomocą LD_PRELOAD (@windows możesz użyć podobnej techniki zwanej objazdami , dość fantazyjnie). polega to na poinformowaniu dynamicznego konsolidatora, aby najpierw załadował wszystkie biblioteki lib do procesu, który chcesz uruchomić, a następnie dodał więcej na nim. zwykle używasz go w ten sposób:

% LD_PRELOAD=./mylib.so ls

i przez to zmieniacie to, co lsrobi.

dla twojego problemu spróbowałbym http://www.ryde.net/code/bind.c.txt , którego możesz użyć w następujący sposób:

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

oto jak to zbudujesz:

% 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

dłuższe howto to http://daniel-lange.com/archives/53-Binding-applications-to-a-specific-IP.html

podobne hacki i narzędzia:

akira
źródło
7
Wow, co do cholery. +1
sinni800
1
Cześć, to wydaje się naprawdę fajną sztuczką, ale dla mnie to nie działa. Mam dwa modemy 3G, które po podłączeniu otwierają dwa interfejsy (ppp0 i ppp1). Jeśli spróbuję wymusić jeden z dwóch adresów IP, zawsze kończę na tym samym interfejsie (widzę to, ponieważ mam dwa wystąpienia Wireshark, po jednym dla każdego interfejsu). Usunąłem również wydruki debugowania z bind.c i rzeczywiście widzę, że biblioteka „przeciążona” jest załadowana, więc nie wiem, dlaczego to nie działa.
Andrea Spadaccini,
3
LD_PRELOAD jest ignorowany, jeśli efektywny identyfikator UID nie jest taki sam, jak rzeczywisty identyfikator UID.
matthias krull
force_bindProjekt Catalin M. Boie obsługuje IPv6
BurnsBA
Działa świetnie, ale aby kompilacja się powiodła, musiałem dodać #include <arpa / inet.h>.
anno
31

ip netns może to zrobić.

TL; DR: Utwórz sieciowe przestrzenie nazw, powiąż z nimi interfejsy, a następnie uruchom „ip netns exec NAME cmd ...”

Tylko sprawdź, czy twoja dystrybucja obsługuje ip netns ... (Backtrack 5r3 nie, podczas gdy Kali;))

WIĘCEJ SZCZEGÓŁÓW:

#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

Dlaczego jest to lepsze niż wiązanie adresu IP za pomocą LD_PRELOAD? Ponieważ LD_PRELOAD nie kontroluje trasy używanej przez procesy. Użyje pierwszej trasy.

A ponieważ zawsze korzysta z tej samej trasy, domyślnie będzie to interfejs zarejestrowany dla trasy (co nie jest tym, czego chcemy)

olivervbk
źródło
2
Spróbuj dodać więcej szczegółów do swojej odpowiedzi.
Renju Chandran chingath
4
nie rób tego na zdalnym serwerze, jeśli eth0 jest interfejsem sieci publicznej.
ygrek
1
ostatnia linia powinna byćip netns exec myNamespace firefox
meuh
1
Użyj „sudo ip netns del <nazwa-przestrzeni-nazw>”, aby w razie potrzeby usunąć przestrzeń nazw!
Eduardo Lucio,
1
@EduardoLucio powinno być możliwe wykonanie go w następujący sposób: sudo ip netns exec myNamespace su -u someUser -c firefox
olivervbk
2

Nie sądzę, że można zmusić proces do korzystania z określonego interfejsu.

Myślę jednak, że możesz grać w ipchain / iptables i wymusić, że określony port, na którym nasłuchuje proces, będzie otrzymywać pakiety tylko przez określony interfejs.

Przydatne HOWTO: http://tldp.org/HOWTO/IPCHAINS-HOWTO.html

thetarro
źródło
2
Dwa wyżej głosowane posty dowodzą inaczej.
Paul Gear
2

Na podstawie @olivervbk odpowiedź poniżej jest moja!

Uruchom wszystkie polecenia jako „root”.

Użyj polecenia ...

ip a

... aby znaleźć nazwę interfejsu sieciowego, którego chcesz użyć.

Uruchom poniższe polecenia jako szablon ...

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] - Zamień na nazwę wybranego interfejsu sieciowego.
  • [YOUR_USER] - Zamień na swoją nazwę użytkownika.
  • [APP_NAME] - nazwa aplikacji, która zostanie uruchomiona w przestrzeni nazw „[INTERFACE_NAME] _ns”. Np .: „firefox”.

UWAGA I: Flagi „-b -u” w poleceniu „sudo” pozwalają aplikacji na uruchomienie się przy użyciu użytkownika (nie „root”) i zwolnienia terminala w tle. 2> /dev/null 1> /dev/null &Fragment jest zapobieganie wyjść z „[APP_NAME]”, która jest drukowana na terminalu.
UWAGA II: Wartości ip „10.1.1.10” i „10.1.1.1” są dowolne.
UWAGA III: Aby pracować dla mnie, musiałem uruchomić dhcpcd [INTERFACE_NAME]polecenie.

Aby usunąć przestrzeń nazw, użyj ...

ip netns del [INTERFACE_NAME]_ns

... lub ...

ip -all netns delete

... aby usunąć wszystko, co istnieje.

Eduardo Lucio
źródło
1

Zwykle jeśli program nie ma opcji ustawiania interfejsu nasłuchiwania, nasłuchuje na WSZYSTKICH interfejsach. (Możesz to zweryfikować za pomocą lsof -i).

Tworzenie reguł zapory iptables, które upuszczają przychodzący ruch skierowany w stronę portów na interfejsach, na których nie chcesz, aby były widoczne, jest najłatwiejszą rzeczą do zrobienia.

LawrenceC
źródło
1

Alternatywa I:

Użycie ld_preload do wymuszenia bramy interfejsu https://github.com/Intika-Linux-Network/App-Route-Jail

Zmusza aplikację do korzystania z określonego interfejsu sieciowego

Musimy znaleźć bramę, z której korzysta interfejs sieciowy, a następnie wymusić tę bramę do naszej uwięzionej aplikacji, a tym samym zmusić aplikację do powiązania z określonym interfejsem sieciowym

  • Jak znaleźć bramę interfejsu (istnieje wiele rozwiązań, aby znaleźć bramę tutaj są niektóre polecenia, które pozwalają znaleźć używaną bramę)
$ 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

Brama aplikacji

  • Zbuduj App-Route-Jail
git clone https://github.com/Intika-Linux-Network/App-Route-Jail.git
cd Approute-Utils
chown 755 make.sh
./make.sh
  • Dodaj trasę dla przyszłych oznaczonych pakietów (dla aplikacji uwięzionej) w tym przykładzie 192.168.1.1jest używana jako brama wymuszona, ta reguła trasy nie wpłynie na inne aplikacje, ta manipulacja musi być wykonana tylko raz przy starcie systemu, na przykład, jeśli chcesz korzystaj z tego rozwiązania codziennie
ip rule add fwmark 10 table 100
ip route add default via 192.168.1.1 table 100
  • Uruchom aplikację, którą chcesz więzić
MARK=10 LD_PRELOAD=./mark.so firefox
  • Testowanie adresu IP wan
MARK=10 LD_PRELOAD=./mark.so wget -qO- ifconfig.me

Alternatywa II:

Firejail https://firejail.wordpress.com/ może zmusić aplikację do korzystania z określonej sieci, ale kompatybilność jest ograniczona.

firejail --dns=8.8.8.8 --net=eth0 --ip=192.168.1.1
intika
źródło
Pamiętaj, że znak nie jest możliwy dla zwykłych użytkowników, musisz uruchomić jako root.
jornane
-2

Dlaczego chcesz, aby program używał interfejsu innego niż interfejs podłączony do serwera, aby komunikować się z tym serwerem? A jeśli system nie używa interfejsu podłączonego do serwera do komunikowania się z tym serwerem, jest to problem na poziomie systemu (tablica routingu) i nie ma on nic wspólnego z tym, który proces chce rozmawiać z tym serwerem.

Różne serwery w sieciach IP mają różne adresy IP. Jądro powinno wiedzieć, którego interfejsu należy użyć, aby uzyskać dostęp do określonego adresu IP na podstawie tabeli routingu. Jeśli próbujesz rozmawiać z dwoma różnymi serwerami, które mają ten sam adres IP, system się pomyli (ponieważ między innymi indeksuje połączenia tylko wewnętrznie według adresu docelowego). Możesz sprawić, by to zadziałało, ale jest to poprawka na poziomie systemu polegająca na umieszczeniu jednego serwera w osobnej sieci logicznej, która jest podłączona do komputera tylko za pośrednictwem oprogramowania NAT.

Więc jeśli mają różne adresy IP, użyj tras, aby wybrać odpowiedni interfejs. Jeśli mają ten sam adres IP, musisz użyć NAT, aby wyglądały na różne adresy IP w systemie.

David Schwartz
źródło
3
Po pierwsze, może istnieć wiele prawidłowych tras między klientem a serwerem, ale o różnych właściwościach odpowiednich dla różnych typów ruchu; np. UMTS (dane komórkowe) może kosztować, ale ma większy zasięg niż WiFi, ale oba są wolniejsze niż połączenie światłowodowe. Jeśli dostawcy wyższego szczebla przeprowadzają filtrowanie źródeł (lub NAT), nie masz innego wyjścia, jak wysłać „właściwy” interfejs. Po drugie, wpływanie na routing nie jest jedynym powodem wyboru adresu źródłowego. Nawet gdy oba adresy znajdują się na tym samym interfejsie, przydatne może być kontrolowanie, z jakim
Jeden przypadek dotyczy sytuacji, gdy masz różne publiczne adresy IP i chcesz uruchomić nowy proces dla każdego z połączeń wychodzących.
Rfraile,