Con Linux iptables, ¿es posible registrar el nombre del proceso / comando que inicia una conexión saliente?

27

Me gustaría realizar un seguimiento de los procesos que inician las conexiones salientes en un escritorio Linux. Lo mejor que se me ocurre es esto:

iptables -A OUTPUT -m state --state NEW -j LOG --log-uid

Esto registra el uid / gid que inicia la conexión, pero no el nombre del proceso / comando o incluso el pid. Si pudiera obtener el pid, probablemente podría crear un script que extraiga el nombre del proceso cuando se escribe el registro, pero parece que eso ni siquiera es posible.

Idealmente, también me gustaría registrar los procesos que aceptan conexiones entrantes también.

¿Alguna idea de cómo esto podría ser posible con iptables [o cualquier otra cosa] en una caja de Linux?

Nack
fuente
Creo (no del todo seguro) que esta pregunta fue respondida en serverfault, búscala.
niXar
Personalmente, usaría sysdig para este trabajo.
Charles Duffy

Respuestas:

7

Podría escribir un programa para monitorear / proc / net / tcp, cuya salida se ve así:

obi-wan ~ # cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
   0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 4847458 1 e6060560 300 0 0 2 -1
   1: 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 4847477 1 f2e64da0 300 0 0 2 -1
   2: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 7109 1 f2e65ac0 300 0 0 2 -1
   3: 0100007F:177A 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1000        0 4864457 1 d2726540 300 0 0 2 -1
   4: 00000000:01BB 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 4847462 1 e60609c0 300 0 0 2 -1
   5: 6B00A8C0:0016 30F4B5CA:C3AB 01 00000044:00000000 01:00000031 00000000     0        0 4982752 3 f2e64940 55 4 0 2 -1
   6: 0100007F:B143 0100007F:BC5E 01 00000000:00000000 00:00000000 00000000  1000        0 2130283 1 d59cce40 21 4 1 2 -1
   7: 0100007F:BC5E 0100007F:B143 01 00000000:00000000 00:00000000 00000000  1000        0 2130285 1 d59cd2a0 21 4 0 2 -1
   8: 6B00A8C0:0016 3276C35B:8E11 01 00000000:00000000 02:000ADAB1 00000000     0        0 4982629 2 d2727260 40 4 8 2 2
   9: 6B00A8C0:0016 6500A8C0:DD5D 01 00000538:00000000 01:00000029 00000000     0        0 4864416 5 e6061b40 42 12 27 3 -1

Luego, puede relacionar los puertos abiertos con los inodos, que pueden relacionarse nuevamente con los procesos y los descriptores de archivo al hacer un enlace de lectura en los descriptores de archivo enumerados para cada proceso:

obi-wan ~ # readlink /proc/28850/fd/3
socket:[4847458]

Vea aquí que el inodo 4847458 corresponde al primer zócalo tcp en la lista anterior. La salida de netstat -tapn lo verifica por mí (y recuerda que 0x50 == 80):

obi-wan ~ # netstat -tapn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     28850/cherokee-work

Cuando el programa del monitor observe un cambio en / proc / net / tcp, analice los datos y determine si el cambio es un socket recién abierto. Luego, puede enumerar todos los descriptores de archivo para cada proceso enumerado en / proc, haciendo un enlace de lectura en cada uno para encontrar el inodo correspondiente. Una vez que encuentre eso, tiene el pid propio, del cual puede obtener cualquier otra cosa que desee, particularmente si tiene contabilidad de procesos.

Si no necesita que su notificación sea instantánea, entonces su programa de monitoreo podría usar una encuesta lenta (quizás un período de 50 ms o 100 ms, o incluso 1000 ms).

