¿Cómo crear un usuario SSH restringido para el reenvío de puertos?

90

ændrük sugirió una conexión inversa para obtener una conexión SSH fácil con otra persona (para obtener ayuda remota). Para que eso funcione, se necesita un usuario adicional para aceptar la conexión. Este usuario debe poder reenviar su puerto a través del servidor (el servidor actúa como proxy).

¿Cómo creo un usuario restringido que no puede hacer nada más que lo descrito anteriormente?

El nuevo usuario debe no ser capaz de:

  • ejecutar comandos de shell
  • accede a archivos o sube archivos al servidor
  • usa el servidor como proxy (por ejemplo, webproxy)
  • accede a los servicios locales que de otro modo no eran públicamente accesibles debido a un firewall
  • matar al servidor

Resumido, ¿cómo creo un usuario SSH restringido que solo puede conectarse al servidor SSH sin privilegios, así que puedo conectarme a través de esa conexión con su computadora?

    
pregunta Lekensteyn 10.06.2011 - 20:04

2 respuestas

142

TL; DR: vaya a la parte inferior de la respuesta, "Aplicar las restricciones"

Agregar un usuario restringido consta de dos partes: 1. Creando el usuario 2. Configurando el daemon SSH (sshd)

Configurando sshd

El mejor lugar para conocer las posibilidades de SSH es leyendo las páginas de manual relacionadas:

  • ssh (1)
  • ssh_config (5)
  • sshd (8)
  • sshd_config (5)

¿Dónde puede el cliente SSH realizar acciones?

Antes de que pueda restringir algo, necesita conocer las características de SSH. Escupir a través de las páginas de manual produce:

  • Ejecución de comandos de Shell
  • Carga de archivos a través de sftp
  • Reenvío de puertos
    • El cliente reenvía un puerto (no) usado al servidor
    • El servidor reenvía su puerto al cliente
    • El servidor reenvía un puerto de otro host al cliente (proxy-ish)
  • Reenvío de X11 (reenvío de visualización)
  • Reenvío del agente de autenticación
  • Reenvío de un dispositivo de túnel

En la sección Autenticación de la página de manual de sshd (8) :

  

Si el cliente se autentica correctamente, un diálogo para preparar   la sesión es ingresada En este momento, el cliente puede solicitar cosas como    asignando un pseudo-tty, reenviando conexiones X11, reenviando TCP   conexiones, o reenviar la conexión del agente de autenticación sobre el   canal seguro.

     

Después de esto, el cliente solicita un shell o la ejecución de un comando .   Los lados luego entran al modo de sesión. En este modo, cualquiera de los lados puede enviar   datos en cualquier momento, y tales datos se envían a / desde el shell o comando   en el lado del servidor, y el terminal de usuario en el lado del cliente.

Opciones para restringir las características SSH

