Regla de IPTables para permitir conexiones SSH entrantes

11

El objetivo de este script es permitir solo el tráfico a través de la VPN, excepto el localhost <-> localhost y el tráfico entrante SSH. Pero cuando ejecuto el script sobre SSH, me desconecto y me veo obligado a reiniciar el vm. ¿Qué tiene de malo mi guión?

#!/bin/bash
iptables -F

#Allow over VPN
iptables -A INPUT -i tun+ -j ACCEPT
iptables -A OUTPUT -o tun+ -j ACCEPT

#Localhost
iptables -A INPUT -s 127.0.0.1/8 -j ACCEPT
iptables -A OUTPUT -d 127.0.0.1/8 -j ACCEPT

#VPN
iptables -A INPUT -s 123.123.123.123 -j ACCEPT
iptables -A OUTPUT -d 123.123.123.123 -j ACCEPT

#SSH
iptables -A INPUT -p tcp --dport ssh -j ACCEPT

#Default Deny
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
Steven
fuente

Respuestas:

10

La cadena de salida es responsable de cualquier paquete que salga.

Su secuencia de comandos solo permite paquetes salientes a la interfaz de túnel, host local y host remoto en 123.123.123.123.

Si se está conectando al servidor de una manera que requiere que el demonio SSH envíe paquetes al destino que no sea uno de los anteriores, no se permitirá que salga el tráfico.

Para permitir paquetes salientes desde su demonio SSH al cliente SSH, debe agregar la siguiente regla:

iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT

También es posible que desee agregar criterios de IP de destino a la regla anterior, si solo se conecta desde una única ubicación. Esta regla debe venir antes que la regla final de 'DROP algo más' para la cadena de salida.

holadanylo
fuente
+1 Esto funcionará y es más específico que usar una regla establecida y relacionada (haciéndola más o menos útil según el contexto).
Ricitos
Ambas respuestas geniales, ¡he aprendido mucho! ¡Probé la respuesta de @SkyDan y funciona bien!
Steven
Nitpick: la cadena de salida no es responsable de los paquetes reenviados .
Björn Lindqvist el
13

Su #SSHregla implica que ssh es una forma de comunicación unidireccional, que no lo es. Los datos se envían de ida y vuelta.

La forma normal de lidiar con esto, ya que no puede conocer el número de puerto en el lado del cliente de antemano, es permitir conexiones que se consideren "establecidas" o "relacionadas" con una conexión establecida. Para hacer esto necesitas:

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Antes de sus DROPreglas (y preferiblemente en la parte superior, ya que las reglas se procesan en orden y estas dos se aplicarán a la mayoría de los paquetes).

Hay una explicación de cómo una conexión TCP se establece aquí ; esencialmente, el hecho de que el servidor responda al paquete permitido por su #SSH INPUTregla lo hace así.

encerrada dorada
fuente
1
Esto no funcionará. Establecido significa que se han visto paquetes en ambas direcciones para una conexión TCP dada. Si solo agrega esta regla, el primer paquete saliente seguirá bloqueado.
holadanylo
2
@SkyDan Aquí hay una referencia para eso . Observe en el diagrama que cuando el servidor envía un syn / ack al cliente después de recibir el syn de apertura, la conexión se establece, lo que significa que iptables permitirá que el paquete de respuesta pase: "Una vez que ha visto un paquete (el SYN), considera la conexión como NUEVA. Una vez que ve el paquete de retorno (SYN / ACK), considera la conexión como ESTABLECIDA ". -> nuevamente: iptables ve el paquete de devolución que el servidor desea enviar, establece la conexión como está establecida y deja pasar la respuesta.
Ricitos
1
Bien, veo por qué funcionará. Es un poco oscuro, ya que el hombre de iptables solo habla de ver los paquetes en ambas direcciones, ni una palabra acerca de que los paquetes de protocolo de enlace TCP son una excepción. Gracias por la referencia!
hellodanylo
2
@SkyDan De hecho, la lógica no se aplica solo a tcp: me equivoqué al -p tcphacer alguna diferencia en este sentido, y mire la explicación posterior para UDP en esa página (es lo mismo). El punto es que el servidor responde sin saber si iptables lo permitirá o no, y cuando iptables recibe esa respuesta del servidor en el sistema local , ahora ha visto tráfico en ambas direcciones (aunque el cliente aún no lo haya hecho), considera la conexión establecida y deja salir la respuesta. El "tecnicismo" aquí depende de que el firewall esté en el medio de las dos partes.
Ricitos
1
Tienes razón allí. Alguien probablemente debería incluir esta información en el hombre de iptables.
hellodanylo