Crear SFTP en Alta disponibilidad en Azure

En la siguiente entrada vamos a ver como montar una arquitectura de SFTP en Azure en alta disponibilidad. 

Este tutorial no veremos en detalle como desplegar un servidor en azure, ni una vnet…etc por lo tanto se pasará un poco por encima en la creación de estos recursos.

Escenario

Para garantizar la alta disponibilidad del servicio disponemos de dos servidores GNU/Linux en diferentes zonas de disponibilidad.

Dicha alta disponibilidad cuenta con balanceo de carga entre los diferentes servidores mediante Azure Load Balancer, de la misma forma, para otorgar persistencia de los datos transferidos contamos con almacenamiento compartido entre los dos servidores empleando Azure File share

Para montar los recursos compartidos de Azure FIle Share se realizará mediante autofs, de esta forma garantizamos que los recursos únicamente se monten cuando sean necesarios.

Diagrama de red

En primer lugar tenemos que crear una Vnet

Configuramos un Resource Group y un nombre para la Vnet

Configuramos el rango de ip que creamos

A continuación en el apartado de Security y tag lo debemos por defecto (a no ser que nosotros queramos configurar algo extra) y presionamos a crear

Tras crear la VNet desplegamos los servidores GNU/Linux, en mi caso no voy a poner los pasos de como desplegar un nuevo servidor para más información sobre esto podemos ver el siguiente link o otros de los muchos recursos que te puedes encontrar en internet. de la misma forma, puedes obtener información sobre los availability set

Sin mas preámbulos, muestro mi configuración de availability set

Una vez desplegado los servidores tenemos que desplegar el Load Balancer, para ello nos vamos a Load Balancer y presionamos en Crear

Configurar Load Balancer

Lo primero que tenemos que configurar es el grupo de recursos, el nombre de load balancer, región y que tipo de load balancer queremos, en nuestro caso dado que va a estar publicado a internet seleccionaremos Public

Configuramos el direccionamiento publico

Creamos un pool agregando los dos servidores desplegados anteriormente

Establecemos el chequeo health al puerto 22

Configuramos en Load balancer, en mi caso voy  como podemos ver en la siguiente imagen, establecemos el puerto 2222 en escucha en el load balancer y esté lo redirigirá al puerto 22 del pool creado anteriormente

Establecemos las reglas de Inbound 

Por ultimo establecemos las reglas de  Outbound

Nos dirigimos al NSG de los servidores y creamos la siguiente regla, no se recomienda bajo ningún concepto tener el puerto del SSH expuesto a internet, pero si por necesidad de negocio no se puede disponer de una VPN o se puede realizar un filtrado de direcciones…

Configuración Storage Account

Una vez creado el Load Balancer nos dirigimos al Storage Account y presionamos en Create

Tras complementar todos los datos que nos pide y crear el Storage Account nos vamos a File Share y creamos un recurso compartido. Una vez creado el recurso, accedemos a el y presionamos conectar.

Copiamos las credenciales para configurarlas en nuestros servidores GNU/Linux

A continuación vamos a configurar el servicio de SFTP en nuestros servidores, por lo tanto todos estos pasos se tendrán que realizar en ambos nodos.

Accedemos mediante SSH a nuestros servidores GNU/Linux y creamos las carpetas en donde se va almacenar el archivo que contiene las claves de acceso al recurso compartido. 

mkdir /root/smbcredentials/

Configuramos el usuario y la contraseña que hemos obtenido anteriormente. 

cat /root/smbcredentials/sftppro.cred
username=sftp
password=paSsSSsw0rd===

Asignamos los permisos correctamente

chown root:root /root/smbcredentials/sftppro.cred 
chmod 600 /root/smbcredentials/sftppro.cred 

Creación de usuario de SFTP

groupadd sftp
useradd -g sftp  -s /bin/false -d /sftp/sftpuser sftpuser
passwd sftpuser

creamos el home del usuario y otorgamos los permisos

mkdir -p /sftp/sftpuser
chmod 755 /sftp/sftpuser
chown root:root /sftp/sftpuser

Accedemos al /etc/ssh/sshd_config y debemos modificar la siguiente linea:

