GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo encuentro todas las interfaces que se han configurado en Linux, incluidas las de los contenedores?

Una interfaz, en un momento dado, pertenece a un espacio de nombres de red y solo a uno. El espacio de nombres de red init (inicial), a excepción de las interfaces físicas heredadas de espacios de nombres de red destruidos, no tiene ninguna habilidad especial sobre otros espacios de nombres de red:no puede ver directamente sus interfaces. Siempre que esté en los espacios de nombres pid y mount de init, aún puede encontrar los espacios de nombres de red utilizando diferentes informaciones disponibles en /proc y finalmente mostrar sus interfaces ingresando esos espacios de nombres de red.

Proporcionaré ejemplos en shell.

  • enumerar los espacios de nombres de red

    Para esto, debe saber cómo existen esos espacios de nombres:siempre que un recurso los mantenga. Un recurso aquí puede ser un proceso (en realidad, un hilo de proceso), un punto de montaje o un descriptor de archivo abierto (fd). Todos esos recursos están referenciados en /proc/ y apunte a un pseudo-archivo abstracto en el nsfs pseudo-sistema de archivos que enumera todos los espacios de nombres. La única información significativa de este archivo es su inodo, que representa el espacio de nombres de la red, pero el inodo no se puede manipular solo, tiene que ser el archivo. Es por eso que más adelante no podemos mantener solo el valor del inodo (dado por stat -c %i /proc/some/file ):mantendremos el inodo para poder eliminar los duplicados y un nombre de archivo para tener una referencia utilizable para nsenter más tarde.

    • proceso (en realidad hilo)

      El caso más común:para contenedores habituales. El espacio de nombres de red de cada subproceso se puede conocer a través de la referencia /proc/pid/ns/net :solo stat y enumerar todos los espacios de nombres únicos. El 2>/dev/null es ocultar cuando stat ya no puedo encontrar procesos efímeros.

      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
      

      Esto se puede hacer más rápido con el lsns especializado comando que trata con espacios de nombres, pero parece manejar solo procesos (no puntos de montaje ni fd abierto como se verá más adelante):

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

      (que tendría que reformatearse para más tarde como lsns -n -u -t net -o NS,PATH | while read inode path; do printf '%20u %s\n' $inode "$path"; done )

    • punto de montaje

      Esos son utilizados principalmente por el ip netns add comando que crea espacios de nombres de red permanentes montándolos, evitando así que desaparezcan cuando no hay ningún proceso ni recurso fd que los mantenga, y luego también permite, por ejemplo, ejecutar un enrutador, un cortafuegos o un puente en un espacio de nombres de red sin ningún proceso vinculado.

      Los espacios de nombres montados (el manejo de los espacios de nombres de montaje y quizás pid es probablemente más complejo, pero de todos modos solo nos interesan los espacios de nombres de red) aparecen como cualquier otro punto de montaje en /proc/mounts , con el tipo de sistema de archivos nsfs . No hay una manera fácil en shell de distinguir un espacio de nombres de red de otro tipo de espacio de nombres, pero como dos pseudoarchivos del mismo sistema de archivos (aquí nsfs ) no compartirá el mismo inodo, solo selecciónelos todos e ignore los errores más adelante en el paso de la interfaz cuando intente usar una referencia de espacio de nombres que no sea de red como espacio de nombres de red. Lo siento, a continuación no manejaré correctamente los puntos de montaje con caracteres especiales, incluidos los espacios, porque ya están escapados en /proc/mounts (sería más fácil en cualquier otro idioma), así que tampoco me molestaré en usar líneas terminadas en nulo.

      awk '$3 == "nsfs" { print $2 }' /proc/mounts | while read -r mount; do
              stat -c '%20i %n' "$mount"
      done
      
    • abrir descriptor de archivo

      Estos son probablemente incluso más raros que los puntos de montaje, excepto temporalmente en la creación del espacio de nombres, pero pueden ser retenidos y utilizados por alguna aplicación especializada que maneje múltiples espacios de nombres, incluida posiblemente alguna tecnología de contenedorización.

      No pude idear un método mejor que buscar todos los fd disponibles en cada /proc/pid/fd/ , usando stat para verificar que apunta a un nsfs espacio de nombres y, de nuevo, no me importa ahora si es realmente un espacio de nombres de red. Estoy seguro de que hay un ciclo más optimizado, pero este al menos no deambulará por todas partes ni asumirá ningún límite máximo de proceso.

      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
      

    Ahora elimine todas las referencias de espacios de nombres de red duplicados de los resultados anteriores. Por ejemplo, usando este filtro en la salida combinada de los 3 resultados anteriores (especialmente de la parte del descriptor de archivo abierto):

    sort -k 1n | uniq -w 20
    
  • en cada espacio de nombres enumere las interfaces

    Ahora que tenemos las referencias a todos los espacios de nombres de red existentes (y también algunos espacios de nombres que no son de red que simplemente ignoraremos), simplemente ingrese cada uno de ellos usando la referencia y muestre las interfaces.

    Tome la salida de los comandos anteriores como entrada a este ciclo para enumerar las interfaces (y según la pregunta de OP, elija mostrar sus direcciones), mientras ignora los errores causados ​​por espacios de nombres que no son de red como se explicó anteriormente:

    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
    

El inodo de la red de inicio se puede imprimir con pid 1 como referencia:

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

Salida de ejemplo (real pero redactada) con un contenedor LXC en ejecución, un espacio de nombres de red "montado" vacío creado con ip netns add ... tener una interfaz de puente no conectada, un espacio de nombres de red con otro dummy0 interfaz, mantenida viva por un proceso no en este espacio de nombres de red pero manteniendo un fd abierto en él, creado 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 &

y un Firefox en ejecución que aísla cada uno de sus subprocesos de "Contenido web" en un espacio de nombres de red no conectado (todos los que están abajo lo interfaces):

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. Cómo encontrar todos los usuarios de Sudo en Linux

  2. ¿Obtener todos los archivos que han sido modificados en una fecha específica?

  3. ¿Cómo encontrar todos los archivos propiedad de un usuario específico en Unix/Linux?

  4. ¿Cómo encontrar todos los archivos de más de 1 GB de tamaño en Linux?

  5. ¿Cómo encontrar todos los archivos/carpetas con permiso 777 en Linux?

Cómo encontrar qué dispositivos están conectados a la red en Linux

Cómo averiguar el estado conectado de un cable de red en Linux

Cómo encontrar interfaces de red disponibles en Linux

¿Cómo encontrar qué tarjeta gráfica tienes en Linux?

Cómo encontrar todas las fuentes instaladas en Linux

¿Cómo puedo encontrar las interfaces de red disponibles?