Servicio SFTP

En este artículo vamos a aprender como configurar y conectarnos a un VPS por SFTP tanto por la terminal como por un cliente gráfico.

SFTP (Secure Shell File Transfer Protocol) es un protocolo de red seguro que se utiliza para transferir archivos de un lugar a otro a través de una red. A diferencia de FTP (File Transfer Protocol), que es un protocolo no seguro, SFTP utiliza cifrado para proteger la información durante la transferencia. Esto hace que SFTP sea una opción más segura para transferir archivos sensibles a través de Internet. SFTP y FTP se llaman muy parecido y comparten la misma función pero no son lo mismo ya que usan protocolos diferentes. Por seguridad es recomendable usar siempre que se pueda SFTP en lugar FTP.

SFTP se utiliza comúnmente para transferir archivos de un ordenador local a un servidor. Para acceder a un servidor SFTP se utiliza un cliente SFTP. El cliente se ejecuta en un ordenador local y se valida al servidor. Los clientes SFTP suelen incluir opciones para subir y descargar archivos, así como para ver y gestionar los archivos en el servidor. Existen clientes de terminal y para entorno gráfico. Veremos el comando sftp para conexiones por consola y también le echaremos un vistazo a Filezilla, seguramente el más famoso de los clientes SFTP/FTP para entorno gráfico.

Instalar SFTP

SFTP viene ya instalado por defecto en la mayoría de linux pero si no estuviera (algo muy raro) se instala con el paquete ssh o con openssh-server.

sudo apt-get update
sudo apt-get install openssh-server
                        

Por defecto, SFTP usa el puerto 22 al igual que SSH por lo que necesitamos tener el abierto en el firewall el puerto correspondiente. Si tienes dudas de como hacerlo tienes varios temas en esta web para varios firewall y como abrir el firewall de infraestructura de Oracle.

Caso 1. Configurar VPS de Oracle Cloud para SFTP para grupos de usuarios

A la hora de configurar que usuarios tienen acceso se puede hacer de manera colectiva por medio de grupos de usuarios o de manera individual para cada usuario. Cual usar dependerá de nuestro criterio o de las necesidades de uso. Como primer ejemplo lo haremos por medio de grupos y a continuación por medio de usuarios. Comencemos:

La idea es utilizar un grupo de usuarios que tengan acceso a carpetas propias en el servidor. Cada usuario perteneciente a este grupo solo tendrá permiso de lectura/escritura en la carpeta de su propiedad, es decir, no podrán acceso a ningún directorio del que no sean propietarios. A esta característica se le llama usuarios enjaulados. Además, el usuario de SFTP no tendrá shell, es decir no podrá ejecutar comandos desde terminal. La ausencia de shell no es obligatoria pero sí muy recomendable por seguridad.

El grupo de usuarios para SFTP lo creamos con el comando:

sudo groupadd usuariossftp
                        

La lista de grupos existentes se puede consultar con cat /etc/group. Al final de la lista aparece el nuevo grupo usuariosftp.

En este ejemplo he creado expresamente un grupo de usuarios para SFTP pero según las necesidades es posible utilizar uno ya existente. Si queremos crear usuarios de SFTP para cargar archivos de desarrollo de una web podemos aprevecharnos del grupo www-data que ya existe en Ubuntu y otras distros Debian si tienen Apache o Ngix instalado.

Sea cual sea el grupo elegido o por el método de usuarios individuales debemos editar el archivo /etc/ssh/sshd_config.

Preparando archivo /etc/ssh/sshd_config

Con el editor que más nos guste y con un usuario con permisos root vamos a editar el archivo de configuración sshd_config.

sudo nano /etc/ssh/sshd_config 
                        

Hacia el final del documento buscamos Subsystem sftp /usr/lib/openssh/sftp-server . Debemos de comentar con # y añadir debajo Subsystem sftp internal-sftp. Debe quedar así:

# override default of no subsystems
# Subsystem      sftp    /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp
                        

