GNU/Linux >> Linux Esercitazione >  >> Linux

Come trovo tutte le interfacce che sono state configurate in Linux, incluse quelle dei container?

Un'interfaccia, in un dato momento, appartiene a uno spazio dei nomi di rete e solo a uno. Lo spazio dei nomi di rete init (iniziale), ad eccezione dell'ereditarietà delle interfacce fisiche degli spazi dei nomi di rete distrutti, non ha capacità speciali rispetto ad altri spazi dei nomi di rete:non può vedere direttamente le loro interfacce. Finché sei ancora nei namespace pid e mount di init, puoi ancora trovare i namespace di rete utilizzando diverse informazioni disponibili da /proc e infine visualizzare le loro interfacce inserendo quegli spazi dei nomi di rete.

Fornirò esempi in shell.

  • enumerare gli spazi dei nomi di rete

    Per questo devi sapere come esistono quegli spazi dei nomi:fintanto che una risorsa li mantiene attivi. Una risorsa qui può essere un processo (in realtà un thread di processo), un punto di montaggio o un descrittore di file aperto (fd). Queste risorse sono tutte referenziate in /proc/ e puntano a uno pseudo-file astratto nel nsfs pseudo-filesystem che enumera tutti gli spazi dei nomi. L'unica informazione significativa di questo file è il suo inode, che rappresenta lo spazio dei nomi di rete, ma l'inode non può essere manipolato da solo, deve essere il file. Ecco perché in seguito non possiamo mantenere solo il valore dell'inode (dato da stat -c %i /proc/some/file ):manterremo l'inode per poter rimuovere i duplicati e un nome file per avere ancora un riferimento utilizzabile per nsenter più tardi.

    • processo (in realtà thread)

      Il caso più comune:per i soliti contenitori. Lo spazio dei nomi di rete di ogni thread può essere conosciuto tramite il riferimento /proc/pid/ns/net :solo stat loro ed enumerare tutti gli spazi dei nomi univoci. Il 2>/dev/null è nascondere quando stat non riesce più a trovare processi effimeri.

      find /proc/ -mindepth 1 -maxdepth 1 -name '[1-9]*' | while read -r procpid; do
              stat -L -c '%20i %n' $procpid/ns/net
      done 2>/dev/null
      

      Questo può essere fatto più velocemente con il lsns specializzato comando che si occupa degli spazi dei nomi, ma sembra gestire solo i processi (non i punti di montaggio né l'apertura di fd come visto in seguito):

      lsns -n -u -t net -o NS,PATH
      

      (che dovrebbe essere riformattato per dopo come lsns -n -u -t net -o NS,PATH | while read inode path; do printf '%20u %s\n' $inode "$path"; done )

    • punto di montaggio

      Quelli sono principalmente usati dal ip netns add comando che crea spazi dei nomi di rete permanenti montandoli, evitando così che scompaiano quando non ci sono processi o risorse fd che li mantengono attivi, permettendo quindi anche ad esempio di eseguire un router, un firewall o un bridge in uno spazio dei nomi di rete senza alcun processo collegato.

      Gli spazi dei nomi montati (la gestione degli spazi dei nomi mount e forse pid è probabilmente più complessa, ma in ogni caso siamo interessati solo agli spazi dei nomi di rete) appaiono come qualsiasi altro punto di montaggio in /proc/mounts , con il tipo di filesystem nsfs . Non esiste un modo semplice nella shell per distinguere uno spazio dei nomi di rete da un altro tipo di spazio dei nomi, ma poiché due pseudo-file dallo stesso filesystem (qui nsfs ) non condividerà lo stesso inode, basta eleggerli tutti e ignorare gli errori successivi nel passaggio dell'interfaccia quando si tenta di utilizzare un riferimento a uno spazio dei nomi non di rete come spazio dei nomi di rete. Spiacenti, di seguito non gestirò correttamente i punti di montaggio contenenti caratteri speciali, inclusi gli spazi, perché sono già sottoposti a escape in /proc/mounts (sarebbe più facile in qualsiasi altra lingua), quindi non mi preoccuperò nemmeno di usare righe con terminazione nulla.

      awk '$3 == "nsfs" { print $2 }' /proc/mounts | while read -r mount; do
              stat -c '%20i %n' "$mount"
      done
      
    • apri il descrittore di file

      Questi sono probabilmente anche più rari dei punti di montaggio, tranne temporaneamente alla creazione dello spazio dei nomi, ma potrebbero essere conservati e utilizzati da alcune applicazioni specializzate che gestiscono più spazi dei nomi, inclusa forse una tecnologia di containerizzazione.

      Non potrei escogitare un metodo migliore che cercare tutti gli fd disponibili in ogni /proc/pid/fd/ , utilizzando stat per verificare che punti a un nsfs namespace e ancora una volta non mi interessa se è davvero uno spazio dei nomi di rete. Sono sicuro che c'è un ciclo più ottimizzato, ma questo almeno non vagherà ovunque né assumerà alcun limite massimo di processo.

      find /proc/ -mindepth 1 -maxdepth 1 -name '[1-9]*' | while read -r procpid; do
              find $procpid/fd -mindepth 1 | while read -r procfd; do
                      if [ "$(stat -f -c %T $procfd)" = nsfs ]; then
                              stat -L -c '%20i %n' $procfd 
                      fi
              done
      done 2>/dev/null
      

    Ora rimuovi tutti i riferimenti allo spazio dei nomi di rete duplicati dai risultati precedenti. Ad esempio, utilizzando questo filtro sull'output combinato dei 3 risultati precedenti (specialmente dalla parte del descrittore di file aperto):

    sort -k 1n | uniq -w 20
    
  • in ogni spazio dei nomi enumera le interfacce

    Ora abbiamo i riferimenti a tutti gli spazi dei nomi di rete esistenti (e anche alcuni spazi dei nomi non di rete che semplicemente ignoreremo), inserisci semplicemente ciascuno di essi utilizzando il riferimento e visualizza le interfacce.

    Prendi l'output dei comandi precedenti come input per questo ciclo per enumerare le interfacce (e secondo la domanda dell'OP, scegli di visualizzare i loro indirizzi), ignorando gli errori causati da spazi dei nomi non di rete come spiegato in precedenza:

    while read -r inode reference; do
        if nsenter --net="$reference" ip -br address show 2>/dev/null; then
                printf 'end of network %d\n\n' $inode
        fi
    done
    

