Como bloquear IPs de países em meu firewall com iptables e nftables no Linux

Quando temos um servidor exposto à Internet, uma recomendação fundamental é configurar seu firewall para permitir apenas o tráfego que desejamos permitir e negar o restante do tráfego. Em muitas ocasiões, somos vítimas de ataques de força bruta ou ataques de negação de serviço de outros países que não a Espanha. Na grande maioria das ocasiões, é aconselhável permitir apenas os endereços IP do país onde você está, ou sua empresa, e negar por padrão qualquer outro tráfego que não tenhamos na lista permitida. Hoje neste artigo vamos te ensinar a baixar todas as faixas de IP de um determinado país para bloqueá-lo quando quisermos, ou permitir uma delas, sempre usando IPv4 já que seu uso é majoritário, se você for usar IPv6 você terá que adaptar o script.

Políticas em um firewall: permissivas ou restritivas

Os firewalls têm principalmente duas políticas, uma política permissiva permitirá todo o tráfego, exceto o que negamos especificamente. Em uma política restritiva, permitiremos apenas o tráfego que definimos especificamente. Por segurança, é sempre aconselhável ter uma política restritiva na Internet WAN, para evitar que uma regra mal configurada possa causar um tráfego que não queremos que entre em nossa rede, além disso, é mais eficiente ter (poucas) regras para permitir determinado tráfego e negar o resto em massa do que o contrário.

Bloquear IPs de países em Meu Firewall com iptables e nftables no Linux

Uma política muito boa em um firewall seria permitir apenas um ou mais países e negar o restante dos países por padrão. Portanto, o script que apresentaremos a seguir pode ser facilmente modificado para permitir apenas endereços IP ou sub-redes baixados e, posteriormente, bloquear o restante dos endereços IP por política.

Onde obtenho os endereços IP e intervalos dos diferentes países?

In Negar IP podes encontrar todos os blocos de endereços IPv4 que pertencem a cada país, desta forma, podemos obter todos os intervalos de endereços IP em formato CIDR de todos os países do mundo, teremos a possibilidade de ver os intervalos de IP de Espanha, China, Rússia e muitos outros. Quanto maior o país, mais faixas de endereços IPv4 teremos, portanto, teremos que permitir ou negar o acesso a essas redes para posteriormente bani-las ou permiti-las. Dentro este outro link temos disponíveis os blocos de endereços IPv6 de cada país.

Um detalhe muito importante é que o IPDeny atualiza todo o banco de dados de endereços IP com muita frequência, tanto IPv4 quanto IPv6, para nos impedir de bloquear endereços IP ou intervalos de um país que na verdade está em outro. Esta página da web é atualizada quase diariamente, conforme os blocos de endereços IPv4 e IPv6 mudam ou mais são adicionados.

Configuração de iptables com ipset para bloquear países

iptables é o Linux firewall por excelência, embora existam algumas distribuições que estão dando o salto para nftables, que é a evolução do iptables, muito mais rápido, mais eficiente e mais fácil de configurar, no entanto, atualmente ainda usamos a sintaxe iptables embora para abaixo estejamos usando nftables , como nas últimas versões do sistema operacional Debian e muitos outros. Se você usa iptables, é altamente recomendável que você use a extensão ipset, que nos permitirá bloquear ou permitir milhões de endereços IP, mas com desempenho superior do que se o fizermos diretamente com IPtables. No caso de permitir ou bloquear um país inteiro, é altamente recomendável fazê-lo através do ipset porque é claramente mais eficiente do que o iptables.

Para usar o ipset com iptables, você precisa instalá-lo porque ele não é instalado por padrão, você pode instalá-lo desta forma:

sudo apt install ipset

Depois de instalado, podemos começar a usá-lo.

O seguinte script que programamos consiste em bloquear um ou vários países, adicionar todas as suas sub-redes baixadas do IPdeny e incorporar todas as sub-redes a um ipset para depois chamar esse ipset e bloqueá-lo no iptables. Desta forma, o iptables será muito mais eficiente do que se você o fizer sem a extensão ipset.

