Associare il programma unix all'interfaccia di rete specifica


40

Domanda: Come posso avviare un programma assicurandomi che il suo accesso alla rete sia collegato tramite una specifica interfaccia di rete?

Caso: voglio accedere a due macchine distinte con lo stesso IP (192.168.1.1), ma accessibile tramite due diverse interfacce di rete (eth1 ed eth2).

Esempio:

net-bind -D eth1 -exec {Program 192.168.1.1}
net-bind -D eth2 -exec {Program 192.168.1.1}

Quanto sopra è un'approssimazione di ciò che mi piacerebbe, ispirato dall'associazione hardware effettuata tramite primusrun e optirun .

Sfida: come suggerito in un thread correlato , le interfacce utilizzate non sono scelte dal programma, ma piuttosto dal kernel (da qui la sintassi di pre-binding nell'esempio sopra).

Ho trovato alcune soluzioni correlate, che sono insoddisfacenti. Si basano su interfacce di rete vincolanti tramite blacklist di reti specifiche dell'utente; cioè, eseguendo il processo come utente che può accedere solo a una singola interfaccia di rete specifica.


Stai insinuando che la tua macchina è connessa a due reti diverse, entrambe 192.168.1.0? Che aspetto ha la tua tabella di routing? Se si desidera limitare le interfacce visibili da un processo, la soluzione più leggera sarebbe cgroups, un contenitore più pesante.
Lgeorget,

Sì, due reti diverse, entrambe sullo stesso intervallo IP. Non sono sicuro di non voler limitare le interfacce visibili, basta dettare quale utilizzare come predefinito? :)
Skeen,

3
Quello che chiedi è difficile per una buona ragione: avere due reti interconnesse usando lo stesso dominio IP è come avere un ascensore in un edificio a due piani con lo stesso numero. L'intervallo IP è ciò che identifica il dominio e non l'interfaccia di output. Tuttavia, ci deve essere un modo per aggirare la progettazione della rete difettosa con iptables.
Lgeorget,

Sto collegando il mio sistema a due diverse infrastrutture sul posto, in quanto tali infrastrutture non sono mai state progettate per interagire, e quindi la progettazione della rete è imperfetta al riguardo.
Skeen,

1
La mia argomentazione nei confronti dei NAT era che interi spazi di indirizzi sono generalmente nascosti dietro il NAT, e mentre sto collegando due infrastrutture NAT non si verifica la collisione. - Non sono in grado di modificare l'infrastruttura. - Ho provato a utilizzare gli spazi dei nomi di rete con coppie di interfacce di rete virtuali (una nello spazio dei nomi, una nello spazio dei nomi radice) collegando uno spazio dei nomi radice all'interfaccia fisica ed eseguendo programmi all'interno dello spazio dei nomi di rete. - Questo sembra funzionare, ma non riesco ad accedere oltre lo spazio dei nomi di root (ovvero nessun accesso al di fuori della macchina stessa).
Skeen,

Risposte:


35

Per Linux, su Superuser è già stata data una risposta: come utilizzare interfacce di rete diverse per processi diversi? .

La risposta più popolare usa un LD_PRELOADtrucco per cambiare l'associazione di rete per un programma, ma i kernel moderni supportano una funzionalità molto più flessibile chiamata "spazi dei nomi di rete" che viene esposta attraverso il ipprogramma. Questa risposta mostra come usare questo. Dai miei esperimenti ho fatto quanto segue (come root):

# Add a new namespace called test_ns
ip netns add test_ns

# Set test to use eth0, after this point eth0 is not usable by programs
# outside the namespace
ip link set eth0 netns test_ns

# Bring up eth0 inside test_ns
ip netns exec test_ns ip link set eth0 up

# Use dhcp to get an ipv4 address for eth0
ip netns exec test_ns dhclient eth0

# Ping google from inside the namespace
ip netns exec test_ns ping www.google.co.uk

È anche possibile gestire gli spazi dei nomi di rete in una certa misura con i comandi unsharee nsenter. Ciò consente di creare spazi separati per PID, utenti e punti di montaggio. Per ulteriori informazioni consultare:


"dopo questo punto eth0 non è utilizzabile da programmi al di fuori dello spazio dei nomi" - Quindi sto abbattendo la connessione per tutti gli altri problemi nel fare questo?
Skeen,

1
@Skeen, sì, quindi presumibilmente potresti spingere un'interfaccia che nessun altro programma sta usando nello spazio dei nomi e usare quello principale normalmente.
Graeme,

1
@Graerne; Entrambe le interfacce vengono utilizzate attivamente; Non posso permettermi di smontare le interfacce.
Skeen,

e con il gateway predefinito? wvdialper esempio non sembra configurarlo affatto ... quindi deve essere definito nello spazio dei nomi stesso
Flash Thunder

Potresti includere istruzioni su come annullarlo? Sei solo ip netns remove test_nsper tornare alla normalità? O devi fare qualcosa di speciale?
Multihunter

17

Accetto la risposta di Graeme; questo è semplicemente un seguito per spiegare i cambiamenti che ho fatto al suo suggerimento per risolvere il mio problema.

Invece di associare l'interfaccia fisica all'interno dello spazio dei nomi, ho creato una coppia di interfacce di rete virtuale, con un'estremità nello spazio dei nomi di rete e una nella radice. I pacchetti vengono quindi instradati tramite questa rete virtuale dallo spazio dei nomi, allo spazio dei nomi radice e quindi all'interfaccia fisica. - Come tale sono in grado di eseguire tutti i miei normali trasferimenti di dati e inoltre avviare processi che possono accedere solo a un'interfaccia specifica.

# Create the eth0 network namespace
ip netns add eth0_ns

