vsftpd (Very Secure FTP Daemon) es el servidor FTP por defecto en Ubuntu y Debian. El FTP clásico envía contraseñas y archivos sin cifrar, así que en este tutorial configurarás vsftpd en Ubuntu 24.04 solo con FTPS (FTP sobre TLS), con usuarios enjaulados en su directorio y un rango de puertos pasivos compatible con el firewall. Al final configurarás también SFTP con OpenSSH, la alternativa recomendada cuando no necesitas compatibilidad con clientes FTP.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con IP pública (your_server_ip).
  • Un usuario no root con privilegios sudo y UFW activo con SSH permitido.
  • Un cliente FTP con soporte TLS, como FileZilla o lftp.
  • Opcional: un dominio (your_domain) apuntando al servidor, si quieres usar un certificado de Let's Encrypt en lugar de uno autofirmado.

FTPS o SFTP

FTPS (vsftpd)SFTP (OpenSSH)
ProtocoloFTP con TLSSubsistema de SSH
Puertos21 más un rango pasivo22
CertificadoNecesarioUsa las claves de SSH
ClientesClientes FTP, dispositivos antiguosCualquier cliente SFTP o SSH

Si puedes elegir, usa SFTP (paso 8): solo necesita el puerto 22 y no requiere software adicional. Usa FTPS cuando una aplicación, un escáner o un cliente heredado solo hable FTP.

Paso 1: Instalar vsftpd

sudo apt update
sudo apt install vsftpd

Comprueba que el servicio está activo:

systemctl status vsftpd --no-pager
● vsftpd.service - vsftpd FTP server
     Loaded: loaded (/usr/lib/systemd/system/vsftpd.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-09-25 12:01:15 UTC; 8s ago

Paso 2: Crear el usuario FTP y su directorio

Crea un usuario dedicado a FTP, sin acceso a una shell interactiva:

sudo adduser --shell /usr/sbin/nologin ftpuser

Introduce una contraseña robusta cuando te la pida. La configuración PAM de vsftpd (/etc/pam.d/vsftpd) incluye pam_shells, que rechaza a los usuarios cuya shell no aparece en /etc/shells. Añade nologin a esa lista para que el usuario pueda entrar por FTP pero no por SSH:

echo /usr/sbin/nologin | sudo tee -a /etc/shells

vsftpd enjaulará al usuario en su directorio personal (chroot) y, por seguridad, se niega a hacerlo si ese directorio es escribible por el usuario. La estructura correcta es una raíz propiedad de root y una subcarpeta donde el usuario sí puede escribir:

sudo chown root:root /home/ftpuser
sudo chmod 755 /home/ftpuser
sudo mkdir /home/ftpuser/archivos
sudo chown ftpuser:ftpuser /home/ftpuser/archivos

Comprueba los permisos:

ls -la /home/ftpuser
drwxr-xr-x 3 root    root    4096 Sep 25 12:04 .
drwxr-xr-x 4 root    root    4096 Sep 25 12:03 ..
drwxr-xr-x 2 ftpuser ftpuser 4096 Sep 25 12:04 archivos
...

Por último, crea la lista de usuarios autorizados. Con la configuración del paso 4, solo los usuarios de este archivo podrán iniciar sesión por FTP:

echo ftpuser | sudo tee /etc/vsftpd.userlist

Paso 3: Crear el certificado TLS

FTPS necesita un certificado. Para un uso interno basta con uno autofirmado; los clientes mostrarán un aviso la primera vez que conecten. Genera un certificado válido durante un año:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/vsftpd.key \
  -out /etc/ssl/certs/vsftpd.crt \
  -subj "/CN=your_server_ip"
sudo chmod 600 /etc/ssl/private/vsftpd.key

Paso 4: Configurar vsftpd

Guarda una copia del archivo original y ábrelo:

sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.orig
sudo nano /etc/vsftpd.conf

Sustituye todo el contenido por la siguiente configuración:

# Escucha en IPv4 e IPv6 como servicio independiente
listen=NO
listen_ipv6=YES

# Solo usuarios locales, sin acceso anónimo
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
pam_service_name=vsftpd

# Solo los usuarios de /etc/vsftpd.userlist pueden iniciar sesión
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO

# Enjaular a cada usuario en su directorio personal
chroot_local_user=YES
secure_chroot_dir=/var/run/vsftpd/empty

# Registro de transferencias en /var/log/vsftpd.log
xferlog_enable=YES
xferlog_std_format=NO
log_ftp_protocol=NO
use_localtime=YES

# Modo pasivo con un rango de puertos fijo
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100

# TLS obligatorio para el login y los datos
ssl_enable=YES
rsa_cert_file=/etc/ssl/certs/vsftpd.crt
rsa_private_key_file=/etc/ssl/private/vsftpd.key
allow_anon_ssl=NO
force_local_logins_ssl=YES
force_local_data_ssl=YES
require_ssl_reuse=NO
ssl_ciphers=HIGH

Las directivas clave son:

  • userlist_enable=YES con userlist_deny=NO convierte /etc/vsftpd.userlist en una lista de usuarios permitidos: el resto, incluido root, no puede entrar.
  • chroot_local_user=YES impide que el usuario salga de /home/ftpuser.
  • pasv_min_port y pasv_max_port limitan las conexiones de datos a 101 puertos, que abrirás en el firewall.
  • force_local_logins_ssl y force_local_data_ssl rechazan cualquier sesión que no use TLS, así las contraseñas nunca viajan en claro.
  • require_ssl_reuse=NO evita errores con clientes que no reutilizan la sesión TLS entre la conexión de control y la de datos.

Si el servidor está detrás de NAT y la IP pública no está configurada en su interfaz, añade también pasv_address=your_server_ip para que vsftpd anuncie la IP correcta en modo pasivo.

Reinicia el servicio para aplicar la configuración:

sudo systemctl restart vsftpd
systemctl is-active vsftpd
active

Si no aparece active, el motivo suele estar en sudo journalctl -u vsftpd -n 20.

Paso 5: Abrir los puertos en el firewall

Abre el puerto de control (21) y el rango pasivo:

sudo ufw allow 21/tcp
sudo ufw allow 40000:40100/tcp

Si solo unos pocos equipos van a usar el servidor, limita las reglas a sus IP con sudo ufw allow from your_client_ip to any port 21 proto tcp y lo mismo para el rango pasivo.

Paso 6: Probar la conexión FTPS

Desde tu equipo, instala lftp y conéctate forzando TLS. La opción ssl:verify-certificate no solo es necesaria con el certificado autofirmado:

sudo apt install lftp
lftp -u ftpuser -e "set ftp:ssl-force true; set ssl:verify-certificate no; ls; put -o archivos/prueba.txt /etc/hostname; ls archivos; bye" your_server_ip
Password:
drwxr-xr-x    2 1001     1001         4096 Sep 25 12:04 archivos
10 bytes transferred
-rw-r--r--    1 1001     1001           10 Sep 25 12:20 prueba.txt

El usuario solo ve su directorio, puede escribir en archivos y todo el tráfico va cifrado. Comprueba también que un intento sin TLS se rechaza:

lftp -u ftpuser -e "set ftp:ssl-allow false; ls; bye" your_server_ip
ls: Login failed: 530 Non-anonymous sessions must use encryption.

En FileZilla, crea una conexión con el protocolo FTP, cifrado Requiere FTP explícito sobre TLS y modo de transferencia pasivo. Acepta el certificado la primera vez.

Las transferencias quedan registradas en el log de vsftpd:

sudo tail -n 2 /var/log/vsftpd.log

Paso 7: Añadir más usuarios FTP

Para cada nuevo usuario repite el esquema del paso 2: crear el usuario con nologin, dejar su directorio personal propiedad de root con una subcarpeta escribible y añadir su nombre a /etc/vsftpd.userlist:

sudo adduser --shell /usr/sbin/nologin cliente2
sudo chown root:root /home/cliente2
sudo mkdir /home/cliente2/archivos
sudo chown cliente2:cliente2 /home/cliente2/archivos
echo cliente2 | sudo tee -a /etc/vsftpd.userlist

No hace falta reiniciar vsftpd: lee la lista de usuarios en cada inicio de sesión.

Paso 8: Configurar SFTP con OpenSSH

SFTP viene incluido en OpenSSH y no necesita vsftpd. Lo habitual es crear un grupo cuyos miembros solo pueden usar SFTP y quedan enjaulados en su directorio. Crea el grupo y un usuario:

sudo groupadd sftpusers
sudo adduser --shell /usr/sbin/nologin --ingroup sftpusers --no-create-home --home /srv/sftp/sftpuser sftpuser

Como en FTP, el directorio raíz de la jaula debe pertenecer a root y no ser escribible por nadie más. Dentro, crea una carpeta para el usuario:

sudo mkdir -p /srv/sftp/sftpuser/archivos
sudo chown root:root /srv/sftp /srv/sftp/sftpuser
sudo chmod 755 /srv/sftp /srv/sftp/sftpuser
sudo chown sftpuser:sftpusers /srv/sftp/sftpuser/archivos

Añade el bloque Match al final de /etc/ssh/sshd_config. Debe ir al final porque todo lo que haya después de un Match solo se aplica a los usuarios que coinciden con él:

sudo nano /etc/ssh/sshd_config
Match Group sftpusers
    ChrootDirectory %h
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no

ChrootDirectory %h enjaula al usuario en su directorio personal (/srv/sftp/sftpuser) y ForceCommand internal-sftp le impide ejecutar cualquier otra cosa. Valida la configuración y reinicia SSH:

sudo sshd -t
sudo systemctl restart ssh

sshd -t no muestra nada si la configuración es correcta. Mantén abierta tu sesión SSH actual hasta confirmar que puedes volver a conectar.

Prueba desde tu equipo:

sftp sftpuser@your_server_ip
Connected to your_server_ip.
sftp> ls
archivos
sftp> pwd
Remote working directory: /

El usuario ve / como raíz y no puede salir de su directorio. Si intenta abrir una shell con ssh sftpuser@your_server_ip, la conexión se cierra con el mensaje This service allows sftp connections only.

Solución de problemas

500 OOPS: vsftpd: refusing to run with writable root inside chroot(). El directorio personal del usuario es escribible por él. Aplica el chown root:root y chmod 755 del paso 2 y usa una subcarpeta para escribir.

530 Login incorrect con la contraseña correcta. Comprueba que el usuario está en /etc/vsftpd.userlist y que /usr/sbin/nologin figura en /etc/shells. Los detalles aparecen en sudo journalctl -u vsftpd y en /var/log/auth.log.

El login funciona pero el listado se queda colgado. Es el modo pasivo: el cliente no puede abrir el puerto de datos. Verifica que el rango 40000:40100/tcp está permitido en UFW y en cualquier firewall externo, y añade pasv_address si el servidor está detrás de NAT.

SFTP devuelve broken pipe o Connection closed justo tras autenticarse. Casi siempre es un problema de propietario en la jaula: /srv/sftp y /srv/sftp/sftpuser deben pertenecer a root y no ser escribibles por el grupo. El motivo exacto aparece en sudo journalctl -u ssh -n 20 como bad ownership or modes for chroot directory.

Conclusión

Tienes vsftpd funcionando en Ubuntu 24.04 solo con FTPS, usuarios enjaulados, una lista de usuarios permitidos y un rango pasivo controlado por el firewall, además de SFTP con OpenSSH para los usuarios que no necesitan FTP.

Como siguientes pasos, puedes proteger el puerto 21 y el 22 frente a ataques de fuerza bruta con fail2ban, sustituir el certificado autofirmado por uno de Let's Encrypt o usar autenticación por clave pública para los usuarios SFTP.