#!/bin/bash
# El objetivo de este script es BLOQUEAR todo el tráfico del pais que nosotros definamos, aunque tambien podriamos permitir solamente el nuestro, y denegar el resto.
# Autor: this article.net; puedes compartir y modificar este script como desees.
# -------------------------------------------------------------------------------
#Elegiremos el nombre PAIS del pais que queremos BLOQUEAR
#Como ejemplo pondremos Andorra ya que tiene pocos rangos de direcciones IP.
PAIS="ad"
### Variables para facilitar el uso del script que apuntan a iptables (cortafuegos), ipset (extension de IPTABLESables), wget para coger los archivos de la base de datos y egrep para seleccionar la IP sin ningún símbolo que iptables no pueda interpretar ###
IPTABLES=/sbin/iptables
IPSET=/sbin/ipset
WGET=/usr/bin/wget
EGREP=/bin/egrep
#Ubicacion donde se guarda la base de datos de
BBDD="/root/iptables-bdd"
#URL de la base de datos de paises
URLDESCARGA="http://www.ipdeny.com/ipblocks/data/countries"
#Funcion para limpiar todas las reglas del firewall y lo ponemos por defecto.
limpiarReglasAntiguas(){
$IPTABLES -F
$IPTABLES -X
$IPTABLES -t nat -F
$IPTABLES -t nat -X
$IPTABLES -t mangle -F
$IPTABLES -t mangle -X
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
$IPSET flush paisbloqueado
$IPSET destroy paisbloqueado
}
#Creamos el directorio para almacenar la base de datos
[ ! -d $BBDD ] && /bin/mkdir -p $BBDD
#Ejecutamos la funcion
limpiarReglasAntiguas
for c in $PAIS
do
# Base de datos local
DBLOCAL=$BBDD/$c.zone
# Descargamos y actualizamos la base de datos
$WGET -O $DBLOCAL $URLDESCARGA/$c.zone
# Filtramos la base de datos para que IPTABLES interprete correctamente la base de datos y vamos anadiendo cada bloque de IP.
FILTROIPS=$(egrep -v "^#|^$" $DBLOCAL)
#Creamos el IPset nuevo para bloquear el pais
$IPSET create paisbloqueado hash:net
for ipbloqueo in $FILTROIPS
do
$IPSET add paisbloqueado $ipbloqueo
done
done
#Denegamos el tráfico del ipset creado.
$IPTABLES -I INPUT -m set --match-set paisbloqueado src -j DROP
#Permitimos todo el resto del trafico. CUIDADO CON ESTO
$IPTABLES -A INPUT -j ACCEPT
exit 0

Agora podemos ver o status do iptables colocando o seguinte, e veremos que ele faz uso do ipset configurado:

iptables -L

Para ver o status do ipset, colocamos o seguinte:

ipset list

Sempre que quisermos bloquear um novo país, você terá que executar o script novamente e automaticamente todo o conteúdo do ipset será excluído e todas as novas sub-redes serão adicionadas do zero. Este é o mais recomendado porque os diferentes bancos de dados de endereços IP e intervalos de diferentes países estão sendo continuamente atualizados. Devemos observar que países como a China têm um grande número de blocos de endereços IP, então vai demorar vários minutos para aplicar todas as regras ao firewall, se tentarmos apenas com “ad” é quase instantâneo porque temos muito poucos.

Graças a este script, se o nosso serviço de Internet só funcionar na Espanha, podemos banir todos os outros países, mas devemos ter em mente que se um usuário da Espanha usa um proxy ou VPN de outro país, não permitiremos o acesso.

Configuração de iptables com ipset para permitir a Espanha e bloquear o resto

Neste script faremos exatamente o contrário do anterior, o que faremos é baixar a base de dados de endereços IP da Espanha, adicionaremos ao novo ipset criado e permitiremos o acesso. Por padrão, o que ele fará é negar todos os outros tráfegos de outros países. Se o seu negócio é na Espanha e você só quer que eles se conectem na Espanha, esta é a melhor e mais eficiente coisa que você pode fazer porque você só permitirá um país e não bloqueará especificamente o resto do mundo.

