Script to block countries in iptables – Bloquear países

Actualizado el domingo, 24 mayo, 2020

Script to block countries in Iptables – Bloquear países.

Todos los propietarios de Servidores o VPS, padecemos de la gran lacra  de los sitios web… evidentemente hablamos de los intentos de intrusión, dDOS, ataques constantes, rastreo de puertos, spammers, etc… etc…

La gran mayoría de este tipo de situaciones que nos pueden generar auténticos dolores de cabeza, provienen de los mismos países, China, Rusia, India, etc…

Entonces yo me pregunto… realmente es necesario admitir a un país como China?, la respuesta es no, no es necesario, pues no te reportara ningún beneficio (salvo casos muy puntuales), solo problemas.

Soy consciente que mi afirmación puede ser discutida, incluso criticada, pero vamos a ver… seamos sinceros, acaso piensas que un chino está interesado en tu tienda de zapatos, tu periódico en castellano, tus servicios en la red, etc…, pues no, no les interesas para nada, su único interés es hacerse con tu servicio, por ejemplo tu SMTP para enviar su mier** de spam que lo único que hará sera perjudicar la reputación de tu IP o dominio.

No te lo pienses más y no dudes, si tienes este problema bloquea el país al completo.

Script to block countries - Bloquear países

Script to block countries – Bloquear países

 

Hace ya un tiempo publicamos un script «bash«, que descargaba el listado de IP’s de un país y las aplicaba en Iptables.

Lamentablemente aquel script ya está obsoleto… y por ello te presento la nueva versión del script bash «block-countries.sh», que viene con muchas mejoras.

Principales novedades:

  • Programación mejorada
  • Definir puertos permitidos (por defecto 80 y 443)
  • Reducción del proceso de las reglas
  • Solo busca la coincidencia en el primer octeto del rango IP
  • Se permite al acceso desde un puerto a definir del país bloqueado
  • Carga el listado de país con iptables-restore
  • etc…

En la antigua versión cargar y aplicar el listado de IP’s, de un país como China, podía tomar más de una hora. En esta nueva versión, menos de 30 segundos y todo gracias a el uso de «iptables-restore», para que me entiendas mejor… restaura tablas IP a partir de datos especificados en STDIN.

AVISO: Este script es para Centos, si utilizas Debian o Ubuntu debes realizar unas modificaciones. Instrucciones al final del artículo.

Sin más preámbulos vemos el script.

 

Script block countries en Iptables

Desde consola / terminal y como root creamos el archivo «block-countries.sh» (países predeterminados, Rusia y China).

nano block-countries.sh

Copia y pega el script.
#!/bin/bash
#Use ISO code countries ###
### Block all traffic from RUSIA (ru) and CHINA (cn)
ISO="ru cn"  ### codigo de país a bloquear
 
### Set PATH ###
IPT=/sbin/iptables
WGET=/usr/bin/wget
EGREP=/bin/egrep
 
### No editing below ###
CBLIST="countrydrop"
ZONEROOT="/var/iptables"
IPTCBRESTORE="/etc/sysconfig/iptables.cb"
IPTCBDEVICE=eth0
ALLOWPORTS=80,443
ALLOWSUBNET=192.168.0.0/255.255.0.0
MAXZONEAGE=7
DLROOT="http://www.ipdeny.com/ipblocks/data/countries"
 
cleanOldRules(){
    $IPT -L $CBLIST > /dev/null 2>&1
    if [ $? = 0 ] ; then
	$IPT -D INPUT ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST
	$IPT -D OUTPUT ${IPTCBDEVICE:+-o }${IPTCBDEVICE} -j $CBLIST
	$IPT -D FORWARD ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST
    fi
    $IPT -F $CBLIST
    $IPT -X $CBLIST

    for i  in `$IPT -L -n | grep Chain | cut -f 2 -d ' ' | grep '\-$CBLIST'`
    do
	$IPT -F ${i}
	$IPT -X ${i}
    done
}

