SFTP con chroot dependiendo de la clave pública del usuario que se conecta

9

Quiero construir un servidor (ejecutando Debian o FreeBSD) que reciba copias de seguridad de diferentes clientes a través de sshfs. Cada cliente debe poder leer y escribir sus propios datos de respaldo, pero no los datos de ninguno de los otros clientes.

Tuve la siguiente idea: cada cliente se conecta a través de autenticación de clave pública a [email protected]. La copia de seguridad del usuario tiene un archivo especial de claves autorizadas, como este:

command="internal-sftp" chroot="/backup/client-1/data" ssh-rsa (key1)
command="internal-sftp" chroot="/backup/client-2/data" ssh-rsa (key2)
command="internal-sftp" chroot="/backup/client-3/data" ssh-rsa (key3)
etc...

La ventaja de esto sería que no necesitaría usar un usuario separado para cada cliente, y podría autogenerar fácilmente el archivo Authorized Keys con un script.

Solo hay un problema: el chroot=...no funciona. El archivo autorizado de claves de OpenSSH no parece tener un equivalente para ChrootDirectory (que funciona en / etc / ssh / sshd_config, ya sea globalmente o en un bloque Match User).

¿Hay una manera razonablemente simple de lograr lo que quiero usando OpenSSH? ¿Tal vez usando la command=...directiva de una manera inteligente? Alternativamente, ¿hay otros servidores SFTP que puedan hacer lo que quiero?

EDITAR : para que quede más claro lo que quiero lograr: quiero que varios clientes puedan almacenar archivos en mi servidor. Cada cliente no debería poder ver los archivos de ningún otro cliente. Y no quiero llenar mi servidor con docenas de cuentas de usuario, por lo que me gustaría una solución fácilmente manejable para que los clientes compartan una cuenta de usuario y aún no tengan acceso a los archivos de los demás.

Xykon42
fuente

Respuestas:

5

Alternativamente, ¿hay otros servidores SFTP que puedan hacer lo que quiero?

sí, puedes usar proftpd

Preparar el entorno del usuario. Con ProFTPD no hay necesidad de darle al usuario un shell válido.

# useradd -m -d /vhosts/backup/user1/ -s /sbin/nologin user1
# passwd --lock user1
Locking password for user user1.
passwd: Success

# mkdir /vhosts/backup/user1/.sftp/
# touch /vhosts/backup/user1/.sftp/authorized_keys

# chown -R user1:user1 /vhosts/backup/user1/
# chmod -R 700 /vhosts/backup/user1/

Para utilizar claves públicas OpenSSH en SFTPAuthorizedUserKeys, debe convertirlas al formato RFC4716. Puede hacer esto con la herramienta ssh-keygen:

# ssh-keygen -e -f user1.public.key > /vhosts/backup/user1/.sftp/authorized_keys

Configurar ProFTPD

ServerName "ProFTPD Default Installation"
ServerType standalone
DefaultServer off

LoadModule mod_tls.c
LoadModule mod_sftp.c
LoadModule mod_rewrite.c

TLSProtocol TLSv1 TLSv1.1 TLSv1.2

# Disable default ftp server
Port 0

UseReverseDNS off
IdentLookups off

# Umask 022 is a good standard umask to prevent new dirs and files
# from being group and world writable.
Umask 022

# PersistentPasswd causes problems with NIS/LDAP.
PersistentPasswd off

MaxInstances 30

# Set the user and group under which the server will run.
User nobody
Group nobody

# Normally, we want files to be overwriteable.
AllowOverwrite                  on

TimesGMT off
SetEnv TZ :/etc/localtime