Subsystem sftp /usr/lib/openssh/sftp-server

Por esta:

Subsystem sftp internal-sftp

También tenemos que añadir la siguiente configuración al final del fichero:

Match user sftpuser
ChrootDirectory %h
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
KbdInteractiveAuthentication yes

Configurar AutoFS

para montar el recurso de Azure File lo vamos a realizar mediante autofs. Instalamos los paquetes necesarios:

 apt-get install autofs samba-client

A continuación tienes que añadir la siguiente linea en /etc/auto.master

Como podemos ver en este fichero de configuración la primera parte (/sftp/sftpuser) es el home del usuario y /etc/auto.master.d/sftpuser corresponde al fichero de configuración de autofs en donde vamos a establecer los datos necesarios para poder montar el recurso. 

/sftp/sftpuser/ /etc/auto.master.d/sftpuser

Para poder montar el recuso mediante autofs debemos establecer la configuración con los datos obtenidos de Azure File. 

Esta configuración se realizará en mi caso en:  /etc/auto.master.d/sftpuser  dado que así lo hemos establecido en el archivo /etc/auto.master

Es muy importante poner correctamente todos los datos, URL del recurso, archivos de las credenciales que hemos configurado anteriormente y el UUID y GUID

 

CARPETA_A_MONTAR -fstype=cifs,nofail,vers=3.0,credentials=/root/smbcredentials/sftppro.cred,uid=UUID_USUARIO,gid=UUID_GRUPO ://STORAGE_ACCOUNT_CREADO.file.core.windows.net/AZURE_FILE_CREADO

CARPETA_A_MONTAR: Debemos que establecer el nombre de la carpeta que se va a montar en el home del usuario que estamos creando (Por ejemplo: /sftp/sftpuser/Public)

credentials: Tenemos que añadir el archivo donde anteriormente hemos configurado el usuario y la contraseña

uid y gid: En este campo tenemos que agregar el UUID del usuario, este dato lo podemos sacar con: «id -u USUARIO» o en /etc/passwd y el del grupo con «id -g GRUPO» o en /etc/groups

//STORAGE_ACCOUNT_CREADO.file.core.windows.net: Este dato se trata de la URL para acceder al Storage Acount que hemos creado, y se puede ver accediendo al recurso compartido que hemos creado en Azure File Share y presionando el conectar.

AZURE_FILE_CREADO: De la misma forma, este recurso es la carpeta compartida creada en Azure File Share

Ejemplo

Public -fstype=cifs,nofail,vers=3.0,credentials=/root/smbcredentials/sftppro.cred,uid=1001,gid=100 ://sftpstorage.file.core.windows.net/fsprueba

Reiniciamos el servicio de autofs y ssh

systemctl restart sshd
systemctl restart autofs

Comprobar el funcionamiento del SFTP

Mediante un cliente SFTP intentamos acceder al recurso

De la misma forma, comprobamos si monta correctamente el recurso mediante autofs el recurso de azure, para ello podemos hacer un df -h

Configurar fail2ban y ipset

Ya tenemos configurado correctamente nuestro SFTP, por ultimo falta configurar fail2ban y ipset para prevenir ataques de fuerza bruta., dado que este recurso estará expuesto a internet.

apt install fail2ban
 ipset

Copiamos la configuración

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

En mi caso,  dado que los servidores son Ubuntu y este tiene por defecto UFW como firewall he configurado fail2ban utilizando este firewall. 

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 
bantime = 1d
findtime = 10m
maxretry = 5

[ssh-with-ufw]
enabled = true
port = 22
filter = sshd
action = ufw[application="OpenSSH", blocktype=reject]
logpath = /var/log/auth.log
maxretry = 3

Reiniciamos el servicio

systemctl restart fail2ban

Para la configuración de ipset he utilizado el script: https://github.com/trick77/ipset-blacklist el cual me gusto mucho la configuración.

wget -O /usr/local/sbin/update-blacklist.sh https://raw.githubusercontent.com/trick77/ipset-blacklist/master/update-blacklist.sh
chmod +x /usr/local/sbin/update-blacklist.sh
mkdir -p /etc/ipset-blacklist ; wget -O /etc/ipset-blacklist/ipset-blacklist.conf https://raw.githubusercontent.com/trick77/ipset-blacklist/master/ipset-blacklist.conf