updateZoneFiles() {
    ZONEARCH=${ZONEROOT}/arch
    mkdir -p ${ZONEARCH}
    find ${ZONEROOT} -maxdepth 1 -mindepth 1 -ctime +${MAXZONEAGE} -exec mv {} ${ZONEARCH} \;

    for c  in $ISO
    do
	# local zone file
	tDB=$ZONEROOT/$c.zone
	
	if [ -f $tDB ] ; then
	    printf "Zone file %s is new enough - no update required.\n" $tDB
	else
	    # get fresh zone file if it is newer than MAXZONEAGE days
	    $WGET -O $tDB $DLROOT/$c.zone
	fi
    done
    oldzones=`find ${ZONEROOT} -mindepth 1 -maxdepth 1 -type f -exec basename {} \; | cut -f 1 -d '.'`
    # Archive old zones no longer blocked
    for z in $oldzones ; do
	archme=${c}
	for c  in $ISO ; do
	    if [ $c = $z ] ; then archme="X"; fi
	done
	if [ $archme = $z ] ; then
	    mv ${archme} ${ZONEARCH}
	else
	    printf "Working from previous zone file for %s\n" ${z}
	fi
    done
}
 
createIPTLoadFile() {
    printf "# Generated by %s on" $0 > ${IPTCBRESTORE}
    printf "%s " `date` >> ${IPTCBRESTORE}
    printf "\n*filter\n" >> ${IPTCBRESTORE}
    # Create CBLIST chain
    printf ":$CBLIST - [0:0]\n" >> ${IPTCBRESTORE}
    printf "%s INPUT ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST\n" "-I" > ${IPTCBRESTORE}.tmp
    printf "%s OUTPUT ${IPTCBDEVICE:+-o }${IPTCBDEVICE} -j $CBLIST\n" "-I"  >> ${IPTCBRESTORE}.tmp
    printf "%s FORWARD ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST\n" "-I" >> ${IPTCBRESTORE}.tmp

    if [ "Z${ALLOWPORTS}" = "Z" ] ; then
	printf "Blocking all traffic from country - no ports allowed\n"
    else
	printf "%s $CBLIST -p tcp -m multiport --dports ${ALLOWPORTS} -j RETURN\n" "-I">> ${IPTCBRESTORE}.tmp
    fi

    if [ "Z${ALLOWSUBNET}" = "Z" ] ; then
	printf "Blocking all traffic from country - no subnets excluded\n"
    else
	printf "%s $CBLIST -s ${ALLOWSUBNET} -j RETURN\n" "-I">> ${IPTCBRESTORE}.tmp
    fi

    for c  in $ISO
    do
	# local zone file
	tDB=$ZONEROOT/$c.zone
	
	# country specific log message
	SPAMDROPMSG="iptables: ${c}-Country-Drop: "
	
        # Create drop chain for identified packets
	CBLISTDROP=${c}-${CBLIST}-DROP
	printf ":${CBLISTDROP} - [0:0]\n" >> ${IPTCBRESTORE}
	printf "%s ${CBLISTDROP} -j LOG --log-prefix \"$SPAMDROPMSG\"\n" "-A" >> ${IPTCBRESTORE}.tmp
	printf "%s ${CBLISTDROP} -j DROP\n" "-A" >> ${IPTCBRESTORE}.tmp
    
	# Load IP ranges into chains correlating to first octet
	BADIPS=$(egrep -v "^#|^$" $tDB)
	for ipblock in $BADIPS
	do
	    topip=`echo $ipblock | cut -f 1 -d '.'`
	    chainExists=`grep -c :${topip}-${CBLIST} ${IPTCBRESTORE}`
	    if [ $chainExists = 0 ] ; then
		printf "Creating chain for octet %s\n" ${topip}
		printf ":$topip-$CBLIST - [0:0]\n" >> ${IPTCBRESTORE}
		sip=${topip}.0.0.0/8
		printf "%s $CBLIST -s ${sip} -j $topip-$CBLIST\n" "-A" >> ${IPTCBRESTORE}.tmp
	    fi
	    printf "  Adding rule for %s to chain for octet %s\n" ${ipblock} ${topip}
	    printf "%s $topip-$CBLIST -s $ipblock -j ${CBLISTDROP}\n" "-A" >> ${IPTCBRESTORE}.tmp
	done
    done
    cat ${IPTCBRESTORE}.tmp >> ${IPTCBRESTORE} && rm -f ${IPTCBRESTORE}.tmp
    printf "COMMIT\n# Completed on " >> ${IPTCBRESTORE}
    printf "%s " `date` >> ${IPTCBRESTORE}
    printf "\n" >> ${IPTCBRESTORE}
}

