Bloqueo de ssh por pais

Cada vez es mas comun que los servidores sean suceptibles a ataques via ssh, generalmente se usan herramientas como fail2ban la cual permite el bloquear IPs por tiempo determinado, pero aun asi se siguen recibiendo ataques. Pero si queremos detener por completo los ataques es mejor aplicar un filtro por geolocalización.

En este caso vamos a usar la base de datos de GeoIP para bloquear los acceso que no sean provenientes los paises en la lista permitida.

Instalación de GeoIP

Para esto vamos a instalar el paquete de GeoIP y su base de datos.

sudo apt-get install geoip-bin geoip-database 

Creación de Script

Creamos el script /usr/local/bin/ipfilter.sh con nuestro editor favorito y agregamos el siguiente codigo

#!/bin/bash
# License: WTFPL

# UPPERCASE space-separated country codes to ACCEPT
ALLOW_COUNTRIES="MX"
LOGDENY_FACILITY="authpriv.notice"

if [ $# -ne 1 ]; then
  echo "Usage:  `basename $0` " 1>&2
  exit 0 # return true in case of config issue
fi

if [[ "`echo $1 | grep ':'`" != "" ]] ; then
  COUNTRY=`/usr/bin/geoiplookup6 "$1" | awk -F ": " '{ print $2 }' | awk -F "," '{ print $1 }' | head -n 1`
else
  COUNTRY=`/usr/bin/geoiplookup "$1" | awk -F ": " '{ print $2 }' | awk -F "," '{ print $1 }' | head -n 1`
fi
[[ $COUNTRY = "IP Address not found" || $ALLOW_COUNTRIES =~ $COUNTRY ]] && RESPONSE="ALLOW" || RESPONSE="DENY"

if [[ "$RESPONSE" == "ALLOW" ]] ; then
  logger -p $LOGDENY_FACILITY "$RESPONSE sshd connection from $1 ($COUNTRY)"
  exit 0
else
  logger -p $LOGDENY_FACILITY "$RESPONSE sshd connection from $1 ($COUNTRY)"
  exit 1
fi

Script de hecho por jokey2k

Para definir que paises son permitidos para el acceso ssh, basta con cambiar la variable ALLOW_COUNTRIES, para mas información checar el comentario del script.

Damos permisos de ejecución al script

chmod +x /usr/local/bin/ipfilter.sh 

Restringir conexiones

Editamos el archivo /etc/hosts.deny y agregamos la restricción

sshd: ALL
vsftpd: ALL

Ahora agregamos la regla de permitir acceso al archivo /etc/hosts.allow

sshd: ALL: aclexec /usr/local/bin/ipfilter.sh %a
vsftp: ALL: aclexec /usr/local/bin/ipfilter.sh %a

Prueba

Ahora toca probar que se haya aplicado correctamente las restricciones, para eso podemos checar el log de autentificacion con un tail -f al archivo de log y debemos ver algo como:

Sep 15 14:19:05 own root: DENY sshd connection from 139.155.40.215 (CN)
Sep 15 14:19:12 own sshd[45414]: Received disconnect from 139.155.40.215 port 47786:11: Bye Bye [preauth]
Sep 15 14:19:12 own sshd[45414]: Disconnected from authenticating user root 139.155.40.215 port 47786 [preauth]
Sep 15 14:19:52 own root: DENY sshd connection from 183.107.195.8 (KR)
Sep 15 14:19:52 own sshd[45427]: Unable to negotiate with 183.107.195.8 port 40753: no matching host key type found. Their offer: ssh-rsa,ssh-dss [preauth]
Sep 15 14:19:58 own root: DENY sshd connection from 198.235.24.59 (CA)
Sep 15 14:20:05 own root: DENY sshd connection from 139.155.40.215 (CN)
Sep 15 14:20:09 own sshd[45440]: Connection reset by 198.235.24.59 port 42739 [preauth]
Sep 15 14:20:10 own sshd[45453]: Received disconnect from 139.155.40.215 port 52726:11: Bye Bye [preauth]
Sep 15 14:20:10 own sshd[45453]: Disconnected from authenticating user root 139.155.40.215 port 52726 [preauth]
Sep 15 14:21:04 own root: DENY sshd connection from 139.155.40.215 (CN)
Sep 15 14:21:09 own sshd[45469]: Received disconnect from 139.155.40.215 port 57662:11: Bye Bye [preauth]
Sep 15 14:21:09 own sshd[45469]: Disconnected from authenticating user root 139.155.40.215 port 57662 [preauth]

Donde se puede observar como la politica niega la conexión a las ip y el país de donde son.