Este cambio debe hacerse para la gran mayoría de Linux actuales. No hay razón alguna para usar la otra salvo que se trate de un equipo muy antiguo. La directica internal-sftp especifica que se debe usar el servidor SFTP integrado proporcionado por el servidor OpenSSH. Esto es así desde el año 2008. El otro método no tiene razón de uso salvo algún caso muy peculiar para seguir teniendo compatibilidad.

Al final del archivo creamos las directivas para el grupo de SFTP. Se inicia con Match Group nombredeGrupo.

Match Group usuariossftp
        ChrootDirectory %h
        ForceCommand internal-sftp
        X11Forwarding no
        AllowTcpForwarding no
        PasswordAuthentication yes
                        
  • Match Group usuariossftp La directiva Match se utiliza para aplicar un conjunto de opciones de configuración a un grupo específico de usuarios o hosts. En este caso, la directiva Match Group usuariossftp especifica que las siguientes opciones de configuración deben aplicarse a los usuarios que son miembros del grupo usuariosftp.
  • ChrootDirectory %h especifica que se debe usar el directorio home del usuario como el directorio raíz para la sesión SFTP. Esto significa que el usuario no podrá navegar fuera de su directorio home durante la sesión SFTP.
    %h equivale a /home/nombre_del_usuario_que_sea
  • ForceCommand internal-sftp especifica que se debe usar el servidor SFTP integrado proporcionado por el servidor OpenSSH para todas las conexiones SFTP de los usuarios en el grupo usuariossftp.
  • X11Forwarding no deshabilita el reenvío de X11 para los usuarios en el grupo usuariossftp. El reenvío de X11 permite que un cliente ejecute aplicaciones X11 en un servidor remoto y muestre la salida en la máquina local del cliente en un entorno gráfico.
  • AllowTcpForwarding no deshabilita el reenvío de TCP para los usuarios en el grupo usuariossftp. El reenvío de TCP permite que un cliente reenvíe las conexiones TCP a través de la conexión SSH a un servidor remoto.
  • PasswordAuthentication yes habilita la autenticación con contraseña para los usuarios en el grupo usuariossftp. Esto significa que los usuarios de este grupo podrán autenticarse con una contraseña al conectarse al servidor. Si ponemos no será necesario registrarse por medio de archivos de clave público/privada.

Una vez grabados los cambios de configuración debemos reiniciar el servicio pero antes es recomendable comprobar que el archivo no tiene errores con sudo sshd -t. Si no responde nada ejecutamos:

sudo service ssh restart
                        

Creando usuarios

Para crear usuarios se usa useradd

sudo useradd -m -s /sbin/nologin -g usuariossftp usuariosftp1
                        

Los parámetros utilizados son:

  • -m indica que el usuario tendrá un directorio inicial en home/usuariossftp1
  • -s /sbin/nologin
  • impide que el usuario pueda iniciar sesión en el sistema y ejecutar comandos en la terminal. Este tipo de usuarios solo pueden ejecutar servicios determinados como el SFTP y otros.
  • -g usuariossftp
  • añade al grupo usuariossftp el usuario creado.
  • usuariosftp1
  • es el nombre del usuario

Tenemos usuario pero le falta la contraseña. Le pondremos una segura evitando caer en las palabras fáciles o cortas.

sudo passwd usuariosftp1
                        

Permisos de los directorios

El directorio del usuario debe ser propiedad de root y pertenecer al grupo usuariosftp o de lo contrario no podremos entrar y además los permisos de escritura de grupos deben estar restringidos. Estas condiciones pueden parecer confusas y hasta contradictorias. Si la carpeta home pertenece a root y el grupo no tiene permisos de escritura, ¿dónde podemos subir los archivos?

Se pueden subir a un nuevo directorio dentro del /home/usuariosftp1 que crearemos más adelante. Ahora cambiamos los propietarios con chown. Un solo parámetro cambia el propietario de usuario. Para cambiar usuario y grupo se separan entre :