En mi caso, cambie esta configuración quedando de la siguiente forma:

IPSET_BLACKLIST_NAME=blacklist # change it if it collides with a pre-existing ipset list
IPSET_TMP_BLACKLIST_NAME=${IPSET_BLACKLIST_NAME}-tmp

# ensure the directory for IP_BLACKLIST/IP_BLACKLIST_RESTORE exists (it won't be created automatically)
IP_BLACKLIST_RESTORE=/etc/ipset-blacklist/ip-blacklist.restore
IP_BLACKLIST=/etc/ipset-blacklist/ip-blacklist.list

VERBOSE=yes # probably set to "no" for cron jobs, default to yes
FORCE=yes # will create the ipset-iptable binding if it does not already exist
let IPTABLES_IPSET_RULE_NUMBER=1 # if FORCE is yes, the number at which place insert the ipset-match rule (default to 1)

# Sample (!) list of URLs for IP blacklists. Currently, only IPv4 is supported in this script, everything else will be filtered.
BLACKLISTS=(
    "file:///etc/ipset-blacklist/ip-blacklist-custom.list" # optional, for your personal nemeses (no typo, plural)
    "file:///etc/ipset-blacklist/ip-blacklist-shodan.list" # Shodan
    "https://www.projecthoneypot.org/list_of_ips.php?t=d&rss=1" # Project Honey Pot Directory of Dictionary Attacker IPs
    "https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.1.1.1"  # TOR Exit Nodes
    "http://danger.rulez.sk/projects/bruteforceblocker/blist.php" # BruteForceBlocker IP List
    "https://www.spamhaus.org/drop/drop.lasso" # Spamhaus Don't Route Or Peer List (DROP)
    "https://cinsscore.com/list/ci-badguys.txt" # C.I. Army Malicious IP List
    "https://lists.blocklist.de/lists/all.txt" # blocklist.de attackers
    "https://blocklist.greensnow.co/greensnow.txt" # GreenSnow
    "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level1.netset" # Firehol Level 1
    "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/stopforumspam_7d.ipset" # Stopforumspam via Firehol
    "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/alienvault_reputation.ipset" #Alienvault reputation
    "http://ipverse.net/ipblocks/data/countries/af.zone" #Afghanistan
    "http://ipverse.net/ipblocks/data/countries/cn.zone" #China
    "http://ipverse.net/ipblocks/data/countries/ir.zone" #Iran
    "http://ipverse.net/ipblocks/data/countries/pk.zone" #Pakistan
    "http://ipverse.net/ipblocks/data/countries/pk.zone" #India
    "http://ipverse.net/ipblocks/data/countries/hk.zone" #Hong Kong
    "http://ipverse.net/ipblocks/data/countries/kp.zone" #North Korea
    "http://ipverse.net/ipblocks/data/countries/kr.zone" #South Korea
    "http://ipverse.net/ipblocks/data/countries/ru.zone" #Russia
    "http://ipverse.net/ipblocks/data/countries/tw.zone" #Taiwan
    "http://ipverse.net/ipblocks/data/countries/il.zone" #Israel
    "http://ipverse.net/ipblocks/data/countries/sa.zone" #Saudi Arabia
    "http://ipverse.net/ipblocks/data/countries/tr.zone" #Turkey
    "http://ipverse.net/ipblocks/data/countries/vn.zone" #Vietnam
    "http://ipverse.net/ipblocks/data/countries/lt.zone" #Lithuania
    "http://ipverse.net/ipblocks/data/countries/ee.zone" #Estonia
    "http://ipverse.net/ipblocks/data/countries/sg.zone" #Singapore
    "http://ipverse.net/ipblocks/data/countries/my.zone" #Malaysia
    "http://ipverse.net/ipblocks/data/countries/ua.zone" #Ukraine
)
MAXELEM=131072

De la misma forma, cree este pequeño script que aunque es cutre funciona correctamente. 

En este script agrego todos los ataques detectados por fail2ban a una backlist de ipset