# Create the virtual network pair
ip link add v_eth0a type veth peer name v_eth0b

# Move v_eth0a to the eth0_ns namespace, the virtual pair is now split
# between two network namespaces.
ip link set v_eth0a netns eth0_ns

# Configure the ends of the virtual network pairs
ip netns exec eth0_ns ifconfig v_eth0a up {{NAMESPACE_IP}} netmask {{NAMESPACE_NETMASK}}
ifconfig v_eth0b up {{ROOT_NS_IP}} netmask {{ROOT_NS_NETMASK}}

# Setup routing from namespace to root
ip netns exec eth0_ns route add default gw {{ROOT_NS_IP}} dev v_eth0a

# Setup IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s {{ROUTE_SOURCE}}/24 -o {{NETWORK_INTERFACE}} -j SNAT --to-source {{ROUTE_TARGET}}

Dopo aver configurato le interfacce per eth0 ed eth1, con i rispettivi spazi dei nomi eth0_ns e eth1_ns, i programmi possono essere eseguiti sull'interfaccia specificata tramite;

ip netns exec eth0_ns fish
ip netns exec eth1_ns fish

4
Molto bene! Penso che puoi anche creare un dispositivo bridge e collegare lo spazio dei nomi predefinito e la coppia virtuale con uno dei dispositivi fisici. Questo sembra equivalente però.
Graeme,

1
Ho provato a collegare il dispositivo virtuale e fisico; Non sono riuscito a raggiungere la rete esterna usando quella soluzione.
Skeen,

2
L'ho fatto, ma solo dal nuovo spazio dei nomi. Penso che il problema che stavo riscontrando riguardasse il gestore della rete, ma non l'ho capito o avrei aggiornato la mia risposta.
Graeme,

Ho lo stesso problema, ma non sono riuscito a utilizzare quella soluzione. Cosa devo inserire esattamente in {{ROUTE_SOURCE}} e {{ROUTE_TARGET}} nell'ultimo passaggio?
Litov

@Graeme, almeno su Ubuntu sono stato in grado di tornare connettività sia spazio dei nomi, così come lo spazio dei nomi globale mediante l'emissione di dhclient <bridge>ogni qui .
Chris Hunt,

4

Soluzione I: precaricamento di una libreria specifica

  • App-Route-Jail : usa ld_preload per forzare il gateway dell'interfaccia (ottima idea ma richiedono funzionalità di root o mark) l'uso è dettagliato nelle note seguenti

  • Proxybound : usa ld_preload per forzare un proxy a un'applicazione specifica (utilizza proxy anziché interfaccia)

  • Force-Bind : ha molte funzionalità ma il bind perde (non affidabile)

  • Bind-Interface-IP : connessioni troppo semplici e con perdite (non affidabili)

  • Bind-IP : connessioni troppo semplici e con perdite (non affidabili)

Soluzione II: spazio utenti Linux

  • Spazio utente linux classico ip-netns : ottima soluzione ma richiede root e l'interfaccia può esistere solo su un singolo spazio utente

  • Firejail : Firejail può forzare un'applicazione a utilizzare una rete specifica, ma la compatibilità è limitata (ad esempio non è compatibile con le interfacce tun). firejail non richiede rootfirejail --dns=8.8.8.8 --noprofile --net=eth0 --ip=192.168.1.1 app-command

  • Firejail con netns : Firejail può forzare un'applicazione a utilizzare uno spazio utente specifico creato separatamente, questo ci permette di nominare gli spazi senza rootfirejail --dns=8.8.8.8 --noprofile --netns=nameOfyourNS app-command

  • Firejail con mascheramento e bridge : Firejail può forzare un'applicazione a utilizzare un'interfaccia specifica con mascheramento di iptables , è eccezionale e non richiede root ma richiede ip_forward e potrebbe implicare un impatto sulla sicurezzafirejail --net=br0 firefox

Soluzione III: iptables Linux

Iptables potrebbe essere utilizzato per questo scopo, ma ciò richiede ip_forward e potrebbe implicare un impatto sulla sicurezza se non configurato correttamente, esempio 1 , esempio 2 , esempio 3 , esempio 4

Note sulle soluzioni (I, II e III):

Gabbia di protezione

Se si utilizza una VPN (in particolare wireguard) e si desidera applicare questa soluzione a un'interfaccia wireguard ( wireguard con spazio utente ), è possibile seguire il collegamento indicato per creare uno spazio utente contenente un'interfaccia wg (e quindi limitato a un'interfaccia vpn ) anche questo può essere combinato con firejail --netns=containerper poter utilizzare lo spazio utente senza root.

Come trovare il gateway dell'interfaccia

Esistono molte soluzioni per trovare il gateway qui ci sono alcuni comandi che consentono di trovare il gateway utilizzato

$ 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

Come usare App-Route-Jail

  • Crea App-Route-Jail
git clone https://github.com/Intika-Linux-Network/App-Route-Jail.git
cd Approute-Utils
chown 755 make.sh
./make.sh
  • Aggiungere una route per i futuri pacchetti contrassegnati (per l'applicazione jailed) in questo esempio 192.168.1.1viene utilizzata come gateway forzato, questa regola di route non influirà su altre applicazioni, questa manipolazione deve essere eseguita una sola volta all'avvio del sistema, ad esempio se si desidera usa questa soluzione ogni giorno
ip rule add fwmark 10 table 100
ip route add default via 192.168.1.1 table 100
  • Avviare l'applicazione che si desidera imprigionare
MARK=10 LD_PRELOAD=./mark.so firefox
  • Test dell'indirizzo IP pallido
MARK=10 LD_PRELOAD=./mark.so wget -qO- ifconfig.me
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.