<VirtualHost sftp.example.net>
    ServerName "SFTP: Backup server."
    DefaultRoot ~
    Umask 002
    Port 2121

    RootRevoke on

    SFTPEngine on
    SFTPLog /var/log/proftpd/sftp.log

    SFTPHostKey /etc/ssh/ssh_host_rsa_key
    SFTPHostKey /etc/ssh/ssh_host_dsa_key
    SFTPDHParamFile /etc/pki/proftpd/dhparam_2048.pem
    SFTPAuthorizedUserKeys file:~/.sftp/authorized_keys

    SFTPCompression delayed
    SFTPAuthMethods publickey
</VirtualHost>

<Global>
    RequireValidShell off
    AllowOverwrite yes

    DenyFilter \*.*/

    <Limit SITE_CHMOD>
        DenyAll
    </Limit>
</Global>

LogFormat default "%h %l %u %t \"%r\" %s %b"
LogFormat auth    "%v [%P] %h %t \"%r\" %s"
ExtendedLog /var/log/proftpd/access.log read,write

Crear parámetros de grupo DH (Diffie-Hellman).

# openssl dhparam -out /etc/pki/proftpd/dhparam_2048.pem 2048

Configure cualquier cliente SFTP. He usado FileZilla

Configuración del servidor FileZilla SFTP

Si ejecuta ProFPTD en modo de depuración

# proftpd -n -d 3 

En la consola verás algo como lo siguiente

2016-02-21 22:12:48,275 sftp.example.net proftpd[50511]: using PCRE 7.8 2008-09-05
2016-02-21 22:12:48,279 sftp.example.net proftpd[50511]: mod_sftp/0.9.9: using OpenSSL 1.0.1e-fips 11 Feb 2013
2016-02-21 22:12:48,462 sftp.example.net proftpd[50511] sftp.example.net: set core resource limits for daemon
2016-02-21 22:12:48,462 sftp.example.net proftpd[50511] sftp.example.net: ProFTPD 1.3.5a (maint) (built Sun Feb 21 2016 21:22:00 UTC) standalone mode STARTUP
2016-02-21 22:12:59,780 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): mod_cap/1.1: adding CAP_SETUID and CAP_SETGID capabilities
2016-02-21 22:12:59,780 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): SSH2 session opened.
2016-02-21 22:12:59,863 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): Preparing to chroot to directory '/vhosts/backup/user1'
2016-02-21 22:12:59,863 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): Environment successfully chroot()ed
2016-02-21 22:12:59,863 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): USER user1: Login successful

Y las siguientes líneas en un /var/log/sftp.log

2016-02-21 22:12:48,735 mod_sftp/0.9.9[50309]: sending acceptable userauth methods: publickey
2016-02-21 22:12:48,735 mod_sftp/0.9.9[50309]: public key MD5 fingerprint: c2:2f:a3:93:59:5d:e4:38:99:4b:fd:b1:6e:fc:54:6c
2016-02-21 22:12:48,735 mod_sftp/0.9.9[50309]: sending publickey OK
2016-02-21 22:12:59,789 mod_sftp/0.9.9[50309]: public key MD5 fingerprint: c2:2f:a3:93:59:5d:e4:38:99:4b:fd:b1:6e:fc:54:6c
2016-02-21 22:12:59,790 mod_sftp/0.9.9[50309]: sending userauth success
2016-02-21 22:12:59,790 mod_sftp/0.9.9[50309]: user 'user1' authenticated via 'publickey' method

PD

La ruta configurada para un archivo que contiene claves autorizadas ( SFTPAuthorizedUserKeys ) puede usar la variable % u , que se interpolará con el nombre del usuario que se autentica. Esta característica admite tener archivos por usuario de claves autorizadas que residen en una ubicación central, en lugar de requerir (o permitir) que los usuarios administren sus propias claves autorizadas. Por ejemplo:

SFTPAuthorizedUserKeys file:/etc/sftp/authorized_keys/%u

Quiero que varios clientes puedan almacenar archivos en mi servidor. Cada cliente no debería poder ver los archivos de ningún otro cliente. Y no quiero llenar mi servidor con docenas de cuentas de usuario, por lo que me gustaría una solución fácilmente manejable para que los clientes compartan una cuenta de usuario y aún no tengan acceso a los archivos de los demás.

