Una implementación personalizada del Protocolo de Transferencia de Archivos (FTP) en Java que incluye un servidor multihilo con control de acceso basado en roles (RBAC), un cliente GUI de estilo retro y un modo de consola interactivo construido sobre Apache Commons Net.
- Resumen
- Características
- Arquitectura
- Prerrequisitos
- Instalación
- Inicio Rápido
- Uso
- Configuración
- Modos de Transferencia FTP
- Control de Acceso Basado en Roles
- Seguridad
- Solución de Problemas
- Contribuciones
- Licencia
- Agradecimientos
Este proyecto es una implementación educativa completa del Protocolo de Transferencia de Archivos (FTP) en Java, construido desde cero para demostrar:
- Programación de Red: Programación de sockets, multihilo y arquitectura cliente-servidor.
- Implementación de Protocolos: Manejo de comandos/respuestas FTP conforme al RFC 959.
- Sistemas Concurrentes: Gestión de un pool de hilos para múltiples conexiones simultáneas.
- Desarrollo de GUI: Interfaz retro basada en Swing con actualizaciones en tiempo real.
- Patrones de Seguridad: Control de acceso basado en roles (RBAC) y sistemas de autenticación.
Cliente FTP con interfaz gráfica estilo terminal retro ámbar
Componente | Archivo | Descripción |
---|---|---|
Servidor | JavaFtpServer.java | Servidor FTP multihilo que soporta los modos de transferencia ACTIVO y PASIVO. |
Cliente de Consola | JavaFtpClient.java | Cliente FTP interactivo de línea de comandos usando Apache Commons Net. |
Cliente GUI | ClientGUI.java | Interfaz gráfica de estilo terminal retro ámbar para operaciones FTP. |
Dependencia | commons-net-3.11.1.jar |
Biblioteca Apache Commons Net (incluida en lib/). |
Al estudiar y ejecutar este proyecto, entenderás:
✓ Cómo funciona el protocolo FTP a nivel de red (canales de control y de datos). ✓ Cómo implementar el análisis de comandos y los códigos de respuesta del lado del servidor. ✓ Cómo gestionar conexiones de clientes concurrentes con pools de hilos. ✓ Cómo manejar los modos de transferencia de datos ACTIVO y PASIVO. ✓ Cómo construir sistemas de permisos basados en roles. ✓ Cómo crear aplicaciones de escritorio con GUI usando Java Swing. ✓ Cómo trabajar con E/S de archivos y flujos de red.
- Conexiones Concurrentes: Arquitectura multihilo que utiliza
ExecutorService
para manejar múltiples clientes simultáneos. - Autenticación de Usuarios: Sistema de autenticación basado en archivos con credenciales en texto plano almacenadas en
files/users/users.txt
. - Control de Acceso Basado en Roles (RBAC): Sistema de permisos de tres niveles:
BASICO
— Acceso de solo lectura (LIST, RETR, CWD, PWD).INTERMEDIO
— Acceso de lectura/escritura (añade STOR, MKD, RMD, RNFR, RNTO, DELE).ADMINISTRADOR
— Acceso administrativo completo.
- Modos de Transferencia Duales:
- Modo PASIVO — El servidor abre un puerto de datos y el cliente se conecta (compatible con NAT/firewall).
- Modo ACTIVO — El cliente abre un puerto de datos y el servidor se conecta (requiere redirección de puertos en el cliente).
- Soporte de Comandos FTP: USER, PASS, SYST, PASV, PORT, LIST, STOR, RETR, DELE, MKD, RMD, RNFR, RNTO, CWD, CDUP, PWD, QUIT.
- Menú interactivo con 10 operaciones FTP.
- Configuración de conexión de host/puerto personalizable.
- Selección del modo de transferencia (PASIVO/ACTIVO).
- Feedback de las operaciones en tiempo real.
- Diseño Retro: Estética de terminal ámbar inspirada en los años 80.
- Tabla de Archivos: Visualización con tipo de archivo, nombre, tamaño y fecha de modificación.
- Botones Dedicados: Acceso con un clic a 10 operaciones FTP (REFRESH, UPLOAD, DOWNLOAD, DELETE, MKD, RMD, RENAME, CD, CDUP, PWD).
- Registro en Tiempo Real: Mensajes codificados por colores (verde=éxito, rojo=error, amarillo=info).
- Tipografía Monoespaciada: Fuente Consolas para una apariencia retro auténtica.
- Barras de Progreso: Indicadores visuales en tiempo real para transferencias de archivos.
- Selección Múltiple: Operaciones batch con Ctrl+Click o Shift+Click.
- Navegación Intuitiva: Doble clic en directorios para navegar.
- Encoding UTF-8: Soporte completo para nombres con acentos, ñ y caracteres especiales.
- Transferencia Binaria: Configuración automática para archivos PDF, ZIP, imágenes y binarios.
java-ftp/
├── src/
│ └── FTP/
│ ├── Client/
│ │ ├── JavaFtpClient.java # Punto de entrada del cliente de consola
│ │ ├── ClientFunctions.java # Implementaciones de comandos del cliente
│ │ └── ClientGUI.java # Cliente GUI (interfaz retro)
│ ├── Server/
│ │ ├── JavaFtpServer.java # Punto de entrada del servidor
│ │ ├── FtpClientHandler.java # Manejador por conexión (Runnable)
│ │ ├── ServerFunctions.java # Implementaciones de comandos FTP
│ │ ├── User.java # Modelo de credenciales de usuario
│ │ └── UserProfile.java # Enum para RBAC
│ └── Util/
│ └── Util.java # Utilidades compartidas
├── lib/
│ └── commons-net-3.11.1.jar # Biblioteca Apache Commons Net
├── files/
│ └── users/
│ └── users.txt # Base de datos de credenciales de usuario
├── bin/ # Clases compiladas (generado)
├── [LICENSE](LICENSE)
└── [README.md](README.md)
- JDK: 8 o superior.
- Shell: PowerShell (Windows) o Bash (Linux/macOS).
- Red: El puerto 21 debe estar disponible (o modificar
CONTROL_PORT
para pruebas en puertos no privilegiados >1024).
Antes de la instalación, verifica tu entorno:
# Comprobar la versión de Java (debe ser 8+)
java -version
javac -version
# Verificar la estructura del proyecto
ls lib/commons-net-3.11.1.jar # Debería existir
git clone <url-del-repositorio>
cd java-ftp
Crea los directorios necesarios:
# Windows (PowerShell)
mkdir -Force bin, files\users
# Linux/macOS
mkdir -p bin files/users
Crea files/users/users.txt
con usuarios iniciales:
# Windows (PowerShell)
@"
admin:admin789:ADMINISTRADOR
alice:pass123:BASICO
bob:secret456:INTERMEDIO
"@ | Out-File -FilePath "files\users\users.txt" -Encoding ASCII
# Linux/macOS
cat > files/users/users.txt << 'EOF'
admin:admin789:ADMINISTRADOR
alice:pass123:BASICO
bob:secret456:INTERMEDIO
EOF
Formato de Usuario: nombre_usuario:contraseña:PERFIL
Perfiles Disponibles:
BASICO
- Solo lectura (listar, descargar).INTERMEDIO
- Lectura/escritura (añade subir, eliminar, renombrar).ADMINISTRADOR
- Acceso completo.
javac -d bin -cp "lib/commons-net-3.11.1.jar" `
src\FTP\Client\*.java `
src\FTP\Server\*.java `
src\FTP\Util\*.java
Verificar compilación:
ls bin\FTP\Server\JavaFtpServer.class # Debería existir
javac -d bin -cp "lib/commons-net-3.11.1.jar" \
src/FTP/Client/*.java \
src/FTP/Server/*.java \
src/FTP/Util/*.java
Verificar compilación:
ls bin/FTP/Server/JavaFtpServer.class # Debería existir
chmod +x run-client-gui.sh
Ahora estás listo para ejecutar el servidor y el cliente. Procede a Inicio Rápido.
💡 ¿Primera vez? Consulta QUICK_START.md para una guía visual paso a paso.
Sigue estos pasos para poner en marcha el servidor y el cliente FTP:
Crea la estructura de directorios necesaria y el archivo de usuarios:
# Windows (PowerShell)
mkdir -Force files\users
New-Item -Path "files\users\users.txt" -ItemType File -Force
# Linux/macOS
mkdir -p files/users
touch files/users/users.txt
Añade las credenciales de usuario a files/users/users.txt
:
admin:admin789:ADMINISTRADOR
alice:pass123:BASICO
bob:secret456:INTERMEDIO
# Windows (PowerShell)
mkdir -Force bin
javac -d bin -cp "lib/commons-net-3.11.1.jar" src\FTP\Client\*.java src\FTP\Server\*.java src\FTP\Util\*.java
# Linux/macOS
mkdir -p bin
javac -d bin -cp "lib/commons-net-3.11.1.jar" src/FTP/Client/*.java src/FTP/Server/*.java src/FTP/Util/*.java
Resultado esperado: Sin errores. Los archivos .class
compilados estarán en el directorio bin/
.
Abre una ventana de terminal y ejecuta:
# Windows (PowerShell)
java -cp "bin;lib/commons-net-3.11.1.jar" FTP.Server.JavaFtpServer
# Linux/macOS (puede requerir sudo para el puerto 21)
java -cp "bin:lib/commons-net-3.11.1.jar" FTP.Server.JavaFtpServer
Cuando se te solicite:
- Introduce el directorio raíz:
files
- El servidor mostrará:
✓ Servidor escuchando en el puerto 21
Mantén esta terminal abierta - el servidor debe ejecutarse continuamente.
Abre una nueva ventana de terminal (mantén el servidor en ejecución) y elige una de las siguientes opciones:
# Windows
.\run-client-gui.bat
# Linux/macOS
chmod +x run-client-gui.sh
./run-client-gui.sh
En la ventana de la GUI:
- Host:
localhost
- Puerto:
21
- Usuario:
admin
- Contraseña:
admin789
- Modo: Selecciona
PASSIVE
- Haz clic en "▶ CONNECT"
Deberías ver un mensaje de éxito en verde y la lista de archivos se cargará.
# Windows (PowerShell)
java -cp "bin;lib/commons-net-3.11.1.jar" FTP.Client.JavaFtpClient
# Linux/macOS
java -cp "bin:lib/commons-net-3.11.1.jar" FTP.Client.JavaFtpClient
Cuando se te solicite:
- Servidor:
localhost
(pulsa Enter) - Puerto:
21
(pulsa Enter) - Usuario:
admin
- Contraseña:
admin789
- Modo:
1
(para PASIVO)
Deberías ver:
- Terminal del servidor:
✓ Usuario 'admin' ha iniciado sesión correctamente
- Cliente: Listado de archivos o menú interactivo.
Problema | Solución |
---|---|
Address already in use |
El puerto 21 está ocupado. Cambia CONTROL_PORT en JavaFtpServer.java línea 41 a 2121 . |
Permission denied (Linux/macOS) |
Ejecuta el servidor con sudo o usa un puerto >1024. |
ClassNotFoundException |
Verifica que commons-net-3.11.1.jar exista en el directorio lib/ . |
Connection refused |
Asegúrate de que el servidor esté en ejecución y escuchando en el puerto correcto. |
Fallo de autenticación | Comprueba que files/users/users.txt exista con el formato correcto. |
- Sube un archivo usando la opción
[2]
en la consola o el botón UPLOAD en la GUI. - Navega por los directorios con
[8]
o haciendo doble clic en las carpetas en la GUI. - Prueba diferentes cuentas de usuario con distintos niveles de permiso.
- Lee la sección de Uso para operaciones detalladas.
Windows (PowerShell):
java -cp "bin;lib/commons-net-3.11.1.jar" FTP.Server.JavaFtpServer
Linux/macOS:
# Puerto estándar 21 (requiere sudo)
sudo java -cp "bin:lib/commons-net-3.11.1.jar" FTP.Server.JavaFtpServer
# Alternativa: Puerto no privilegiado (cambia CONTROL_PORT a 2121 primero)
java -cp "bin:lib/commons-net-3.11.1.jar" FTP.Server.JavaFtpServer
┌─────────────────────────────────────┐
│ 1. Visualización del Banner ASCII │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ 2. Petición: Directorio raíz │
│ Entrada: files │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ 3. Validar Estructura │
│ ✓ files/ existe │
│ ✓ files/users/users.txt existe │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ 4. Iniciar Escucha │
│ Servidor escuchando en puerto 21 │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ 5. Listo para Conexiones │
│ [LOG] Esperando clientes... │
└─────────────────────────────────────┘
✓ Servidor escuchando en el puerto 21 # Servidor iniciado correctamente
✓ Cliente conectado: /127.0.0.1:54321 # Nueva conexión de cliente
✓ Usuario 'admin' ha iniciado sesión # Autenticación exitosa
⇄ LIST: /files/ # Solicitud de listado de archivos
⇄ RETR: document.txt # Descarga de archivo
⇄ STOR: upload.jpg # Carga de archivo
✗ Acceso denegado para el usuario 'alice' # Error de permisos
✓ Cliente desconectado: admin # Cliente cerró sesión
Para uso en producción (no recomendado - ver Seguridad):
-
Cambiar Puerto por Defecto (Linux/macOS):
# Editar src/FTP/Server/JavaFtpServer.java private static final int CONTROL_PORT = 2121; // Usar un puerto no privilegiado
-
Ejecutar como Servicio del Sistema:
# Crear un servicio systemd (Linux) sudo nano /etc/systemd/system/ftp-server.service
-
Configurar el Firewall:
# Permitir puertos FTP sudo ufw allow 21/tcp sudo ufw allow 20/tcp sudo ufw allow 1024:65535/tcp # Puertos para modo pasivo
Nota: En sistemas Unix, vincularse al puerto 21 requiere privilegios de root/sudo. Para desarrollo/pruebas, modifica CONTROL_PORT
en JavaFtpServer.java línea 41 a un puerto >1024 (ej. 2121
).
PowerShell:
java -cp "bin;lib/commons-net-3.11.1.jar" FTP.Client.JavaFtpClient
Linux/macOS:
java -cp "bin:lib/commons-net-3.11.1.jar" FTP.Client.JavaFtpClient
- Introduce el nombre de host (por defecto:
localhost
). - Introduce el puerto (por defecto:
21
). - Proporciona nombre de usuario y contraseña.
- Selecciona el modo de transferencia (
PASSIVE
oACTIVE
).
[1] Listar archivos
[2] Subir archivo
[3] Descargar archivo
[4] Eliminar archivo
[5] Crear directorio
[6] Eliminar directorio
[7] Renombrar archivo/directorio
[8] Cambiar directorio de trabajo
[9] Cambiar al directorio padre
[10] Salir
PowerShell:
java -cp "bin;lib/commons-net-3.11.1.jar" FTP.Client.ClientGUI
# O usa el script de conveniencia:
.\run-client-gui.bat
Linux/macOS:
java -cp "bin:lib/commons-net-3.11.1.jar" FTP.Client.ClientGUI
# O usa el script de conveniencia:
./run-client-gui.sh
- Rellena los campos: Host, Puerto, Usuario, Contraseña.
- Selecciona el modo (PASSIVE/ACTIVE).
- Haz clic en "▶ CONNECT".
- Navega por los archivos usando la tabla y los botones de operación.
Crea el archivo de usuarios en files/users/users.txt
con el siguiente formato:
nombre_usuario:contraseña:PERFIL
Perfiles: BASICO
, INTERMEDIO
, ADMINISTRADOR
Ejemplo:
alice:pass123:BASICO
bob:secret456:INTERMEDIO
admin:admin789:ADMINISTRADOR
- Cuándo usarlo: Cliente detrás de un NAT/firewall.
- Cómo funciona:
- El cliente envía el comando
PASV
. - El servidor abre un puerto aleatorio y envía los detalles de conexión.
- El cliente se conecta a ese puerto para la transferencia de datos.
- El cliente envía el comando
- Configuración: Manejado automáticamente por el cliente.
- Cuándo usarlo: Cliente con IP pública o redirección de puertos adecuada.
- Cómo funciona:
- El cliente abre un puerto local y envía el comando
PORT
con los detalles de conexión. - El servidor se conecta al puerto especificado por el cliente para la transferencia de datos.
- El cliente abre un puerto local y envía el comando
- Configuración: El cliente solicita un puerto de datos (se recomienda >5000).
Comando | BASICO | INTERMEDIO | ADMINISTRADOR |
---|---|---|---|
LIST | ✓ | ✓ | ✓ |
RETR | ✓ | ✓ | ✓ |
CWD | ✓ | ✓ | ✓ |
CDUP | ✓ | ✓ | ✓ |
PWD | ✓ | ✓ | ✓ |
STOR | ✗ | ✓ | ✓ |
DELE | ✗ | ✓ | ✓ |
MKD | ✗ | ✓ | ✓ |
RMD | ✗ | ✓ | ✓ |
RNFR | ✗ | ✓ | ✓ |
RNTO | ✗ | ✓ | ✓ |
Los comandos no autorizados devuelven: 530 Not logged in
o el código de error apropiado.
Esta implementación está diseñada con fines de aprendizaje y contiene varias limitaciones de seguridad.
- Almacenamiento de contraseñas en texto plano en
users.txt
. - Sin cifrado TLS/SSL para los canales de control o de datos.
- Validación de entrada básica sin sanitización exhaustiva.
- Sin limitación de velocidad o protección contra fuerza bruta.
- Protección de un solo nivel contra el recorrido de directorios (directory traversal).
Antes de usar en producción, implementa:
- Hashing de contraseñas (bcrypt/Argon2) con sales.
- Cifrado TLS (FTPS).
- Validación exhaustiva de rutas contra directory traversal.
- Limitación de intentos de autenticación.
- Registros de auditoría.
- Cuotas de recursos por usuario.
- Alternativas modernas (SFTP, APIs de archivos sobre HTTPS).
# Opción 1: Ejecutar con sudo (no recomendado para desarrollo)
sudo java -cp "bin:lib/commons-net-3.11.1.jar" FTP.Server.JavaFtpServer
# Opción 2: Usar un puerto no privilegiado (recomendado)
# Modifica CONTROL_PORT en JavaFtpServer.java a 2121
- Verifica que el servidor esté en ejecución (
netstat -an | grep 21
). - Comprueba que las reglas del firewall permitan el tráfico en el puerto 21.
- Confirma que el cliente se esté conectando al host/puerto correcto.
- Verifica que
files/users/users.txt
exista y tenga el formato correcto. - Comprueba si hay espacios en blanco al final de las entradas de usuario/contraseña.
- Asegúrate de que el perfil de usuario sea un valor enum válido.
# Verificar la versión de JDK
java -version
# Asegurarse de que el JAR de commons-net existe
ls lib/commons-net-3.11.1.jar
# Limpiar y reconstruir
rm -rf bin
mkdir bin
javac -d bin -cp "lib/commons-net-3.11.1.jar" src/FTP/**/*.java
¡Las contribuciones son bienvenidas! Por favor, siéntete libre de enviar:
- Informes de errores a través de issues en el repositorio.
- Mejoras de funcionalidades a través de Pull Requests.
- Mejoras en la documentación.
- Informes de vulnerabilidades de seguridad (por favor, divúlguelos de manera responsable).
- Añadir soporte para TLS/SSL.
- Implementar almacenamiento seguro de contraseñas.
- Añadir pruebas unitarias exhaustivas.
- Soportar comandos FTP adicionales (ABOR, REST, STAT).
- Soporte para IPv6.
- Archivo de configuración para los ajustes del servidor.
- Haz un fork del repositorio.
- Crea una rama para tu nueva característica (
git checkout -b feature/amazing-feature
). - Confirma tus cambios (
git commit -m 'Add amazing feature'
). - Sube la rama a tu fork (
git push origin feature/amazing-feature
). - Abre un Pull Request.
Este proyecto está licenciado bajo la Licencia MIT — consulta el archivo LICENSE para más detalles.
- Construido con la biblioteca Apache Commons Net.
- Protocolo FTP: RFC 959.
- Desarrollado con fines educativos para comprender los protocolos de red y la programación de sockets en Java.
- RFC 959 - File Transfer Protocol (FTP)
- Documentación de Apache Commons Net
- Guía de Programación de Red en Java
Desarrollado por Edu Díaz a.k.a RGiskard7 ❤️