#!/bin/bash
filecontent=(`zgrep 'Ban' /var/log/fail2ban.log* | awk '{print $8}'`)
blacklist=/etc/ipset-blacklist/ip-blacklist-custom.list
blacklist1=$( cat $blacklist )

touch $blacklist.1

for ip in "${filecontent[@]}"
do


  if [[ " $blacklist1" =~ "$ip" ]]
    then
        echo "" > /dev/null 2>&1

  else
       echo "$ip" >> $blacklist.1
  fi


done

sort -u $blacklist.1 >>  $blacklist
sed -i '/^$/d'  $blacklist
rm  $blacklist.1
/usr/local/sbin/update-blacklist.sh /etc/ipset-blacklist/ipset-blacklist.conf

Por ultimo, configuro este script en el crontab

@hourly           root /usr/local/sbin/update-blacklist-custom.sh

Por ultimo, creamos un script para la creación del usuario automáticamente, en este script no crea el File share en Azure, eso es lo único que tiene que crear a mano.

#!/bin/bash
usage()
{
cat << EOF
USO: $0 -G grupo -u usuario  -f file system
Script para la creacion de usuarios enjaulados SFTP
OPCIONES:
   -G      Grupo
   -u      Usuario SFTP
   -f      file system
ejemplo de uso: /usr/bin/createuser.sh -G sftp -u usersftp -f /sftp/usersftp
EOF
}

inputgroup=
inputusuario=
inputfs=
remotesrv=X.X.X.X
while getopts "hH:G:u:f:" OPTION
do
        case $OPTION in
                h)
                usage
                exit 1
                        ;;
                G)
                inputgroup=$OPTARG
                        ;;
                u)
                inputusuario=$OPTARG
                        ;;
                f)
                inputfs=$OPTARG
                        ;;
                esac
done

if [ -z $inputgroup ] || [ -z $inputusuario ] || [ -z $inputfs ]
then
        usage
        exit 1
fi

if [[ $EUID -ne 0 ]]; then
    echo "Este script se tiene que ejecutar con el usuario root"
    exit 1
fi

function SSHconfig (){
if [ -f "/etc/ssh/sshd_config-bck" ]
then

cat << EOF >> /etc/ssh/sshd_config

Match user $inputusuario
ChrootDirectory %h
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
KbdInteractiveAuthentication yes
EOF
else
   echo "No se encontro el fichero de configuracion /etc/ssh/sshd_config-bck"
   exit 1
fi
}

checkuser=`getent passwd $inputusuario | wc -l`

if [ $(getent group admin) ]; then
  echo "Existe el grupo $inputgroup"
else
  
  groupadd $inputgroup
  ssh root@$remotesr "groupadd $inputgroup"

fi


if [ $checkuser == "0"  ]
then


useradd -g $inputgroup  -s /bin/false -d $inputfs $inputusuario
ssh root@$remotesrv "useradd -g $inputgroup  -s /bin/false -d $inputfs $inputusuario"
passwd $inputusuario

echo "Repite de nuevo la password para mprolsftp002"
ssh root@$remotesrv "passwd $inputusuario"

mkdir -p $inputfs/Processed
chmod 755 $inputfs
chown root:root $inputfs
chown $inputusuario:$inputgroup $inputfs/Processed



cp /etc/ssh/sshd_config /etc/ssh/sshd_config-bck

SSHconfig

scp /etc/ssh/sshd_config root@$remotesrv:/etc/ssh/sshd_config


service sshd restart
ssh root@$remotesrv "service sshd restart"

echo "Se ha creado el usuario sftp $inputusuario"

else

echo "*ERROR: El usuario $inputusuario ya existe"
exit 1
fi

Modo de eso:

Script para la creacion de usuarios enjaulados SFTP
OPCIONES:
   -G      Grupo
   -u      Usuario SFTP
   -f      file system
   -s      Name Azure File Share
ejemplo de uso: /usr/bin/createuser.sh -G sftp -u usersftp -f /sftp/usersftp -s fsprueba

:wq!

Una respuesta a “Crear SFTP en Alta disponibilidad en Azure”

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*