# propietario root, grupo el que tenía "usuariossftp"
sudo chown root /home/usuariosftp1/
# en este ejemplo es equivalente a sudo chown root:usuariossftp /home/usuariosftp1/
                        

Listaremos en modo 'largo' el directorio /home/ fijándonos en los permisos y propietarios de usuariosftp1. Usaremos ls -l /home.

ls -l /home

drwxr-xr-x 3 root   usuariossftp 4096 Dec 17 13:26 usuariosftp1
                        

Los permisos aparecen codificados en drwxr-xr-x. La d indica que se trata de un directorio. Cualquier archivo, un directorio también lo es, tiene permisos para propietarios, grupos y los otros que no son ni propietarios ni grupos. Los permisos asignables son la lectura r, la escritura w y la ejecución x. Un permiso no asignado se simboliza con el -. Como SFTP nos pone como condición que el grupo no tenga permisos de escritura debe aparecer un - en la posición correspondiente.

Para cambiar los permisos se utiliza el comando chmod. Consulta en esta web "Comandos básicos Linux" donde se explica con más detalle como cambiar las propiedades de un archivo. Aquí solo te voy a recordar que existe el método numérico, mi preferido, y el método simbólico.

Con cualquiera de las siguientes comandos conseguiremos dar permisos rwxr-xr-x al directorio usuariosftp1

# cambio de permisos por método numérico o octal
sudo chmod go-w /home/usuariosftp1/
# cambio de permisos por método simbólico
sudo chmod 755 /home/usuariosftp1/
                        

En el directorio Home de cada usuario creamos un nuevo directorio llamado subidosftp que tendrá está ruta /home/nombredelusuario/subidosftp. La creación de directorios es con el comando mkdir:

sudo mkdir /home/usuariosftp1/subidosftp/
                        

Inicialmente, al crearlo pertenece a root como propietario y grupo. Necesitamos que el propietario sea usuariosftp1 y el grupo usuariossftp. Nuevamente usamos chown como ya sabemos:

sudo chown usuariosftp1:usuariossftp /home/usuariosftp1/subidosftp
                        

El directorio de SFTP debe de tener los permisos para el propietario, en este caso usuariosftp1. De nuevo recurrimos a chmod y con 775 asignamos todos los permisos para usuarios y grupos mientras que para el resto con el 5 indicamos lectura y ejecución. Funciona también si ponemos 700 pero en este caso el archivo sería imposible de ver para el resto de usuarios. El directorio donde se encuentra es inaccesible para otros usuarios SFTP pero es que además si ponemos 700 lo dejamos como un archivo totalmente privado aunque lo saquemos de la "jaula":

# todos los permisos a usuarios y grupos. Usaremos el método que más nos guste, simbólico o numérico.
sudo chmod ug+rwX /home/usuariosftp1/subidosftp/
sudo chmod 775 /home/usuariosftp1/subidosftp/
                        

Y con esto ya tenemos un directorio dentro de la home del usuario donde conectarnos por un cliente SFTP. Si queremos crear más debemos repetir los pasos de crear usuario, directorios y permisos. No es necesario modificar nuevamente el archivo /etc/ssh/sshd_config ni tampoco reiniciar el servicio ssh porque usamos el método de grupos.

Creación de un segundo usuario

# ejemplo de creación de segundo usuario y carpeta compartida para SFTP
sudo useradd -m -s /sbin/nologin -g usuariossftp usuariosftp2
sudo passwd usuariosftp2

sudo mkdir /home/usuariosftp2/subidosftp/

sudo chown root /home/usuariosftp2/ ( propietario root, grupo el que tenía)

# verificar que no tenga permisos de escritura para grupos y otros. Por defecto sale bien para cambiarlo se puede hacer:

sudo chmod 755 /home/usuariosftp2/

sudo chown usuariosftp2:usuariossftp /home/usuariosftp2/subidosftp/

# todos los permisos a usuarios y grupos

sudo chmod 775 /home/usuariosftp2/subidosftp/

                        

