Bloqueo de Países con GeoIP en AlmaLinux 9 usando xtables-addons

En el mundo de la seguridad de servidores y la administración de redes, una de las estrategias más efectivas para reducir ataques y tráfico no deseado es el bloqueo geográfico de IPs. En este artículo te mostraré cómo implementar un sistema de bloqueo basado en GeoIP utilizando xtables-addons en AlmaLinux 9, incluyendo la solución a los problemas de compilación más comunes.

¿Qué es xtables-addons?

Xtables-addons es un conjunto de extensiones para iptables/netfilter que añade funcionalidades adicionales no incluidas en el kernel estándar de Linux. Una de sus características más potentes es el módulo GeoIP, que permite crear reglas de firewall basadas en la ubicación geográfica de las direcciones IP.

Ventajas del bloqueo con GeoIP

  • Simplicidad: Una sola regla puede bloquear millones de IPs
  • Eficiencia: Consume menos recursos que grandes listas de ipset
  • Mantenimiento: Las bases de datos se actualizan fácilmente
  • Flexibilidad: Permite bloquear o permitir países específicos

Requisitos previos

Antes de comenzar, asegúrate de tener:

  • AlmaLinux 9 instalado y actualizado
  • Acceso root o sudo
  • Conexión a Internet para descargar paquetes
  • iptables instalado (no firewalld)

Paso 1: Preparación del sistema

Primero, instalamos todas las dependencias necesarias:

# Actualizar el sistema
dnf update -y

# Instalar EPEL repository
dnf install epel-release -y

# Instalar dependencias de compilación
dnf install kernel-devel kernel-headers gcc make automake autoconf libtool -y

# Instalar herramientas adicionales
dnf install iptables iptables-services wget unzip perl-Text-CSV_XS -y

# Deshabilitar firewalld si está activo
systemctl stop firewalld
systemctl disable firewalld

# Habilitar iptables
systemctl enable iptables
systemctl start iptables

Paso 2: Descargar xtables-addons

Descargamos la última versión estable de xtables-addons:

# Crear directorio de trabajo
cd /usr/src

# Descargar xtables-addons
wget https://inai.de/files/xtables-addons/xtables-addons-3.24.tar.xz

# Extraer el archivo
tar xf xtables-addons-3.24.tar.xz
cd xtables-addons-3.24

Paso 3: Aplicar el parche para AlmaLinux 9

AlmaLinux 9 utiliza un kernel 5.14+, que tiene cambios en la API que causan errores de compilación. Necesitamos aplicar un parche:

# Crear el archivo de parche
cat > fix-kernel-5.14.patch << 'EOF'
--- a/extensions/compat_xtables.h
+++ b/extensions/compat_xtables.h
@@ -27,7 +27,11 @@
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)
-#	define pde_data(inode) PDE_DATA(inode)
+#	if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
+#		define pde_data(inode) ((inode)->i_private)
+#	else
+#		define pde_data(inode) PDE_DATA(inode)
+#	endif
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)
EOF

# Aplicar el parche
patch -p1 < fix-kernel-5.14.patch

¿Por qué es necesario este parche?

El kernel 5.14 cambió la forma en que se accede a los datos privados de las entradas /proc. La función PDE_DATA() fue reemplazada por acceso directo a inode->i_private. Este parche detecta la versión del kernel y usa el método apropiado.

Paso 4: Compilar e instalar xtables-addons

Ahora procedemos con la compilación:

# Configurar el paquete
./configure

# Compilar
make

# Instalar
make install

# Cargar el módulo del kernel
modprobe xt_geoip

# Verificar que el módulo se cargó correctamente
lsmod | grep xt_geoip

Si ves una salida similar a xt_geoip 16384 0, el módulo se cargó correctamente.

Paso 5: Descargar la base de datos GeoIP

Ahora necesitamos descargar y preparar la base de datos de ubicaciones geográficas:

# Crear directorio para la base de datos
mkdir -p /usr/share/xt_geoip

# Navegar al directorio de scripts GeoIP
cd /usr/src/xtables-addons-3.24/geoip

# Descargar la base de datos (esto puede tardar unos minutos)
./xt_geoip_dl

# Construir la base de datos binaria
./xt_geoip_build -D /usr/share/xt_geoip *.csv

# Verificar que se crearon los archivos
ls /usr/share/xt_geoip/ | wc -l

Deberías ver un número mayor a 200, representando los diferentes países y territorios.

Paso 6: Crear reglas de firewall con GeoIP

Ahora viene la parte interesante: crear reglas basadas en países.

Bloquear un país específico