Los archivos y sus opciones que modifican el comportamiento son:

  • ~/.ssh/authorized_keys - contiene claves a las que se les permite conectarse a las que se les pueden dar opciones:
    • command="command" - El comando proporcionado por el usuario (si lo hay) se ignora. Tenga en cuenta que el cliente puede especificar el reenvío TCP y / o X11 a menos que estén explícitamente prohibidos . Tenga en cuenta que esta opción se aplica a la ejecución de shell, comandos o subsistemas.
    • no-agent-forwarding - Prohibe el reenvío del agente de autenticación cuando esta clave se usa para autenticación.
    • no-port-forwarding - Prohibe el reenvío de TCP cuando esta clave se usa para la autenticación
    • no-X11-forwarding - "Prohibe el reenvío de X11 cuando esta clave se usa para autenticación."
    • permitopen="host:port" - Limita el reenvío del puerto 'ssh -L' local de modo que solo se pueda conectar al host y puerto especificados.
  • ~/.ssh/environment - Este archivo se lee en el entorno al iniciar sesión (si existe). El procesamiento del entorno está deshabilitado de forma predeterminada y se controla a través de la opción PermitUserEnvironment
  • ~/.ssh/rc - Contiene las rutinas de inicialización que se ejecutarán antes de que se pueda acceder al directorio de inicio del usuario.
  • /etc/ssh/sshd_config - el archivo de configuración de todo el sistema
    • AllowAgentForwarding - Especifica si se permite el reenvío de ssh-agent (1).
    • AllowTcpForwarding
    • ForceCommand - "Fuerza la ejecución del comando especificado por ForceCommand, ignorando cualquier comando proporcionado por el cliente y ~ / .ssh / rc si está presente. El comando se invoca usando el shell de inicio de sesión del usuario con la opción -c."
    • GatewayPorts - "Especifica si los hosts remotos pueden conectarse a los puertos reenviados para el cliente. De forma predeterminada, sshd (8) vincula los enrutamientos de puertos remotos a la dirección de bucle invertido. Esto evita que otros hosts remotos se conecten a los puertos reenviados. utilizado para especificar que sshd debería permitir que los enrutamientos de puertos remotos se vinculen a direcciones que no sean de bucle invertido, lo que permite que otros hosts se conecten. "
    • %código%:
        

      Especifica los destinos a los que se reenvía el puerto TCP   permitido. La especificación de reenvío debe ser una de las   siguientes formas:

      PermitOpen host:port
      PermitOpen IPv4_addr:port
      PermitOpen [IPv6_addr]:port
      
           

      Se pueden especificar múltiples forwards separándolos con   espacio en blanco. Se puede usar un argumento de 'cualquiera' para eliminar todo   restricciones y permitir cualquier solicitud de reenvío. Por defecto todos   las solicitudes de reenvío de puertos están permitidas.

    •   
    • PermitOpen - Especifica si se permite el reenvío del dispositivo tun (4). El valor predeterminado es 'no'
    •   
    • PermitTunnel - Especifica si se permite el reenvío X11.El valor predeterminado es 'no'
    •   
  •   

Aplicando las restricciones

La modificación del archivo de configuración de todo el sistema X11Forwarding permite aplicar la configuración incluso si se aplica la autenticación basada en contraseña o si las restricciones en /etc/ssh/sshd_config se eliminan accidentalmente. Si ha modificado los valores predeterminados globales, debe descomentar las opciones en consecuencia.

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

Ahora agrega un usuario:

sudo useradd -m limited-user

La opción ~/.ssh/authorized_keys se puede omitir si el shell se establece en un no shell como ForceCommand (o /bin/false ) ya que /bin/true no hará nada.

Ahora el cliente solo puede conectarse al puerto 62222 en la dirección de bucle invertido del servidor a través de SSH (no escuchará en la dirección IP pública)

Al deshabilitar /bin/false -c [command] , también se rechazaría el uso de AllowTcpForwarding , lo que anularía el uso de una cuenta restringida para reenviar un solo puerto. -R asume que el puerto 62222 en el servidor nunca está en uso porque el cliente puede conectarse con él y escucharlo también.

Si se permite el reenvío de TCP en la configuración de todo el sistema y se deshabilita la autenticación basada en contraseña, también puede usar la configuración por clave. Edite PermitOpen localhost:62222 y agregue las siguientes opciones antes del ~/.ssh/authorized_keys (con un espacio entre las opciones y ssh- ):

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

Verificar

Para asegurarse de que funciona como se espera, se deben ejecutar algunos casos de prueba. En los comandos siguientes, ssh- debe reemplazarse por el inicio de sesión real si no está configurado en host . Detrás del comando, se muestra un comando que debe ejecutarse en el cliente o servidor (como se especifica).

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

Conclusión