Más abajo tienes como conectar al servidor SFTP por terminal y por Filezilla. Antes vamos a ver como configurar usuarios usando por directiva de usuarios.

Caso 2. Configurar VPS de Oracle Cloud para SFTP por directiva de usuarios

Aunque algunos pasos ya están vistos y hechos anteriormente los enumero todos. Con nano o otro editor modificamos el archivo de configuración sshd_config.

sudo nano /etc/ssh/sshd_config 
                        

Aquí al final si no lo hemos hecho ya hacemos el cambio de Subsystem sftp internal-sftp. Debe quedar así:

# override default of no subsystems
# Subsystem      sftp    /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp
                        

Al final del archivo van las directivas de los usuarios. Podemos poner varios usuarios separados por , con las mismas directivas o crearlas de manera individual.


Match User usuario1, usuario2
        ChrootDirectory %h
        ForceCommand internal-sftp
        X11Forwarding no
        AllowTcpForwarding no
        PasswordAuthentication yes

                        

Prácticamente todo igual a como lo hicimos para grupos salvo que ahora usamos Match User. Reiniciamos el servicio para que apliquen los cambios.

sudo service ssh restart
                        

Creamos los usuarios. De momento, no nos vamos a preocupar a que grupo pertenecen ya que inicialmente queremos que cada usuario tenga su directorio privado. En otros casos nos puede interesar que los usuarios puedan verse los directorios. Se ha de tener en cuenta que cada usuario entra a su "jaula" y no puede entrar con esta configuración a la carpeta home de otro.

sudo adduser usuario1
sudo adduser usuario2
                        

Para cada usuario creado nos pide una contraseña, pondremos una segura. Los valores de valores de nombre, teléfono, etc los omitimos dejándolos en blanco.

