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.
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.
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.
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
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
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.
Interesante Script para bloquear paises. Pero que paises recomiendas bloquear?
La elección de países a bloquear es una elección muy personal, pues depende de los intereses y temática de tu web. Yo no puedo aconsejar nada, lo que puedo hacer es decirte los que yo tengo bloqueados:
Afganistán, China, Taiwan, Tailandia, Seychelles y Vietnam.
«af cn tw th sc vn».
Gracias por el código
Al ejecutarlo en debian indica que no existe el archivo o directorio
/etc/sysconfig/iptables.cb
Adding rule for 223.165.8.0/21 to chain for octet 223
block-countries.sh: line 119: /etc/sysconfig/iptables.cb.tmp: No such file or directory
grep: /etc/sysc
Can’t open /etc/sysconfig/iptables.cb: No such file or directory
para que sistema esta confeccionado
Al final lo he conseguido para una distribucion debian.9
cambiando la ruta en:
IPTCBRESTORE=»/etc/sysconfig/iptables.cb»
por:
IPTCBRESTORE=»/etc/iptables.cb»
Buen aporte.
Si quiero que un determinado país no tenga acceso alguno basta con dejar la variable ALLOWPORTS = «»?
¿Tiene algún tutorial para la correcta modificación si hay necesidad de la sección abajo?
### 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
= 7 MAXZONEAGE
DLROOT = «http://www.ipdeny.com/ipblocks/data/countries»
Acabo de probarlo y a mi al menos no me bloquea china por ejemplo chinafirewalltest.com.
Me dice que todo Ok
Lo he instalado como el manual en ubuntu 18.04 cambiando también la ruta del itpbrestore pero yo creo que el listado no esta del todo actualizado.
Buenos dias Mariano.
Si accedes a ipdeny podrás ver que el listado se actualizo ayer, día 18 (hoy 19). Pero este script no es para que china te bloquee a ti, si no, para que tu bloquees a china.
La url que indicas chinafirewalltest verifica que china no te bloquea a ti, ademas como saben que pueden tener problemas de bloqueo la alojan en un compartido de EEUU, concretamente en iwfhosting.
El script funciona perfectamente, pero está claro que existen ip que cambian constantemente (y más en china).
Un detalle que tal vez no has tenido en cuenta es que las listas de ip son temporales, si reinicias el servidor debes ejecutar el script de nuevo, o hacer las reglas permanentes.
Un saludo.
Hola, he probado el script en ubuntu, he creado el directorio /etc/sysconfig y el archivo iptables.cb con:
sudo mkdir /etc/sysconfig
sudo touch /etc/sysconfig/iptables.cb
Y he corrido el script como sudo
Pero pruebo con Tor a entrar en mi web desde un pais bloqueado y me deja entrar sin problemas.
He comprobado que la ip esta dentro de el listado que crea el script y tambien que iptables esta corriendo…
Algo estoy haciendo mal? o es que no lo estoy probando bien?
Gracias !! buen aporte 😉
El script se desarrolló para CentOS, que es lo que utilizo habitualmente. He añadido las instrucciones para Ubuntu / Debian.
Probado en Ubuntu 18.04 server satisfactoriamente.
Un saludo.
Hola, lo acabo de probar en unbuntu 20 y cuando llega al final del proceso me salta este error.
block-countries.sh: line 181: /sbin/iptables-restore: No such file or directory
¿Me puedes ayudar?
Que por cierto he tenido que entrar en rescue mode para borrar las reglas, no habia otra forma de entraren el servidor.
Es un scrpt creado para centos7, tan solo tienes que modificar las rutas.-
¿yo pensaba que ‘ipdeny.com’ se encargaba de facilitar listas de IPs ‘malas’?
Pero por lo que dices te muestra todas las de cada pais.
Osea que una basura!
ya que mi IP ni siquiera se encuentra en el rango ‘ES’ y cualquier base de datos de geolocalizacion me saca pais, comunidad autonoma y ciudad.
¿no conoceis alguna similar que solo muestre IPs conocidas que tengan malos intereses y se actualice?