Configurar un FTP Server y ejecutar un script tras un evento

ftp

A continuación mostraré los sencillos pasos que son necesarios para configurar un FTP y monitorear los eventos para ejecutar un script al momento que se copie satisfactoriamente un archivo, cuando se elimine, al iniciar o cerrar la sesión. Este tipo de situaciones son muy comunes en los ambientes automatizados.

Me tocó configurar un servidor FTP para automatizar la entrada de órdenes que llegaban por correo electrónico y desde ahí un persona se encargaba de introducirlas al sistema con un formulario para cargar los registros de un archivo CSV, todo funcionaba perfecto, pero aún se necesitaba la intervención de dicha persona para una tarea que podía delegarse completamente a quien envíaba el archivo original (que por razones de seguridad no puede tener acceso a la plataforma, inclusive el webservices fue descartado).

Hay varias opciones en el ámbito GNU para solucionar esta situación, dos servidores FTP en específico ofrecen el disparado de eventos de forma nativa, sin embargo la primera opción era proftpd y no permitia esta opción si era específicada una ruta por defecto para el usuario del FTP (algo obligatorio para mi caso). Mi segunda opción fue pureftpd, tras varios intentos obtenía errores que luego de unas horas no pude resolver de forma amigable.

Tras esas experiencias decidí optar por un una herramienta complementaria al proftpd, estoy hablando de incron. Esta fabulosa aplicación es una especie de crontab que se encarga de monitorear eventos específicos en el sistema y disparar un script. Ya era solo configurar incron para que estuviera monitoreando la carpeta del usuario en el FTP y esperar por una acción de insertar un nuevo archivo.

Para instalar dichas aplicaciones estaré usando un ambiente sobre Debian 6. Primero actualizamos la lista de los repositorios e instalamos los paquetes:

apt-get update
apt-get install proftpd incron

Para configurar el proftpd modificamos el fichero /etc/shells y le agregamos /bin/false

echo "/bin/false" >> /etc/shells

Podemos crear un espacio común para los usuarios que utilizarán el FTP y agregar tantos usuarios vayan a utilizar el servicio:

cd /home
mkdir FTP-shared
useradd userftp -p your_password -d /home/FTP-shared -s /bin/false
passwd userftp
cd /home/FTP-shared/
mkdir download
mkdir upload
cd /home
chmod 755 FTP-shared
cd FTP-shared
chmod 755 download
chmod 777 upload

El archivo de configuración es /etc/proftpd.conf, procedemos a editarlo:

nano /etc/proftpd.conf

Lo configuramos de la siguiente manera:

# To really apply changes reload proftpd after modifications.

 AllowOverwrite on
 AuthAliasOnly on

# Choose here the user alias you want !!!!
 UserAlias sauron userftp

ServerName "ChezFrodon"
 ServerType standalone
 DeferWelcome on

MultilineRFC2228 on
 DefaultServer on
 ShowSymlinks off

TimeoutNoTransfer 600
 TimeoutStalled 100
 TimeoutIdle 2200

DisplayChdir .message
 ListOptions "-l"

RequireValidShell off

TimeoutLogin 20

RootLogin off

# It's better for debug to create log files 😉
 ExtendedLog /var/log/ftp.log
 TransferLog /var/log/xferlog
 SystemLog /var/log/syslog.log

#DenyFilter \*.*/

# I don't choose to use /etc/ftpusers file (set inside the users you want to ban, not useful for me)
 UseFtpUsers off

# Allow to restart a download
 AllowStoreRestart on

# Port 21 is the standard FTP port, so you may prefer to use another port for security reasons (choose here the port you want)
 Port 1980

# To prevent DoS attacks, set the maximum number of child processes
 # to 30. If you need to allow more than 30 concurrent connections
 # at once, simply increase this value. Note that this ONLY works
 # in standalone mode, in inetd mode you should use an inetd server
 # that allows you to limit maximum number of processes per service
 # (such as xinetd)
 MaxInstances 8

# Set the user and group that the server normally runs at.
 User nobody
 Group nogroup

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

PersistentPasswd off

MaxClients 8
 MaxClientsPerHost 8
 MaxClientsPerUser 8
 MaxHostsPerUser 8

# Display a message after a successful login
 AccessGrantMsg "welcome !!!"
 # This message is displayed for each access good or not
 ServerIdent on "you're at home"

# Lock all the users in home directory, ***** really important *****
 DefaultRoot ~

MaxLoginAttempts 5

#VALID LOGINS
 <Limit LOGIN>
 AllowUser userftp
 DenyALL
 </Limit>

<Directory /home/FTP-shared>
 Umask 022 022
 AllowOverwrite off
 <Limit MKD STOR DELE XMKD RNRF RNTO RMD XRMD>
 DenyAll
 </Limit>
 </Directory>

<Directory /home/FTP-shared/download/*>
 Umask 022 022
 AllowOverwrite off
 <Limit MKD STOR DELE XMKD RNEF RNTO RMD XRMD>
 DenyAll
 </Limit>
 </Directory>

<Directory /home/FTP-shared/upload/>
 Umask 022 022
 AllowOverwrite on
 <Limit READ RMD DELE>
 DenyAll
 </Limit>

<Limit STOR CWD MKD>
 AllowAll
 </Limit>
 </Directory>

Reiniciamos el proftpd:

/etc/init.d/proftpd restart

Configuramos el incron para permitir que los scripts se ejecuten como root:

echo "root" >> /etc/incron.allow

Luego modificamos los eventos que estarán siendo monitoreados:

incrontab -e

Dentro del editor, la forma de hacerlo es la siguiente:

/home/FTP-shared/upload/ IN_CLOSE_WRITE /home/FTP-shared/script.sh $@/$#

Los parámetros que se pueden aceptan son los siguientes:

  • $$ – Envía el signo de dólar
  • $@ – La ruta que se está monitoreando
  • $# – El nombre del archivo que ha disparado el evento
  • $% – Flags del evento (en texto)
  • $& – Flags del evento (en números)

Los tipos de eventos que pueden ser monitoreados son los siguientes:

  • IN_ACCESS: Archivo que ha sido leído
  • IN_ATTRIB: Cambio de metadata como permisos, fecha y demás atributos.
  • IN_CLOSE_WRITE: Archivo que ha sido abierto para la escritura y ha sido cerrado (creación de nuevo archivo por ejemplo).
  • IN_CREATE: Archivo o directorio ha sido creado (esto dispara el evento sin importar si ha sido cerrado).
  • IN_DELETE: Archivo o directorio ha sido eliminado.
  • IN_MODIFY: Archivo modificado.
  • IN_MOVE_SELF: Archivo o directorio ha sido movido dentro del ambiente monitoreado.
  • IN_MOVED_FROM: Archivo o directorio ha sido movido fuera del ambiente monitoreado.
  • IN_OPEN: Archivo ha sido abierto.

Espero este tutorial les haya sido de ayuda.