Un cliente necesita llegar al servicio SSH de otro cliente, y el resto del grupo debe seguir tan aislado como hoy. El interruptor tentador es client-to-client, que activa el acceso entre pares para todos a la vez y entrega la decisión a OpenVPN en lugar del núcleo. Una respuesta más estrecha mantiene ese interruptor apagado y deja que el enrutamiento y el cortafuegos del propio servidor lleven exactamente un flujo.

El mecanismo importa más que el texto de la regla, porque los dos enfoques colocan el paquete en lugares distintos. Saber cuál elegiste explica tanto la regla que parece no hacer nada como el par que se conecta sin ella.

Dónde mueve el paquete client-to-client

Con client-to-client activado, el servidor retransmite un paquete de par internamente en lugar de enviarlo de vuelta por el dispositivo de túnel, así que el paquete nunca llega a la ruta de reenvío del núcleo. Eso es cómodo y también significa que tu cortafuegos nunca ve el flujo que debería vigilar. Déjalo desactivado y el servidor encamina el paquete de vuelta por la misma interfaz, lo que lo pone delante de netfilter. La misma interfaz a la entrada, la misma a la salida, y la cadena FORWARD tiene el voto.

El intercambio es explícito: ganas un punto de política y asumes el trabajo de enrutamiento y reenvío que el atajo hacía por ti. Ese trabajo es pequeño para un solo flujo y crece con cada excepción que añades. Cuenta las excepciones ahora, porque el conjunto de reglas es donde vive de verdad la política entre pares.

La ruta que sigue realmente un paquete de par

Supón un servicio OpenVPN 2.6 Community sobre Linux, procesamiento TUN en espacio de usuario en lugar de DCO, topología de subred, tun0 y un grupo de 10.44.0.0/24 con el cliente A en 10.44.0.21 y el cliente B en 10.44.0.37. Con topología de subred, la dirección y la máscara que recibió A ya cubren el grupo, así que A envía el paquete al dispositivo de túnel sin necesidad de una ruta empujada extra. Comprueba la ruta efectiva en A en lugar de suponer una.

En el servidor, el paquete llega dirigido a B, que no es una dirección local, así que se reenvía. El reenvío IPv4 tiene que estar activado para que eso ocurra, y la consulta de ruta tiene que enviar el paquete de vuelta por tun0. Por tanto el cortafuegos ve un flujo reenviado con la misma interfaz en ambos lados, y ese es el detalle que casi todos los conjuntos de reglas pasan por alto. Aquí no hace falta traducción de origen, y mantener intacta la dirección de A es lo que permite que B aplique su propia regla basada en el origen.

Dos reglas en el servidor, en este orden

Tres reglas llevan toda la concesión: el reenvío, la excepción del par y un descarte por defecto para el par de túnel. La regla de aceptación nombra el par y el servicio, así que la concesión sobrevive a un grupo que crece. Colócala antes de cualquier denegación general del tráfico túnel a túnel, porque gana la primera coincidencia:

sysctl -w net.ipv4.ip_forward=1
iptables -A FORWARD -i tun0 -o tun0 -s 10.44.0.21 -d 10.44.0.37 -p tcp --dport 22 -j ACCEPT
iptables -A FORWARD -i tun0 -o tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i tun0 -o tun0 -j DROP

Esos comandos son ilustrativos y pertenecen al mecanismo que use tu anfitrión para persistir reglas; una inserción en tiempo de ejecución desaparece en el siguiente arranque. La regla con estado es la que permite que las respuestas de B y el apretón de manos TCP vuelvan sin una segunda aceptación espejo.

Comprueba los contadores después, no el listado de reglas, porque una regla que nunca coincide es idéntica a una que funciona. Si los contadores se quedan a cero, el paquete no sigue el camino que crees.

Lo que B aún debe permitir

B ejecuta el servicio SSH, así que B decide si algo escucha en la dirección del túnel y si su propio cortafuegos acepta el origen. Un permiso de red en el servidor no es permiso para ninguna cuenta de B, y la verificación de la clave del anfitrión y la autenticación de usuario siguen aplicándose como desde cualquier otro sitio.

Prueba primero el caso positivo: una conexión SSH nueva de A a la dirección del túnel de B, aceptada con la clave de anfitrión esperada. Luego prueba otro par u otro puerto y confirma que se rechaza, porque una concesión que permite todo en silencio es indistinguible de una que funciona hasta que importa. Las dos mitades de esa prueba son necesarias, y la segunda es la que la gente se salta.

Anota las direcciones asignadas, las rutas efectivas en ambos clientes y las reglas exactas en el servidor y en B. Un ping correcto a la puerta de enlace o un puerto abierto en el servidor no demuestra nada de esto, ya que ambas cosas pueden ser ciertas mientras el reenvío entre pares sigue bloqueado. Escribe esos números con el túnel levantado, porque la dirección que un cliente recibe tras reconectarse puede ser otra.

Artículos relacionados