con ProFTPD también es posible. Solo necesitas modificar un poco mi configuración inicial

<VirtualHost sftp.example.net>
    ...   
    SFTPAuthorizedUserKeys file:/etc/proftpd/sftp_authorized_keys
    AuthUserFile /etc/proftpd/sftp_users.passwd

    CreateHome on 0700 dirmode 0700 uid 99 gid 99

    RewriteHome on
    RewriteEngine on
    RewriteLog /var/log/proftpd/rewrite.log
    RewriteCondition %m REWRITE_HOME
    RewriteRule (.*) /vhosts/backup/%u
</VirtualHost>

Y crea una cuenta virtual

# ftpasswd --passwd --file /etc/proftpd/sftp_users.passwd --sha512 --gid 99 --uid 99 --shell /sbin/nologin --name user1 --home /vhosts/backup

Eso es todo. Para cada cuenta adicional, todo lo que necesita es agregar su clave pública a / etc / proftpd / sftp_authorized_keys

Nota: ¡el archivo debe contener una nueva línea al final! Es importante.

ALex_hha
fuente
Gracias por tu respuesta detallada. Sin embargo, no veo cómo esto me ayudaría a lograr mi objetivo principal de usar solo una cuenta de usuario para muchos clientes que no deberían poder ver los archivos de los demás. (Y ser fácilmente manejable con un guión). Al leer mi pregunta original nuevamente, admito que podría no haber sido completamente obvio lo que quería lograr. Lo siento por eso.
Xykon42
He actualizado la respuesta
ALex_hha
1
De acuerdo, con un pequeño cambio, esto realmente funciona bien, ¡gracias! Para asegurarse de que los usuarios no puedan acceder a los archivos de otros usuarios adivinando su nombre de usuario (o para inundar mi servidor haciendo un mal uso de la función CreateHome), el archivo autorizado_keys debe ser específico del usuario, como /foo/authorized_keys.d/%u.
Xykon42
6

El chroot=...no funciona.

No, no hay nada de eso en la página del manual para sshddescribir el formato del authorized_keysarchivo.

Si pusieras chroot command=, no podrías usarlo internal-sftp, porque es una sustitución de la llamada interna a la función interna sshd.

La forma recomendada es configurar más usuarios, si necesita separación. También puede usar argumentos para internal-sftp, si no necesita una separación estricta (por ejemplo, solo directorios de trabajo diferentes), como

command="internal-sftp -d /backup/client-1/data" ssh-rsa (key1)

También es posible limitar la cantidad de solicitudes usando la -Popción como en la página del manual sftp-server.

Jakuje
fuente
0

Mientras tanto, se me ocurrió otra solución simple que también funciona bien, al menos en mi caso de uso:

Cada cliente se conecta al servidor con la misma cuenta de usuario y posiblemente incluso la misma clave (no importa). OpenSSH se convierte en un directorio que tiene la siguiente estructura:

d--x--x---   dark-folder
drwxr-x---   |- verylongrandomfoldername1
drwxr-x---   |- verylongrandomfoldername2
drwxr-x---   `- ...

Junto con el comando de copia de seguridad, el servidor le dice al cliente el nombre de la carpeta en la que debe colocar sus archivos. Los nombres de las carpetas son cadenas aleatorias de 64 bytes que son prácticamente indiscutibles, por lo que cada cliente solo puede acceder a su propia carpeta, aunque los otros estén "en algún lugar en la oscuridad".

El modo d - x - x-- en dark-folder asegura que cada cliente puede ingresar a la carpeta (y las carpetas a continuación), pero no puede enumerar su contenido o crear nuevas entradas.

El proceso del servidor de respaldo crea las subcarpetas y la conexión entre el cliente y la carpeta se almacena (entre otras cosas) en una base de datos sqlite.

Xykon42
fuente