directLoadTables() {
    # Create CBLIST chain
    $IPT -N $CBLIST
    $IPT -I INPUT ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST
    $IPT -I OUTPUT ${IPTCBDEVICE:+-o }${IPTCBDEVICE} -j $CBLIST
    $IPT -I FORWARD ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST

    if [ "Z${ALLOWPORTS}" = "Z" ] ; then
	printf "Blocking all traffic from country - no ports allowed\n"
    else
	$IPT -I $CBLIST -p tcp -m multiport --dports ${ALLOWPORTS} -j RETURN
    fi

    if [ "Z${ALLOWSUBNET}" = "Z" ] ; then
	printf "Blocking all traffic from country - no subnets allowed\n"
    else
	$IPT -I $CBLIST -s ${ALLOWSUBNET} -j RETURN
    fi

    for c  in $ISO
    do
	# local zone file
	tDB=$ZONEROOT/$c.zone
	
	# country specific log message
	SPAMDROPMSG="$c Country Drop"
	
        # Create drop chain for identified packets
	CBLISTDROP=${c}-${CBLIST}-DROP
	$IPT -N ${CBLISTDROP}
	$IPT -A ${CBLISTDROP} -j LOG --log-prefix "$SPAMDROPMSG"
	$IPT -A ${CBLISTDROP} -j DROP
    
	# Load IP ranges into chains correlating to first octet
	BADIPS=$(egrep -v "^#|^$" $tDB)
	for ipblock in $BADIPS
	do
	    topip=`echo $ipblock | cut -f 1 -d '.'`
	    $IPT -L $topip-$CBLIST > /dev/null 2>&1
	    if [ $? = 1 ] ; then
		printf "Creating chain for octet %s\n" ${topip}
		$IPT -N $topip-$CBLIST
		sip=${topip}.0.0.0/8
		$IPT -A $CBLIST -s ${sip} -j $topip-$CBLIST
	    fi
	    printf "  Adding rule for %s to chain for octet %s\n" ${ipblock} ${topip}
	    $IPT -A $topip-$CBLIST -s $ipblock -j ${CBLISTDROP}
	done
    done
}

loadTables() {
    createIPTLoadFile
    ${IPT}-restore -n ${IPTCBRESTORE}
    #directLoadTables
    printf "Country block instituted for: %s\n" "$ISO"
}

# create a dir
[ ! -d $ZONEROOT ] && /bin/mkdir -p $ZONEROOT
 
# clean old rules
cleanOldRules
 
# update zone files as needed
updateZoneFiles

# create a new iptables list
loadTables

exit 0

Guarda y cierra el editor.

Script to block countries in iptables - Bloquear países 1

 

Ejecuta el script:

bash block-countries.sh

Como te comente anteriormente, este script es muy rápido.

Ejemplo de salida:

--2018-02-07 06:37:55--  http://www.ipdeny.com/ipblocks/data/countries/cn.zone
Resolviendo www.ipdeny.com (www.ipdeny.com)... 192.241.240.22
Conectando con www.ipdeny.com (www.ipdeny.com)[192.241.240.22]:80... conectado.
Petición HTTP enviada, esperando respuesta... 200 OK
Longitud: 125774 (123K)
Grabando a: “/var/iptables/cn.zone”

