En mi script de iptables, he estado experimentando con la escritura de reglas tan finas como sea posible. Limito qué usuarios pueden usar qué servicios, en parte por seguridad y en parte como un ejercicio de aprendizaje.
Usando iptables v1.4.16.2 en Debian 6.0.6 ejecutando el kernel 3.6.2.
Sin embargo, he encontrado un problema que aún no entiendo ...
puertos de salida para todos los usuarios
Esto funciona perfectamente bien. No tengo reglas genéricas de seguimiento de estado.
## Puerto de salida 81 $ IPTABLES -A OUTPUT -p tcp --dport 81 -m conntrack --ctstate NUEVO, ESTABLECIDO -j ACEPTAR $ IPTABLES -A INPUT -p tcp --sport 81 -s $ MYIP -m conntrack --ctstate ESTABLISHED -j ACCEPT
puertos de salida con coincidencia de usuario
## puerto de salida 80 para cuenta de uso $ IPTABLES -A SALIDA --propietario propietario --uid-propietario useraccount -p tcp --dport 80 -m conntrack --ctstate NUEVO, ESTABLECIDO --sport 1024: 65535 -j ACEPTAR $ IPTABLES -A INPUT -p tcp --sport 80 --dport 1024: 65535 -d $ MYIP -m conntrack --ctstate ESTABLISHED -j ACCEPT
Esto permite que el puerto 80 salga solo para la cuenta "useraccount", pero reglas como esta para el tráfico TCP tienen problemas.
## Registros salientes predeterminados + reglas de bloqueo $ IPTABLES -A OUTPUT -j LOG --log-prefix "BAD OUTGOING" --log-ip-options --log-tcp-options --log-uid $ IPTABLES -A SALIDA -j DROP
La cuestión
Lo anterior funciona, el usuario "useraccount" puede obtener archivos perfectamente bien. Ningún otro usuario en el sistema puede hacer conexiones salientes al puerto 80.
useraccount @ host: $ wget http://cachefly.cachefly.net/10mb.test
Pero el wget anterior deja entradas caídas x7 en mi syslog:
18 de octubre 02:00:35 kernel xxxx: MALA SALIDA IN = OUT = eth0 SRC = xx.xx.xx.xx DST = 205.234.175.175 LEN = 40 TOS = 0x00 PREC = 0x00 TTL = 64 ID = 12170 DF PROTO = TCP SPT = 37792 DPT = 80 SEQ = 164520678 ACK = 3997126942 VENTANA = 979 RES = 0x00 ACK URGP = 0
No obtengo estas caídas para reglas similares con tráfico UDP. Ya tengo reglas establecidas que limitan qué usuarios pueden realizar solicitudes de DNS.
Los paquetes ACK salientes descartados parecen provenir de la cuenta raíz (URGP = 0) que no entiendo. Incluso cuando cambio useraccount por root.
Creo que los paquetes ACK se clasifican como nuevos porque conntrack comienza a rastrear las conexiones después del tercer paso del protocolo de enlace de 3 vías, pero ¿por qué se descartan?
¿Se pueden ignorar estas gotas de forma segura?
Editar
Así que a menudo veo reglas como estas, que funcionan bien para mí:
$ IPTABLES -A SALIDA -s $ MYIP -p tcp -m tcp --dport 80 -m estado - estado NUEVO, ESTABLECIDO -j ACEPTAR $ IPTABLES -A INPUT -p tcp -m tcp --sport 80 -d $ MYIP -m state --state ESTABLISHED -j ACCEPT
Cambié "-m state --state" por "-m conntrack --ctstate" ya que la coincidencia de estado es aparentemente obsoleta.
¿Es una buena práctica tener reglas genéricas de seguimiento de estado? ¿Las reglas anteriores no se consideran correctas?
Para un control estricto sobre las conexiones de los usuarios salientes, ¿sería mejor algo como esto?
$ IPTABLES -A ENTRADA -m conntrack --ctstate ESTABLECIDO -j ACEPTAR $ IPTABLES -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT $ IPTABLES -A OUTPUT -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate NEW -m owner --uid-owner useraccount -j ACCEPT $ IPTABLES -A OUTPUT -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate NEW -m owner --uid-owner otheraccount -j ACCEPT