Comando per eseguire un processo figlio "offline" (nessuna rete esterna) su Linux


15

Ho un programma che vorrei testare in modalità offline senza rimuovere la mia rete attuale. Questo programma dovrebbe comunque connettersi a socket locali, inclusi socket di dominio unix e loopback. Deve anche ascoltare in loopback ed essere visibile ad altre app.

Ma i tentativi di connessione a una macchina remota dovrebbero fallire.

Mi piacerebbe avere un'utilità che funzioni come strace/ unshare/ sudoe semplicemente esegua un comando con Internet (e LAN) nascosto e tutto il resto ancora funzionante:

$ offline my-program-to-test

Questa domanda ha suggerimenti alla risposta: bloccare l'accesso alla rete di un processo?

Ci sono un paio di suggerimenti lì, come eseguire come un altro utente quindi manipolare iptables o unshare -n. Ma in entrambi i casi non conosco l'incantesimo per ottenere socket di dominio unix e loopback da condividere con il sistema principale - le risposte a questa domanda mi dicono solo come annullare la condivisione dell'intera rete.

Il programma che sto testando deve ancora connettersi al mio server X e dbus e persino essere in grado di ascoltare in loopback le connessioni da altre app sul sistema.

Idealmente, vorrei evitare di creare chroot o utenti o macchine virtuali o simili, poiché diventa altrettanto fastidioso quanto scollegare il cavo di rete. cioè il punto della domanda è come posso renderlo semplice come a sudo.

Mi piacerebbe che il processo funzionasse al 100% normalmente, tranne per il fatto che le chiamate di rete che specificano un indirizzo non locale fallirebbero. Idealmente mantenendo lo stesso uid, lo stesso homedir, lo stesso pwd, lo stesso tutto tranne ... offline.

Sto usando Fedora 18, quindi le risposte Linux non portabili vanno bene (previste, anche).

Sono anche felice di risolverlo scrivendo un programma in C, se questo è ciò che è coinvolto, quindi le risposte che implicano la scrittura in C vanno bene. Semplicemente non so quali syscalls quel programma C dovrebbe fare per revocare l'accesso alla rete esterna mantenendo la rete locale.

Qualsiasi sviluppatore che cerca di supportare la "modalità offline" apprezzerebbe probabilmente questa utility!

Risposte:


9

La risposta tradizionale è eseguire il programma come un altro utente e utilizzarlo iptables -m owner. In questo modo, la configurazione di rete è condivisa. Tuttavia, con l'avvento degli spazi dei nomi, esiste un modo più semplice.

Con gli spazi dei nomi, si annulla la condivisione della rete, quindi si crea un collegamento di rete virtuale se è necessario un accesso limitato alla rete.

Per condividere socket di dominio unix, tutto ciò che serve è avere un kernel abbastanza recente, dopo questa patch del 2010 , quindi 2.6.36 o superiore (che è il caso di tutte le distribuzioni attuali al momento della scrittura tranne RHEL / CentOS).

Esegui il programma nel suo spazio dei nomi IP. Prima di avviare il programma, stabilire un'interfaccia Ethernet virtuale. Non sembra esserci molta documentazione; Ho trovato l'incantesimo giusto in alcuni blog:

Nello snippet di seguito, utilizzo ns_execis is the this wrapper aroundsetns elencato nella pagina man per richiamare il lato host del collegamento di rete dal processo in esecuzione nello spazio dei nomi limitato. In realtà non ti serve questo: puoi impostare il lato host del link dall'esterno dello spazio dei nomi limitato. Farlo dall'interno semplifica semplicemente il controllo del flusso, altrimenti è necessario un po 'di sincronizzazione per impostare il collegamento dopo che è stato stabilito ma prima di avviare il programma.

unshare -n -- sh -c '
  # Create a virtual ethernet interface called "confined",
  # with the other end called "global" in the namespace of PID 1
  ip link add confined type veth peer name global netns 1

  # Bring up the confined end of the network link
  ip addr add 172.16.0.2/30 dev confined
  ip link set confined up

  # Bring up the global end of the network link
  ns_exec /proc/1/ns/net ifconfig global 172.16.0.1 netmask 255.255.255.252 up

  # Execute the test program
  exec sudo -E -u "$TARGET_USER" "$0" "$@"
' /path/to/program --argument

Devi fare tutto questo come root. L' introduzione di spazi dei nomi utente nel kernel 3.8 può renderlo fattibile senza autorizzazioni speciali, tranne che per l'impostazione dell'estremità globale del collegamento di rete.

Non so come condividere localhost tra i due spazi dei nomi. Le interfacce Ethernet virtuali creano un bridge point-to-point. Se lo desideri, puoi utilizzare le iptablesregole di inoltro per reindirizzare il traffico da / a lo.


Buone informazioni aggiuntive, grazie. Penso che veth mi dia un link "esterno" allo spazio dei nomi, ma il mio nuovo spazio dei nomi equivale ancora a un nodo di rete separato, anziché allo stesso nodo di rete meno le interfacce non locali. Le implicazioni sono: -changing) le porte dovrebbero essere visibili in entrambi gli spazi dei nomi ... iniziare a indovinare ciò che voglio è impossibile qui: - /
Havoc P

1

Questo può essere ottenuto anche con cgroups corrispondenti alla regola iptables. Ho scritto uno strumento per astrarre i passaggi. Mentre richiede i permessi di root per l'installazione iniziale ed è altrimenti un binario setuid, penso che offra un modo abbastanza semplice per affrontare il problema nella domanda. Richiede una versione di iptables abbastanza recente e che siano disponibili i moduli netfilter appropriati.

https://github.com/quitesimpleorg/qsni


0

/ !! \ Probabilmente questa non è una risposta valida poiché porterà tutto il tuo traffico con te, non solo il traffico di un singolo pid.

Non l'ho usato, ma penso che potresti potenzialmente usare Comcast:

https://github.com/tylertreat/Comcast

impostato su 100% di perdita di pacchetti

Ancora una volta, non ho testato questo, ma teoricamente, modificato dal loro readme puoi fare:


Linux

Su Linux, è possibile utilizzare iptablesper eliminare i pacchetti in entrata e in uscita.

$ iptables -A INPUT -m statistic --mode random --probability 1 -j DROP
$ iptables -A OUTPUT -m statistic --mode random --probability 1 -j DROP

In alternativa, è possibile utilizzare tcche supporta alcune opzioni aggiuntive.

$ tc qdisc change dev eth0 root netem reorder 0 duplicate 0 corrupt 1

Resettare:

$ tc qdisc del dev eth0 root netem
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.