100%[======================================>] 125.774      324KB/s   en 0,4s   

2018-02-07 06:37:56 (324 KB/s) - “/var/iptables/cn.zone” guardado [125774/125774]

Working from previous zone file for cn
Creating chain for octet 1
  Adding rule for 1.0.1.0/24 to chain for octet 1
  Adding rule for 1.0.2.0/23 to chain for octet 1
  Adding rule for 1.0.8.0/21 to chain for octet 1
  Adding rule for 1.0.32.0/19 to chain for octet 1
  Adding rule for 1.1.0.0/24 to chain for octet 1
  Adding rule for 1.1.2.0/23 to chain for octet 1
  Adding rule for 1.1.4.0/22 to chain for octet 1
              .............................................
                       ..............................................

Ya lo tenemos instalado y ejecutándose Script to block countries, te recomiendo que crees una tarea cron para que se actualice el listado de ip’s.

Por ejemplo:

@weekly /path/to/block-countries.sh

y lo ejecutamos.
/path/to/block-countries.sh

Si prefieres descargar el script «block countries«directamente, lo encontraras a continuación.

Script to block countries in iptables - Bloquear países 2

 

Uso del Script to block countries en Debian, Ubuntu y derivados

Este Script to block countries fue creado para CentOS. En Ubuntu o Debian se deben utilizar otras rutas que pasamos a detallar.

Primero ejecuta el siguiente comando, para realizar una instalacion completa.

sudo apt install iptables-persistent netfilter-persistent

Te solicitara que aceptes la persistencia en V4 y V6. Responde YES.

Script to block countries

Script to block countries

Al terminar reiniciamos iptables.

sudo service iptables restart

En el script to block countries buscas la siguiente sección.

### No editing below ### 
CBLIST="countrydrop" 
ZONEROOT="/var/iptables" 
IPTCBRESTORE="/etc/sysconfig/iptables.cb" 
IPTCBDEVICE=eth0 
ALLOWPORTS=80,443 
ALLOWSUBNET=192.168.0.0/255.255.0.0 
MAXZONEAGE=7 
DLROOT="http://www.ipdeny.com/ipblocks/data/countries"

y la cambias por…

### No editing below ### 
CBLIST="countrydrop" 
ZONEROOT="/var/iptables" 
IPTCBRESTORE="/etc/iptables/rules.v4" 
IPTCBDEVICE=eth0 
ALLOWPORTS=80,443 
ALLOWSUBNET=192.168.0.0/255.255.0.0 
MAXZONEAGE=7 
DLROOT="http://www.ipdeny.com/ipblocks/data/countries"

Ahora, ya puedes ejecutar el script anterior con las modificaciones para Debian o Ubuntu. El resto de pasos son los mismos. Que disfrutes el script.

 

Recursos

Listas de países y sus ip.

Nota Final

Asegurate que estas utilizando la interfaz…

IPTCBDEVICE=eth0

Si no es así, modificas el nombre.

 

Canales de Telegram: Canal SoloLinux – Canal SoloWordpress

Espero que este articulo te sea de utilidad, puedes ayudarnos a mantener el servidor con una donación (paypal), o también colaborar con el simple gesto de compartir nuestros artículos en tu sitio web, blog, foro o redes sociales. Script to block countries in iptables – Bloquear países.

 

14 Comentarios

  1. manjajo
    11/02/2018
    • sergio
      11/02/2018
  2. Javier
    08/04/2018
    • Javier
      08/04/2018
  3. Julio
    23/05/2018
  4. mariano
    19/11/2019
    • sololinux
      19/11/2019
  5. Javier
    24/05/2020
    • Sergio G.B.
      24/05/2020
  6. Vandark
    18/06/2020
    • vandark
      18/06/2020
      • Sergio G.B.
        19/06/2020
  7. David
    01/11/2020

Agregar comentario