Comando para ejecutar un proceso hijo "sin conexión" (sin red externa) en Linux

15

Tengo un programa que me gustaría probar en modo fuera de línea sin desconectar mi red real. Este programa aún necesitaría conectarse a sockets locales, incluidos los sockets de dominio Unix y el loopback. También necesita escuchar en loopback y ser visible para otras aplicaciones.

Pero los intentos de conectarse a una máquina remota deberían fallar.

Me gustaría tener una utilidad que funcione como strace/ unshare/ sudoy simplemente ejecute un comando con Internet (y LAN) oculto y todo lo demás sigue funcionando:

$ offline my-program-to-test

Esta pregunta tiene pistas sobre la respuesta: ¿ Bloquear el acceso a la red de un proceso?

Hay un par de sugerencias allí, como ejecutar como otro usuario y luego manipular iptables, o unshare -n. Pero en ambos casos no conozco el encantamiento para que los sockets de dominio Unix y el loopback se compartan con el sistema principal; las respuestas a esa pregunta solo me dicen cómo dejar de compartir toda la red.

El programa que estoy probando todavía necesita conectarse a mi servidor X y dbus e incluso poder escuchar en el loopback las conexiones de otras aplicaciones en el sistema.

Idealmente, me gustaría evitar crear chroots o usuarios o máquinas virtuales o similares, ya que se vuelve tan molesto como desconectar el cable de red. es decir, el punto de la pregunta es cómo puedo hacer esto tan simple como a sudo.

Me encantaría que el proceso se ejecute al 100% normalmente, excepto que las llamadas de red que especifican una dirección no local fallarían. Lo ideal es mantener el mismo uid, el mismo homedir, el mismo pwd, el mismo todo excepto ... sin conexión.

Estoy usando Fedora 18, por lo que las respuestas de Linux no portables están bien (incluso se espera).

Incluso estoy feliz de resolver esto escribiendo un programa en C, si eso es lo que está involucrado, por lo que las respuestas que involucran escribir en C están bien. Simplemente no sé qué syscalls necesitaría hacer el programa C para revocar el acceso a la red externa mientras se mantiene la red local.

¡Cualquier desarrollador que intente admitir el "modo fuera de línea" probablemente agradecería esta utilidad!

Caos P
fuente

Respuestas:

9

La respuesta tradicional es ejecutar el programa como otro usuario y usarlo iptables -m owner. De esa manera, la configuración de red es compartida. Sin embargo, con la llegada de los espacios de nombres, hay una manera más fácil.

Con espacios de nombres, no comparte la red, luego crea un enlace de red virtual si necesita acceso limitado a la red.

Para compartir sockets de dominio Unix, todo lo que necesita es tener un kernel suficientemente reciente, después de este parche de 2010 , entonces 2.6.36 o superior (que es el caso en todas las distribuciones actuales en el momento de la escritura, excepto RHEL / CentOS).

Ejecute el programa en su propio espacio de nombres IP. Antes de iniciar el programa, establezca una interfaz virtual de ethernet. No parece haber mucha documentación; Encontré el encantamiento correcto en algunos blogs:

En el siguiente fragmento, yo uso el ns_execes el este envoltura alrededorsetns enumerados en la página del manual para abrir el lado del host de la conexión de red del proceso que se ejecuta en el espacio de nombres restringido. En realidad no necesita esto: puede configurar el lado del host del enlace desde fuera del espacio de nombres restringido. Hacerlo desde adentro simplemente facilita el control de flujo; de lo contrario, necesitará algo de sincronización para configurar el enlace después de que se haya establecido, pero antes de iniciar su programa.

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

Necesita hacer todo esto como root. La introducción de espacios de nombres de usuario en el kernel 3.8 puede hacer que esto sea factible sin permisos especiales, excepto configurar el final global del enlace de red.

No sé cómo compartir localhost entre los dos espacios de nombres. Las interfaces virtuales de Ethernet crean un puente punto a punto. Puede usar iptablesreglas de reenvío para redirigir el tráfico de / a losi lo desea.

Gilles 'SO- deja de ser malvado'
fuente
Buena información adicional, gracias. Creo que veth me da un enlace a "fuera" del espacio de nombres, pero mi nuevo espacio de nombres todavía equivale a un nodo de red separado, en lugar del mismo nodo de red menos las interfaces no locales. Las implicaciones son (?): El dominio Unix / los sockets abstractos todavía fallarían, y el bucle invertido podría reenviarse a través de iptables, pero el reenvío no logra compartir, es decir, tanto el espacio de nombres original como el restringido pueden estar escuchando en bucle invertido y ambos conjuntos de (dinámicamente -cambiando) los puertos tendrían que ser visibles en ambos espacios de nombres ... comenzar a adivinar lo que quiero es imposible aquí: - /
Havoc P
1

Esto también se puede lograr con cgroups de reglas de iptables. Escribí una herramienta para abstraer los pasos. Si bien requiere permisos de root para la configuración inicial y, de lo contrario, es un binario setuid, creo que ofrece una forma bastante directa de abordar el problema en la pregunta. Requiere una versión de iptables que sea lo suficientemente reciente y que tenga disponibles los módulos netfilter adecuados.

https://github.com/quitesimpleorg/qsni

crtxcr
fuente
0

/ !! \ Probablemente esta no sea una respuesta válida, ya que reducirá todo tu tráfico contigo, no solo el tráfico de un solo pid.

No lo he usado, pero creo que potencialmente podrías usar Comcast:

https://github.com/tylertreat/Comcast

establecido en 100% de pérdida de paquetes

Nuevamente, no he probado esto, pero teóricamente, modificado a partir de su archivo Léame, puede hacer:


Linux

En Linux, puede usar iptablespara descartar paquetes entrantes y salientes.

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

Alternativamente, puede usar el tcque admite algunas opciones adicionales.

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

Reiniciar:

$ tc qdisc del dev eth0 root netem
ThorSummoner
fuente