¿Cómo limitar los puertos de tunelización SSH inversa?

9

Tenemos un servidor público que acepta conexiones SSH de múltiples clientes detrás de firewalls.

Cada uno de estos clientes crea un túnel SSH inverso mediante el ssh -Rcomando de sus servidores web en el puerto 80 a nuestro servidor público.

El puerto de destino (en el lado del cliente) del túnel SSH inverso es 80 y el puerto de origen (en el lado del servidor público) depende del usuario. Estamos planeando mantener un mapa de direcciones de puerto para cada usuario.

Por ejemplo, el cliente A haría un túnel en su servidor web en el puerto 80 a nuestro puerto 8000; cliente B de 80 a 8001; cliente C de 80 a 8002.

Client A: ssh -R 8000:internal.webserver:80 clienta@publicserver

Client B: ssh -R 8001:internal.webserver:80 clientb@publicserver

Client C: ssh -R 8002:internal.webserver:80 clientc@publicserver

Básicamente, lo que estamos tratando de hacer es vincular a cada usuario con un puerto y no permitirles hacer un túnel a ningún otro puerto.

Si estuviéramos usando la función de tunelización directa de SSH con ssh -L, podríamos permitir qué puerto se tunelizaría usando la permitopen=host:portconfiguración. Sin embargo, no hay equivalente para el túnel SSH inverso.

¿Hay alguna forma de restringir los puertos de túnel inverso por usuario?

Utku Zihnioglu
fuente
1
Solo por políticas de todo el sistema como SELinux o IPTABLES.
Andrew Smith

Respuestas:

6

Dado que ha colocado no permitir en negrita, supongo que desea algún tipo de rechazo en tiempo de ejecución en el lado del cliente SSH que impide el enlace del puerto. Entonces, he cavado el código fuente para ti:

serverloop.c:

/* check permissions */
if (!options.allow_tcp_forwarding ||
    no_port_forwarding_flag ||
    (!want_reply && listen_port == 0)
#ifndef NO_IPPORT_RESERVED_CONCEPT
    || (listen_port != 0 && listen_port < IPPORT_RESERVED &&
    pw->pw_uid != 0)
#endif
    ) {
        success = 0;
        packet_send_debug("Server has disabled port forwarding.");
} else {
        /* Start listening on the port */
        success = channel_setup_remote_fwd_listener(
            listen_address, listen_port,
            &allocated_listen_port, options.gateway_ports);
}

Desafortunadamente, como puede ver, no hay muchas condiciones que parezcan evitar el reenvío de puertos aparte de las estándar.

Estaba a punto de recomendar la misma sugerencia para usar mod_ownerdentro iptables, pero Jeff me ha convencido.

Su solución más limpia sería simplemente modificar este archivo (por ejemplo, puede usarlo pw->pw_uidpara obtener la conexión del usuario del usuario y asignarlo al puerto correcto) y recompilar su servidor SSH, pero eso dependería de qué tan cómodo se sienta con esto. .

Arrendajo
fuente
Esto es realmente bueno. De hecho, puedo copiar la misma sintaxis de la opción -L (tunelización) y hacer que funcione. Gracias.
Utku Zihnioglu
3

Mi sugerencia es usar SELinux para esto. Tendrá que configurar perfiles de usuario que permitan qué puertos se abrirán. El sshdproceso se bifurca y cae a los privilegios del usuario antes de abrir un puerto para reenviar, por lo que todo lo aplicado a los procesos del usuario se aplicará sshd. Tenga en cuenta que deberá restringir todos los procesos del usuario, ya que una vez podría utilizar netcatpara reenviar otro puerto. Intentaré resolver la sintaxis adecuada para usted más tarde (o cualquier otro usuario puede editarlo).

Alternativamente, puede intentar usar iptables.

iptables -m owner --add-owner $user -p tcp --sport 8000 -j ACCEPT
iptables -m owner --add-owner $user -p tcp --tcp-flags SYN,ACK SYN,ACK -j REJECT

Sin embargo, eso no les impedirá abrir el puerto y negar a otro usuario.

Jeff Ferland
fuente
Gracias por la gran respuesta. Probaré la configuración de los perfiles de SELinux / Usuario. Suena como la solución a mi pregunta.
Utku Zihnioglu