#!/bin/bash
# El objetivo de este script es PERMITIR todo el tráfico del pais que nosotros definamos.
# Autor: this article.net; puedes compartir y modificar este script como desees.
# -------------------------------------------------------------------------------
#Elegiremos el nombre PAIS del pais que queremos PERMITIR
#Como ejemplo pondremos Andorra ya que tiene pocos rangos de direcciones IP.
PAIS="ad"
### Variables para facilitar el uso del script que apuntan a iptables (cortafuegos), ipset (extension de IPTABLESables), wget para coger los archivos de la base de datos y egrep para seleccionar la IP sin ningún símbolo que iptables no pueda interpretar ###
IPTABLES=/sbin/iptables
IPSET=/sbin/ipset
WGET=/usr/bin/wget
EGREP=/bin/egrep
#Ubicacion donde se guarda la base de datos de
BBDD="/root/iptables-bdd"
#URL de la base de datos de paises
URLDESCARGA="http://www.ipdeny.com/ipblocks/data/countries"
#Funcion para limpiar todas las reglas del firewall y lo ponemos por defecto.
limpiarReglasAntiguas(){
$IPTABLES -F
$IPTABLES -X
$IPTABLES -t nat -F
$IPTABLES -t nat -X
$IPTABLES -t mangle -F
$IPTABLES -t mangle -X
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
$IPSET flush paispermitido
$IPSET destroy paispermitido
}
#Creamos el directorio para almacenar la base de datos
[ ! -d $BBDD ] && /bin/mkdir -p $BBDD
#Ejecutamos la funcion
limpiarReglasAntiguas
for c in $PAIS
do
# Base de datos local
DBLOCAL=$BBDD/$c.zone
# Descargamos y actualizamos la base de datos
$WGET -O $DBLOCAL $URLDESCARGA/$c.zone
# Filtramos la base de datos para que IPTABLES interprete correctamente la base de datos y vamos anadiendo cada bloque de IP.
FILTROIPS=$(egrep -v "^#|^$" $DBLOCAL)
#Creamos el IPset nuevo para bloquear el pais
$IPSET create paispermitido hash:net
for ippermitir in $FILTROIPS
do
$IPSET add paispermitido $ippermitir
done
done
#Permitimos el tráfico del ipset creado.
$IPTABLES -I INPUT -m set --match-set paispermitido src -j ACCEPT
#DENEGAMOS todo el resto del trafico.
$IPTABLES -A INPUT -j DROP
exit 0

Agora podemos ver o status do iptables colocando o seguinte, e veremos que ele faz uso do ipset configurado:

iptables -L

Para ver o status do ipset, colocamos o seguinte:

ipset list

Como você viu, é muito fácil bloquear ou permitir que um país faça uso do ipset do iptables, além disso, é muito mais eficiente do que fazê-lo diretamente com o iptables, por isso recomendamos que você sempre use o ipset para este tipo de ações .

Configuração de Nftables para bloquear países

nftables é o novo firewall do Linux, melhor, mais rápido e mais intuitivo do que os populares iptables que sempre usamos. nftables já está instalado na maioria das distribuições Linux, mesmo se usarmos a sintaxe iptables. Se você usa as versões mais recentes do Debian, já estará usando o nftables sem saber, mas não poderemos usar a sintaxe do nftables em si.

Para podermos usar o nftables 100%, teremos que instalá-lo diretamente dos repositórios, executando o seguinte comando:

sudo apt install nftables

Uma vez instalado, podemos começar a configurar nftables com o comando “nft”. A sintaxe é radicalmente diferente do iptables, então se você não o usou, vai demorar um pouco para se ajustar à nova sintaxe.

O seguinte script que programamos consiste em bloquear um país ou vários, adicionar todas as suas sub-redes baixadas de IPdeny e incorporar todas as sub-redes a nftables para bloqueá-lo no firewall. Devemos lembrar que o nftables é muito mais eficiente do que o iptables e funcionará muito bem.

#!/bin/bash
# El objetivo de este script es BLOQUEAR todo el tráfico del pais que nosotros definamos, aunque tambien podriamos permitir solamente el nuestro, y denegar el resto.
# Autor: this article.net; puedes compartir y modificar este script como desees.
# -------------------------------------------------------------------------------
#Elegiremos el nombre PAIS del pais que queremos BLOQUEAR
#Como ejemplo pondremos Andorra ya que tiene pocos rangos de direcciones IP.
PAIS="ad"
### Variables para facilitar el uso del script que apuntan a nftables (cortafuegos), wget para coger los archivos de la base de datos y egrep para seleccionar la IP sin ningún símbolo que NFT no pueda interpretar ###
NFT=/sbin/nft
WGET=/usr/bin/wget
EGREP=/bin/egrep
#Ubicacion donde se guarda la base de datos de
BBDD="/root/NFT-bdd"
#URL de la base de datos de paises
URLDESCARGA="http://www.ipdeny.com/ipblocks/data/countries"
#Funcion para limpiar todas las reglas del firewall y lo ponemos por defecto.
limpiarReglasAntiguas(){
$NFT flush set filter ips_baneadas
$NFT flush chain ip filter INPUT
}
#Creamos el directorio para almacenar la base de datos
[ ! -d $BBDD ] && /bin/mkdir -p $BBDD
#Ejecutamos la funcion
limpiarReglasAntiguas
for c in $PAIS
do
# Base de datos local
DBLOCAL=$BBDD/$c.zone
# Descargamos y actualizamos la base de datos
$WGET -O $DBLOCAL $URLDESCARGA/$c.zone
# Filtramos la base de datos para que NFT interprete correctamente la base de datos y vamos anadiendo cada bloque de IP.
FILTROIPS=$(egrep -v "^#|^$" $DBLOCAL)
#Creamos el set de ips_baneadas de tipo IPv4.
$NFT add set ip filter ips_baneadas {type ipv4_addr; flags interval;}
#Metemos en el set todos los rangos de IP.
for ipbloqueo in $FILTROIPS
do
$NFT add element ip filter ips_baneadas { $ipbloqueo }
done
done
#Bloqueamos todo lo que coincida con el SET anteriormente creado.
$NFT add rule ip filter INPUT ip saddr @ips_baneadas counter drop
$NFT list ruleset > /etc/nftables.conf
systemctl restart nftables.service
exit 0