Lista de verificación: el usuario de SSH no debería poder:

  • ejecuta comandos de shell - hecho
  • accede a archivos o sube archivos al servidor - hecho
  • usa el servidor como proxy (por ejemplo, webproxy) - hecho
  • accede a los servicios locales que de otro modo no eran públicamente accesibles debido a un firewall - parcialmente , el cliente no puede acceder a otros puertos además del 62222, pero puede escuchar y conectarse al puerto 62222 en el servidor
  • matar el servidor - hecho (tenga en cuenta que estas comprobaciones están limitadas al servidor SSH. Si tiene otro servicio vulnerable en la máquina, podría permitir que un posible atacante ejecute comandos, mate el servidor, etc.)
respondido por el Lekensteyn 22.06.2011 - 09:11
2

Estoy seguro de que hay muchas soluciones para esto, y muchas más sólidas que la que estoy proponiendo. Sin embargo, esto puede ser suficiente para sus necesidades. Para hacerlo, supongo que el usuario puede realizar la autenticación basada en la clave ssh (la masilla o cualquier ssh de Unix debería ser compatible).

  • Agregue un usuario como lo haría normalmente ('adduser' o cualquier otra herramienta)

  • Crea los usuarios .ssh dir y .ssh / authorized_keys

your_user $ sudo -Hu ssh_forwarder /bin/bash

ssh_forwarder $ cd ~
ssh_forwarder $ mkdir .ssh
ssh_forwarder $ ( umask 066 && cat > .ssh/authorized_keys ) <<EOF
no-agent-forwarding,no-X11-forwarding,command="read a; exit" ssh-rsa AAAB3NzaC1y....2cD/VN3NtHw== smoser@brickies
EOF
  • Desactiva el acceso de contraseña a esta cuenta.
your_user $ sudo usermod --lock ssh_forwarder

Ahora, la única forma en que el usuario puede ingresar a su sistema es a través del acceso a la clave ssh apropiada, y ssh ejecutará "/ bin / bash -c 'leer a'" para ellos, sin importar lo que intenten ejecutar . 'leer a' simplemente leerá hasta una nueva línea, y luego el shell se cerrará, por lo que el usuario solo tiene que presionar 'enter' para cancelar la conexión.

Hay muchas otras cosas que podrías hacer en 'command ='. Ver man authorized_keys y buscar 'comando' para más información.

Si no le gusta el hecho de que presionar enter mata la conexión, podría usar algo como lo siguiente para la entrada 'command =':

command="f=./.fifo.$$ && mkfifo $f && trap \"rm -f $f\" EXIT && read a <$f && echo $a; exit;"

Esto solo crea un fifo temporal en el directorio de inicio de los usuarios, y luego intenta leer de él. No se escribirá nada en ese archivo, por lo que se bloqueará indefinidamente. Además, si quiere terminar con fuerza esa conexión, podría hacer algo como:

 your_user$ echo GOODBYE | sudo tee ~ssh_forwarder/.fifo.*

Esto debería usar muy pocos recursos, y nada debería ir mal en ese script que no terminaría en la terminación del shell.

sleep 1h; echo You have been here too long. Good bye.

No vi de entrada cómo podría permitir al usuario avanzar remotamente ( ssh -R ) pero limitar ( ssh -L ). Tal vez 'permitopen' podría ser utilizado. Google = no fue muy útil. Parece que algo como 'no-port-forwarding, permitremoteopen = 10001' sería útil para permitir ssh -R 6901:localhost:6901 .

Esta es una solución. Definitivamente se puede mejorar, y cualquier apertura de puertos remotos debe ser examinada. Si mi objetivo era permitir que mi abuela se conectara a mi LAN para poder usar vnc para ver su pantalla, y el acceso a esas teclas se limitaba a ella, personalmente me sentiría razonablemente seguro. Si esto fuera para una empresa, sería necesaria una investigación más exhaustiva. Una cosa a tener en cuenta es que ssh -N no solicita ningún shell, por lo que el código 'command =' no se ejecuta.

Otros mecanismos, posiblemente más seguros, pueden incluir crear un shell personalizado para el usuario e incluso bloquearlo con un apparmour.

    
respondido por el smoser 21.06.2011 - 13:09

Lea otras preguntas en las etiquetas