Adding user `usuario1' ...
Adding new group `usuario1' (1003) ...
Adding new user `usuario1' (1004) with group `usuario1' ...
Creating home directory `/home/usuario1' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for usuario1
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] Y
                        

En este punto de la configuración si intentamos conectarnos por SFTP no funcionará porque por seguridad la ruta raiz de entrada debe ser siempre a un directorio propietario de root. Desde nuestro cliente SFTP el error devuelto podría ser como este:

sftp usuario1@129.151.228.46
usuario1@129.151.228.46's password:
client_loop: send disconnect: Broken pipe
Connection closed
                        

El mensaje es un poco abstracto. Literalmente quiere decir que la tubería de comunicación entre el cliente y el servidor se ha roto. En este La sesión se corta abruptamente por los permisos del directorio raiz.

Para solucionarlo cambiamos la propiedad a root de /home/usuario1 y /home/usuario2. El grupo podemos dejar el que tenga pero siempre que no tenga permisos de escritura o tampoco podremos entrar.

Para cambiar al propietario:

sudo chown root /home/usuario1
sudo chown root /home/usuario2
                        

Para cambiar los permisos para grupo y desactivar la escritura. (este paso quizás no tengas que hacerlo porque al menos a mi cuando desarrollaba este ejemplo ya me aparecen deshabilitados los permisos de escritura para grupos):

sudo chmod 755 /home/usuario1
sudo chmod 755 /home/usuario2
                        

Ahora aunque ya podemos entrar por SFTP tenemos otro obstáculo. Podemos ver y descargar el contenido del directorio pero no tenemos permisos de escritura y por tanto no podemos archivos. Por SFTP por nunca podemos tener permisos totales a la raiz de la jaula. Los archivos solo se pueden subir a directorios por debajo de este cuyo propietario sea el usuario con el que conectamos. Lo que haremos es crear uno o más directorios y le daremos permisos totales para En el siguiente nivel si los directorios son propiedad del usuario ya podremos subir/bajar y hasta crear nuevos directorios.

Crearemos nuevos directorios con permisos totales para los usuarios. Como estoy con usuario con permisos de root será este el propietario.

sudo mkdir /home/usuario1/subidos/
sudo mkdir /home/usuario2/subidos/
                        

Comprobamos los directorios y vemos que efectivamente pertenecen a root. Necesitamos cambiar los propietarios. En este momento como se entra al servidor con "usuario1 o 2" se disponen de permisos de lectura porque la sección de Otros, los que no son propietarios ni grupos, tienen permisos de lectura. Esto aparece codificado como "drwxr-xr-x":

ls -l /home/usuario1/
total 4
drwxr-xr-x 2 root root 4096 Jan  4 18:21 subidos
                        

Ahora, si subimos un archivo dará un error de "Acceso Denegado". Una vez asignados propietarios a los usuarios ya dispondrán de los permisos totales al establecer la conexión.

sudo chown usuario1 /home/usuario1/subidos
sudo chown usuario2 /home/usuario2/subidos
                        

Con esto ya funcionaría perfectamente la conexión al servidor. Nos falta por explicar como conectarnos desde algunos clientes SFTP.

Conectar con Filezilla

Filezilla es un cliente SFTP y FTP por GUI muy utilizado. Para conectarnos al servidor rellenamos los campos de servidor, usario, contraseña y puerto. Fíjate en el detalle de que es necesario especificar el protócolo en la dirección. Si no añadimos sftp:// no funciona. El número de puerto solo es necesario si no es el 22.

Una vez conectados es muy intuitivo subir, bajar, editar o renombrar archivos. También podemos crear nuevas carpetas y movernos por ellas pero nunca podremos salir de la jaula del usuario.

Es posible establecer la conexión a un directorio concreto si se lo indicamos en la dirección de servidor. Por ejemplo con sftp://x.x.x.x/subidosftp ya entramos directamente en ese directorio.

Conectar desde terminal

Para conectarte a un servidor SFTP desde el terminal se utiliza el formato sftp usuario@servidor. La primera vez que conectamos nos pedirá que confiemos en la huella digital. Es una medida de seguridad debido a que nuestro sistema no conoce el servidor al que se conecta y quiere verificar la identidad. Tras aceptar con yes y poner el password nos sale un prompt donde entrar comandos.

sftp usuariosftp1@129.151.228.46
The authenticity of host '129.151.228.46 (129.151.228.46)' can't be established.
ECDSA key fingerprint is SHA256:rkszzd8oIFMnKCfUD57KS/Uc4J0yQj4jwKI5HSm9uIg.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

Warning: Permanently added '129.151.228.46' (ECDSA) to the list of known hosts.
usuariosftp1@129.151.228.46's password:
Connected to 129.151.228.46.

sftp> 

                        

Es posible especificar dentro de que directorio empiece la sesión. Por defecto será la raiz pero si tras la IP o dominio del servidor añadimos el nombre del directorio/subdirectorio se establecerá conexión donde le indiquemos. Por supuesto, siempre dentro de la jaula.

sftp usuariosftp1@129.151.228.46:/subidosftp
usuariosftp1@129.151.228.46's password:
Connected to 129.151.228.46.
Changing to: /subidosftp

sftp> 

                        

Una vez que estés conectado al servidor SFTP, puedes utilizar los siguientes comandos para transferir archivos:

  • get nombre_archivo: para descargar un archivo del servidor SFTP al directorio local en el que te encuentras.
  • put nombre_archivo: para subir un archivo desde tu directorio local al servidor SFTP.
  • mget: para descargar varios archivos a la vez.
  • mput: para subir varios archivos a la vez.

Por ejemplo, para descargar el archivo "archivo.txt" del servidor SFTP y guardarlo en el directorio local, puedes utilizar el siguiente comando:

get archivo.txt
                        

Para subir un archivo local al servidor:

put archivo.txt
                        
Para subir o bajar varios archivos a la vez, se usa mput y mgetseguido del nombre de los archivos, separados por espacio. Por ejemplo:
# subir varios archivos
mput archivo1.txt archivo2.pdf archivo3.jpg
# subir todos los archivos del directorio actual
mput *
                        

Para movernos entre directorios tenemos los mismos comandos de la terminal que ya debemos conocer:

  • cd: cambia al directorio que se indique como parámetro. Para volver al directorio anterior se usa cd .. pero nunca saldremos de la jaula.
  • ls: para listar archivos y directorios
  • pwd: indica el directorio actual

Con estos conocimientos ya somos capaces de subir y bajar archivos. Vamos a verlo con unos ejemplos hechos entre una máquina local y el servidor. Tengo en local un archivo llamado texto.txt que quiero subir. Primero voy a verificar en que directorio del servidor me encuentro porque en la raiz no puedo escribir. Debo cambiarme a la carpeta subidosftp donde tengo permisos de escritura.

sftp> pwd
Remote working directory: /
sftp> ls
subidosftp
sftp> cd subidosftp
sftp> pwd
Remote working directory: /subidosftp
sftp> 
                        

Ahora que me encuentro dentro del directorio /subidosftp usaré el comamndo para subir archivos put

sftp> put texto.txt
put texto.txt
Uploading texto.txt to /subidosftp/texto.txt
texto.txt                                     100%    5     7.7KB/s   00:00
sftp> ls
texto.txt
sftp> 
                        

Todo tal cual se esperaba, archivo subido con respuesta de confirmación y además listamos para verlo en su nueva ubicación. Más operaciones que podemos hacer crear directorios y renombrar archivos

sftp> mkdir otrodirectorio
sftp> rename texto.txt texto2.txt
sftp> ls
otrodirectorio   texto2.txt
sftp> 
                        

Mientras estás dentro de la sesión de SFTP se pueden ejecutar comandos en local poniendo el código de escape !. De esta manera si queremos ver los archivos del directorio local donde nos encotramos o comprobar el directorio actual pondríamos !ls y !pwd. Muy práctico para no tener que cerrar sesión y consultar alguna cosa o movernos entre directorios locales.

Como ves, todo muy sencillo y con comandos que ya conocemos. La lista completa la puedes obtener entrando help

sftp> help
Available commands:
bye                                Quit sftp
cd path                            Change remote directory to 'path'
chgrp [-h] grp path                Change group of file 'path' to 'grp'
chmod [-h] mode path               Change permissions of file 'path' to 'mode'
chown [-h] own path                Change owner of file 'path' to 'own'
df [-hi] [path]                    Display statistics for current directory or
                                   filesystem containing 'path'
exit                               Quit sftp
get [-afpR] remote [local]         Download file
help                               Display this help text
lcd path                           Change local directory to 'path'
lls [ls-options [path]]            Display local directory listing
lmkdir path                        Create local directory
ln [-s] oldpath newpath            Link remote file (-s for symlink)
lpwd                               Print local working directory
ls [-1afhlnrSt] [path]             Display remote directory listing
lumask umask                       Set local umask to 'umask'
mkdir path                         Create remote directory
progress                           Toggle display of progress meter
put [-afpR] local [remote]         Upload file
pwd                                Display remote working directory
quit                               Quit sftp
reget [-fpR] remote [local]        Resume download file
rename oldpath newpath             Rename remote file
reput [-fpR] local [remote]        Resume upload file
rm path                            Delete remote file
rmdir path                         Remove remote directory
symlink oldpath newpath            Symlink remote file
version                            Show SFTP version
!command                           Execute 'command' in local shell
!                                  Escape to local shell
?                                  Synonym for help
                        
Detener servicio SFTP

Para detener el servicio SFTP podríamos pensar en detener el servicio SSH pero eso también deshabilita las conexiones remotas por SSH. La manera correcta es editar el archivo de configuración nano /etc/ssh/sshd_config y comentar la línea que añadimos en su momento: Subsystem sftp internal-sftp

# override default of no subsystems
# Subsystem      sftp    /usr/lib/openssh/sftp-server
# Subsystem sftp internal-sftp
                        

Para que los cambios surtan efecto, reiniciamos el servicio SSH. Tras esto se detendrá SFTP sin afectar a SSH:

sudo systemctl restart ssh