L'inode della rete init può essere stampato con pid 1 come riferimento:

echo -n 'INIT NETWORK: ' ; stat -L -c %i /proc/1/ns/net

Output di esempio (reale ma redatto) con un contenitore LXC in esecuzione, uno spazio dei nomi di rete "montato" vuoto creato con ip netns add ... avere un'interfaccia bridge non connessa, uno spazio dei nomi di rete con un altro dummy0 interfaccia, mantenuta in vita da un processo not in questo spazio dei nomi di rete ma mantenendo un fd aperto su di esso, creato con:

unshare --net sh -c 'ip link add dummy0 type dummy; ip address add dev dummy0 10.11.12.13/24; sleep 3' & sleep 1; sleep 999 < /proc/$!/ns/net &

e un Firefox in esecuzione che isola ciascuno dei suoi thread "Contenuto Web" in uno spazio dei nomi di rete non connesso (tutti quelli in basso lo interfacce):

lo               UNKNOWN        127.0.0.1/8 ::1/128 
eth0             UP             192.0.2.2/24 2001:db8:0:1:bc5c:95c7:4ea6:f94f/64 fe80::b4f0:7aff:fe76:76a8/64 
wlan0            DOWN           
dummy0           UNKNOWN        198.51.100.2/24 fe80::108a:83ff:fe05:e0da/64 
lxcbr0           UP             10.0.3.1/24 2001:db8:0:4::1/64 fe80::216:3eff:fe00:0/64 
virbr0           DOWN           192.168.122.1/24 
virbr0-nic       DOWN           
[email protected]   UP             fe80::fc8e:ff:fe85:476f/64 
end of network 4026531992

lo               DOWN           
end of network 4026532418

lo               DOWN           
end of network 4026532518

lo               DOWN           
end of network 4026532618

lo               DOWN           
end of network 4026532718

lo               UNKNOWN        127.0.0.1/8 ::1/128 
[email protected]        UP             10.0.3.66/24 fe80::216:3eff:fe6a:c1e9/64 
end of network 4026532822

lo               DOWN           
bridge0          UNKNOWN        fe80::b884:44ff:feaf:dca3/64 
end of network 4026532923

lo               DOWN           
dummy0           DOWN           10.11.12.13/24 
end of network 4026533021

INIT NETWORK: 4026531992

Linux
  1. Ottenere tutti i file che sono stati modificati in una data specifica?

  2. Come trovare tutti i file di dimensioni superiori a 1 GB in Linux?

  3. Come trovare tutti i file/cartelle con l'autorizzazione 777 in Linux?

  4. Come trovo tutti i file contenenti testo specifico su Linux?

  5. Come elencare tutti i file di una partizione su Linux?

Come trovare quali dispositivi sono collegati alla rete in Linux

Come trovare il pacchetto che fornisce un file specifico in Linux

Come scoprire lo stato connesso di un cavo di rete in Linux

Come trovare le interfacce di rete disponibili su Linux

Come trovare quale scheda grafica hai in Linux?

Come trovare tutti i caratteri installati in Linux