Ben Collins
fuente
2
¡Gracias por proporcionar una opción! Pero exigir sondeos y consultas cada descriptor de archivo abierto cada vez no es muy robusto y es muy ineficiente. Todavía espero que alguien encuentre una mejor solución, o aclare por qué esto ya no es parte de iptables, y por qué --cmd-owner se considera inamovible.
nealmcb
A menos que el núcleo cambie su diseño de / proc o a menos que netstat y readlink o ps cambien (poco probable), diría que esto es bastante robusto. ¿Qué tipo de problemas de eficiencia le preocupan? Si desea un procesamiento instantáneo, deberá escribir un módulo del núcleo para usarlo con iptables.
Ben Collins
Si estoy registrando conexiones rechazadas, el núcleo destruye el socket inmediatamente, por lo que tengo muy pocas posibilidades de verlo en / proc. Tal vez solo cambie el RECHAZO a DROP para que se agote el tiempo de conexión ...
Marki555
No ayuda en este escenario debido a la ventana de tiempo súper pequeña, pero en lo que respecta a la fragilidad del análisis / proceso, uno también podría usar "lsof -F -i" y obtener un volcado de la red muy bien abstraído datos. Eso también se puede filtrar (por ejemplo, solo en un puerto específico), y ya ha hecho todo el mapeo de nombre de archivo / pid / usuario por usted.
dannysauer
9

Desea el módulo de coincidencia del propietario, que solo funciona en la cadena OUTPUT (y tal vez PREROUTING ...?). Lea los documentos, pero funcionará de la siguiente manera:

iptables --append OUTPUT -m owner --cmd-owner "$app" \
--jump LOG --log-level DEBUG --log-prefix "OUTPUT $app packet died: "

fuente
1
¿Puede un comando de registro de iptables establecer e interpolar una variable de esta manera? No parece funcionar para mí. Además, parece que la opción --cmd-owner se eliminó en el kernel> = 2.6.15. Esto es lamentable, porque parece una opción útil.
44
Sí, --cmd-owner fue eliminado: "roto no reparable"
guettli
1
Gracias por la información, @guettli. Hay más detalles en permalink.gmane.org/… que cita más del registro de cambios: "[NETFILTER]: Elimine el abuso tasklist_lock en el propietario ipt {, 6}; Extraiga la coincidencia cmd / sid / pid ya que su archivo fijo no funciona y se encuentra en la forma de bloquear los cambios en tasklist_lock ". Pero todavía me gustaría tener más antecedentes o mejores alternativas.
nealmcb
5

Nada que ver con iptables o registro; pero aquí hay una interfaz similar a "superior" que sondea el directorio / proc / y muestra el ancho de banda por programa / pid:

http://sourceforge.net/projects/nethogs

"NetHogs es una pequeña herramienta 'net top'. En lugar de desglosar el tráfico por protocolo o por subred, como la mayoría de las herramientas, agrupa el ancho de banda por proceso. NetHogs no depende de un módulo especial del núcleo para cargar".

Lokal
fuente
He descubierto que los nethogs dan estadísticas poco confiables, pero en la parte superior 2 (+ netatop) lo hace bien.
Tobu
1

Cuando estoy investigando una pregunta similar, tratando de limitar la velocidad de Skype, he encontrado

$ netstat -p | grep <mycmdname>

es una buena forma de vincular el número de puerto a pid / cmd, ahora que pid-owner / cmd-owner ya no se admite directamente en iptables; luego deberá analizar el resultado, luego agregar la regla de iptables de acuerdo con el puerto; naturalmente, necesitará un código de limpieza después / al apagar / reiniciar el sistema, etc. guarde el / los número / s de puerto en un archivo para referencia en el momento de la limpieza

de hecho, una buena respuesta a la pregunta de números de puerto es

$ sudo netstat -p | grep "tcp.*<mycmdname>" | sed -r "s/.*<MYCOMPUTER>:([0-9]+).*/\1/"`

es posible que deba ajustar el elemento grep tcp de acuerdo con sus necesidades

entonces, para mis propósitos, era más simple agregar filtros tc u32 de acuerdo con los números de puerto, las entradas de iptables de acuerdo con los números de puerto similares

marca
fuente