# Bloquear todo el tráfico desde China
iptables -I INPUT -m geoip --src-cc CN -j DROP

# Bloquear tráfico saliente hacia Rusia
iptables -I OUTPUT -m geoip --dst-cc RU -j DROP

Bloquear múltiples países

# Bloquear varios países simultáneamente
iptables -I INPUT -m geoip --src-cc CN,RU,KP,IR -j DROP

Crear una lista blanca (whitelist)

# Permitir solo tráfico desde España, Italia y Francia
iptables -I INPUT -m geoip ! --src-cc ES,IT,FR -j DROP

Logging antes de bloquear

Es útil registrar los intentos de conexión antes de bloquearlos:

# Registrar y luego bloquear
iptables -I INPUT -m geoip --src-cc CN -j LOG --log-prefix "GeoBlock-CN: "
iptables -I INPUT -m geoip --src-cc CN -j DROP

Paso 7: Guardar la configuración

Para que las reglas persistan después de un reinicio:

# Guardar las reglas de iptables
service iptables save

# Asegurar que iptables inicie con el sistema
systemctl enable iptables

Paso 8: Script de gestión automatizada

Para facilitar la gestión, creamos un script de administración:

cat > /usr/local/bin/geoip-manager.sh << 'SCRIPT'
#!/bin/bash

# Script de gestión de GeoIP para iptables
# Autor: Tu nombre
# Fecha: $(date +%Y-%m-%d)

ACTION=$1
COUNTRIES=$2
LOG_FILE="/var/log/geoip-manager.log"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}

usage() {
    cat << EOF
Uso: $0 {block|unblock|list|status|update} [COUNTRY_CODES]

Comandos:
  block CODES     Bloquear países (ej: CN,RU,KP)
  unblock CODES   Desbloquear países
  list            Mostrar reglas GeoIP activas
  status          Mostrar estadísticas de bloqueo
  update          Actualizar base de datos GeoIP

Ejemplos:
  $0 block CN,RU       # Bloquea China y Rusia
  $0 unblock CN        # Desbloquea China
  $0 list              # Lista reglas activas
  $0 update            # Actualiza base de datos

Códigos de países comunes:
  CN=China, RU=Rusia, US=Estados Unidos, BR=Brasil
  KP=Corea del Norte, IR=Irán, IN=India, VN=Vietnam
EOF
    exit 1
}

block_countries() {
    log "Bloqueando países: $1"
    
    # Bloquear tráfico entrante
    iptables -I INPUT -m geoip --src-cc $1 -j LOG --log-prefix "GeoBlock-$1: " --log-level 4
    iptables -I INPUT -m geoip --src-cc $1 -j DROP
    
    # Opcional: bloquear tráfico saliente
    # iptables -I OUTPUT -m geoip --dst-cc $1 -j DROP
    
    service iptables save
    log "Países bloqueados correctamente: $1"
}

unblock_countries() {
    log "Desbloqueando países: $1"
    
    # Eliminar reglas de bloqueo
    iptables -D INPUT -m geoip --src-cc $1 -j LOG --log-prefix "GeoBlock-$1: " --log-level 4 2>/dev/null
    iptables -D INPUT -m geoip --src-cc $1 -j DROP 2>/dev/null
    iptables -D OUTPUT -m geoip --dst-cc $1 -j DROP 2>/dev/null
    
    service iptables save
    log "Países desbloqueados: $1"
}

list_rules() {
    echo "=== Reglas GeoIP INPUT ==="
    iptables -L INPUT -n -v --line-numbers | grep geoip
    echo ""
    echo "=== Reglas GeoIP OUTPUT ==="
    iptables -L OUTPUT -n -v --line-numbers | grep geoip
}

show_status() {
    echo "=== Estado del sistema GeoIP ==="
    echo ""
    echo "Módulo del kernel:"
    lsmod | grep xt_geoip || echo "  ¡ADVERTENCIA! Módulo no cargado"
    echo ""
    echo "Base de datos GeoIP:"
    DB_COUNT=$(ls /usr/share/xt_geoip/ 2>/dev/null | wc -l)
    echo "  Países en base de datos: $DB_COUNT"
    echo ""
    echo "Reglas activas:"
    RULES_COUNT=$(iptables -L INPUT -n | grep -c geoip)
    echo "  Total de reglas GeoIP: $RULES_COUNT"
    echo ""
    echo "Estadísticas de bloqueo (INPUT):"
    iptables -L INPUT -n -v | grep geoip | awk '{print "  Paquetes bloqueados: " $1 ", Bytes: " $2}'
}