Agora podemos ver o estado de nftables colocando o seguinte, e veremos que ele faz uso do ipset configurado:

nft list ruleset

Configurando nftables para permitir países

O próximo script que programamos consiste em permitir um país, adicionar todas as suas sub-redes baixadas do IPdeny e incorporar todas as sub-redes ao nftables para permitir no firewall, o resto do tráfego será negado. Devemos lembrar que o nftables é muito mais eficiente do que o iptables e funcionará muito bem.

#!/bin/bash
# El objetivo de este script es PERMITIR todo el tráfico del pais que nosotros definamos, aunque tambien podriamos permitir solamente el nuestro, y denegar el resto.
# Autor: this article.net; puedes compartir y modificar este script como desees.
# -------------------------------------------------------------------------------
#Elegiremos el nombre PAIS del pais que queremos PERMITIR
#Como ejemplo pondremos Andorra ya que tiene pocos rangos de direcciones IP.
PAIS="ad"
### Variables para facilitar el uso del script que apuntan a nftables (cortafuegos), wget para coger los archivos de la base de datos y egrep para seleccionar la IP sin ningún símbolo que NFT no pueda interpretar ###
NFT=/sbin/nft
WGET=/usr/bin/wget
EGREP=/bin/egrep
#Ubicacion donde se guarda la base de datos de
BBDD="/root/NFT-bdd"
#URL de la base de datos de paises
URLDESCARGA="http://www.ipdeny.com/ipblocks/data/countries"
#Funcion para limpiar todas las reglas del firewall y lo ponemos por defecto.
limpiarReglasAntiguas(){
$NFT flush set filter ips_permitidas
$NFT flush chain ip filter INPUT
}
#Creamos el directorio para almacenar la base de datos
[ ! -d $BBDD ] && /bin/mkdir -p $BBDD
#Ejecutamos la funcion
limpiarReglasAntiguas
for c in $PAIS
do
# Base de datos local
DBLOCAL=$BBDD/$c.zone
# Descargamos y actualizamos la base de datos
$WGET -O $DBLOCAL $URLDESCARGA/$c.zone
# Filtramos la base de datos para que NFT interprete correctamente la base de datos y vamos anadiendo cada bloque de IP.
FILTROIPS=$(egrep -v "^#|^$" $DBLOCAL)
#Creamos el set de ips_permitidas de tipo IPv4.
$NFT add set ip filter ips_permitidas {type ipv4_addr; flags interval;}
#Metemos en el set todos los rangos de IP.
for ippermitida in $FILTROIPS
do
$NFT add element ip filter ips_permitidas { $ippermitida }
done
done
#Permitimos todo lo que coincida con el SET anteriormente creado.
$NFT add rule ip filter INPUT ip saddr @ips_permitidas counter accept
#Bloqueamos todo lo demas en cadena base
$NFT add chain ip filter INPUT '{ policy drop; }'
#Guardamos y reiniciamos servicio
$NFT list ruleset > /etc/nftables.conf
systemctl restart nftables.service
exit 0

Agora podemos ver o estado de nftables colocando o seguinte, e veremos que ele faz uso do ipset configurado:

nft list ruleset

Até agora viemos com este tutorial sobre iptables e ipset para bloquear ou permitir IPs de diferentes países, também vimos como fazer isso com nftables, o novo firewall Linux com uma nova sintaxe muito mais intuitiva, mas que vai custar nos acostumamos com algum trabalho se sempre trabalhamos com iptables.