update_geoip() {
    log "Iniciando actualización de base de datos GeoIP"
    
    # Backup de la base actual
    if [ -d "/usr/share/xt_geoip" ]; then
        BACKUP_DIR="/usr/share/xt_geoip.backup.$(date +%Y%m%d_%H%M%S)"
        cp -r /usr/share/xt_geoip $BACKUP_DIR
        log "Backup creado en: $BACKUP_DIR"
    fi
    
    # Descargar nueva base de datos
    cd /usr/src/xtables-addons-3.24/geoip
    ./xt_geoip_dl
    
    if [ $? -eq 0 ]; then
        # Construir base de datos
        ./xt_geoip_build -D /usr/share/xt_geoip *.csv
        
        if [ $? -eq 0 ]; then
            log "Base de datos GeoIP actualizada correctamente"
            
            # Limpiar backups antiguos (más de 30 días)
            find /usr/share -name "xt_geoip.backup.*" -mtime +30 -exec rm -rf {} \; 2>/dev/null
        else
            log "ERROR: Fallo al construir la base de datos"
            # Restaurar backup
            rm -rf /usr/share/xt_geoip
            mv $BACKUP_DIR /usr/share/xt_geoip
            exit 1
        fi
    else
        log "ERROR: Fallo al descargar la base de datos"
        exit 1
    fi
}

# Verificar que se ejecuta como root
if [ "$EUID" -ne 0 ]; then
    echo "ERROR: Este script debe ejecutarse como root"
    exit 1
fi

# Procesar comando
case "$ACTION" in
    block)
        if [ -z "$COUNTRIES" ]; then
            echo "ERROR: Debes especificar los códigos de países"
            usage
        fi
        block_countries $COUNTRIES
        ;;
    unblock)
        if [ -z "$COUNTRIES" ]; then
            echo "ERROR: Debes especificar los códigos de países"
            usage
        fi
        unblock_countries $COUNTRIES
        ;;
    list)
        list_rules
        ;;
    status)
        show_status
        ;;
    update)
        update_geoip
        ;;
    *)
        usage
        ;;
esac
SCRIPT

# Hacer el script ejecutable
chmod +x /usr/local/bin/geoip-manager.sh

Paso 9: Uso del script de gestión

El script que acabamos de crear simplifica enormemente la gestión:

# Bloquear China y Rusia
geoip-manager.sh block CN,RU

# Ver estadísticas
geoip-manager.sh status

# Listar reglas activas
geoip-manager.sh list

# Desbloquear un país
geoip-manager.sh unblock CN

# Actualizar base de datos GeoIP
geoip-manager.sh update

Paso 10: Automatizar actualizaciones de la base de datos

Las bases de datos GeoIP deben actualizarse periódicamente:

# Crear script de actualización automática
cat > /etc/cron.monthly/update-geoip << 'EOF'
#!/bin/bash
/usr/local/bin/geoip-manager.sh update >> /var/log/geoip-update.log 2>&1
EOF

# Hacer ejecutable
chmod +x /etc/cron.monthly/update-geoip

También puedes usar crontab para actualizaciones más frecuentes:

# Editar crontab
crontab -e

# Agregar línea para actualizar el primer día de cada mes a las 3 AM
0 3 1 * * /usr/local/bin/geoip-manager.sh update >> /var/log/geoip-update.log 2>&1

Paso 11: Cargar módulo automáticamente al inicio

Para asegurar que el módulo GeoIP se cargue en cada reinicio:

# Agregar módulo a la carga automática
echo "xt_geoip" >> /etc/modules-load.d/xtables-addons.conf

# Verificar
cat /etc/modules-load.d/xtables-addons.conf

Códigos de países más utilizados

Aquí tienes una lista de códigos ISO que puedes usar:

Código País Código País
CN China US Estados Unidos
RU Rusia BR Brasil
KP Corea del Norte IN India
IR Irán VN Vietnam
TR Turquía ID Indonesia
UA Ucrania PK Pakistán
DE Alemania JP Japón
FR Francia KR Corea del Sur
ES España IT Italia
GB Reino Unido MX México

Casos de uso prácticos

Proteger servidor VoIP

Si tienes un servidor VoIP (Kamailio, Asterisk, FreeSWITCH), puedes bloquear países de donde no esperas llamadas:

# Permitir solo España, Italia y países europeos
geoip-manager.sh block CN,RU,KP,IR,VN,IN,BR,TR

Proteger servidor web

Para un sitio web que solo atiende clientes locales:

# Permitir solo España y países vecinos
iptables -A INPUT -p tcp --dport 80 -m geoip ! --src-cc ES,FR,PT,IT -j DROP
iptables -A INPUT -p tcp --dport 443 -m geoip ! --src-cc ES,FR,PT,IT -j DROP
service iptables save

Proteger SSH

Bloquear acceso SSH desde países específicos:

# Bloquear SSH desde China y Rusia
iptables -I INPUT -p tcp --dport 22 -m geoip --src-cc CN,RU -j DROP
service iptables save

Monitorización y logs

Ver intentos de conexión bloqueados

# Ver logs en tiempo real
tail -f /var/log/messages | grep GeoBlock

# Ver estadísticas de bloqueos
grep "GeoBlock" /var/log/messages | wc -l

Analizar países bloqueados

# Crear script de análisis
cat > /usr/local/bin/geoip-stats.sh << 'EOF'
#!/bin/bash
echo "=== Estadísticas de bloqueo GeoIP ==="
echo ""
echo "Top 10 países bloqueados hoy:"
grep "GeoBlock" /var/log/messages | \
    grep "$(date '+%b %e')" | \
    awk -F'GeoBlock-' '{print $2}' | \
    awk -F':' '{print $1}' | \
    sort | uniq -c | sort -rn | head -10
EOF

chmod +x /usr/local/bin/geoip-stats.sh

Troubleshooting (Resolución de problemas)

El módulo no carga

# Verificar si el módulo existe
find /lib/modules -name "xt_geoip.ko"

# Recargar módulo
modprobe -r xt_geoip
modprobe xt_geoip

# Ver errores del kernel
dmesg | grep -i geoip

Las reglas no funcionan

# Verificar que la base de datos existe
ls -lh /usr/share/xt_geoip/

# Verificar reglas de iptables
iptables -L INPUT -n -v | grep geoip

# Probar manualmente
iptables -I INPUT -m geoip --src-cc CN -j LOG --log-prefix "TEST-GeoIP: "
# Intenta conectar desde una IP china y revisa los logs
tail -f /var/log/messages

Error de compilación persiste

Si el parche no funciona, compila sin el módulo problemático:

cd /usr/src/xtables-addons-3.24
make clean
./configure --without-pknock
make
make install

Consideraciones de seguridad

  1. No dependas solo de GeoIP: Los atacantes pueden usar VPNs o proxies
  2. Combina con otras medidas: Usa fail2ban, rate limiting, etc.
  3. Actualiza regularmente: Las asignaciones de IPs cambian
  4. Cuidado con bloqueos excesivos: Podrías bloquear tráfico legítimo
  5. Mantén logs: Monitorea lo que estás bloqueando

Rendimiento

GeoIP es muy eficiente:

  • Impacto mínimo: Las búsquedas son en memoria
  • Escalable: Puede manejar millones de conexiones
  • Mejor que ipset grandes: Para bloqueos masivos por país

Actualización del sistema

Cuando actualices el kernel de AlmaLinux:

# Después de actualizar el kernel, recompila xtables-addons
cd /usr/src/xtables-addons-3.24
make clean
./configure
make
make install

# Recargar módulo
modprobe -r xt_geoip
modprobe xt_geoip

Desinstalación (si es necesario)

Si necesitas eliminar xtables-addons:

# Eliminar reglas de iptables
iptables -F

# Descargar módulo
modprobe -r xt_geoip

# Desinstalar
cd /usr/src/xtables-addons-3.24
make uninstall

# Limpiar archivos
rm -rf /usr/share/xt_geoip
rm -f /etc/modules-load.d/xtables-addons.conf

Conclusión

El bloqueo geográfico con xtables-addons y GeoIP es una herramienta poderosa para administradores de sistemas en AlmaLinux 9. Aunque requiere compilación y configuración inicial, los beneficios en seguridad y reducción de tráfico no deseado son significativos.

Este método es especialmente útil para:

  • Servidores VoIP que reciben ataques de países específicos
  • Servicios web con audiencia local
  • Protección de servicios administrativos (SSH, panels)
  • Reducción de spam y escaneos automatizados

Recuerda mantener actualizada la base de datos GeoIP y combinar esta técnica con otras medidas de seguridad para una protección integral.

Referencias y recursos adicionales


Nota del autor: Este tutorial ha sido probado en AlmaLinux 9.x con kernel 5.14+. Si encuentras algún problema o tienes sugerencias, no dudes en dejar un comentario. Se agradece el apoyo de Claude Sonnet 4.5

Vota el Articulo: 

Sin votos (todavía)
Evalúa la calidad del articulo
Suscribirse a Comentarios de "Bloqueo de Países con GeoIP en AlmaLinux 9 usando xtables-addons" Suscribirse a VozToVoice - Todos los comentarios