A segurança de servidores Linux é uma prioridade crítica para qualquer infraestrutura moderna. Embora o UFW (Uncomplicated Firewall) seja a ferramenta padrão para gerenciar regras de firewall em distribuições baseadas em Debian, sua capacidade nativa de filtrar por geolocalização é limitada. Por padrão, o UFW opera sobre as cadeias do netfilter usando endereços IP individuais ou ranges CIDR, sem consultar bancos de dados geográficos internamente.
Para implementar um hardening avançado que bloqueie tráfego indesejado baseado na origem geográfica (por exemplo, bloquear todo o tráfego proveniente da China, Rússia ou Coreia do Norte se o seu negócio for local), é necessário integrar o UFW com ferramentas externas de resolução de IP. Este tutorial demonstra como construir uma solução robusta, automatizada e eficiente para bloqueio por geolocalização.
1. Fundamentos: Por que combinar UFW e GeoIP?
O firewall linux tradicional trabalha na camada 3 e 4 do modelo OSI. O netfilter, o subsistema de firewall do kernel Linux, é extremamente rápido ao verificar endereços IP estáticos. No entanto, IPs são dinâmicos e podem mudar de dono ou ser usados em botnets globais. A filtragem por geolocalização (GeoIP) adiciona uma camada de inteligência contextual.
A estratégia aqui não é substituir o UFW, mas sim extender suas capacidades. Utilizaremos:
- UFW: Para gerenciar as regras padrão (SSH, HTTP, HTTPS).
- maxmind-db-parser ou geoipupdate: Para baixar e ler o banco de dados de geolocalização.
- Scripts Bash: Para converter os ranges de IP de países bloqueados em regras UFW compatíveis.
Esta abordagem garante que, mesmo com milhares de IPs sendo bloqueados, a administração do firewall permaneça centralizada e documentada.
2. Preparação do Ambiente
Antes de configurar as regras de bloqueio, é essencial garantir que o servidor esteja seguro contra acessos não autorizados durante o processo. Nunca execute este tutorial se você estiver conectado via SSH sem ter acesso de emergência (como console VNC ou KVM), pois um erro de configuração pode travar seu acesso ao servidor.
Instale as dependências necessárias para baixar e processar os dados de geolocalização. Utilizaremos a ferramenta geoipupdate da MaxMind, que é o padrão da indústria para precisão, ou uma alternativa open-source como o DBIP. Neste exemplo, focaremos na estrutura genérica que funciona com qualquer banco de dados GeoIP.
Instale as ferramentas básicas:
sudo apt update
sudo apt install -y ufw geoip-bin curl jq python3-pip
O pacote geoip-bin fornece utilitários básicos, mas para automação avançada, recomendaremos o uso de scripts Python ou Go que convertem bancos de dados .mmdb em listas de IP. Se preferir uma solução sem dependências externas pesadas, você pode utilizar APIs públicas ou feeds RSS atualizados diariamente.
3. Obtenção do Banco de Dados GeoIP
Para bloquear por geolocalização, precisamos de um banco de dados que mapeie ranges de IP (CIDR) a códigos de país (ISO 2-letter codes). A MaxMind oferece o GeoLite2, uma versão gratuita e atualizada frequentemente.
- Crie uma conta gratuita no site da MaxMind.
- Gere uma chave de API para acesso ao download automático.
- Instale o cliente oficial:
sudo apt install geoipupdate
Configure a ferramenta editando o arquivo /etc/GeoIP.conf:
LicenseKey SUA_CHAVE_AQUI
Editions GeoLite2-Country
Rode o comando de atualização para baixar o banco de dados:
sudo geoipupdate
O arquivo resultante será salvo em /usr/share/GeoIP/GeoLite2-Country.mmdb. Este arquivo é a fonte da verdade para nossas regras.
4. Desenvolvimento do Script de Conversão
O UFW não entende o formato .mmdb. Precisamos de um script que leia esse banco de dados, extraia os ranges de IP dos países que desejamos bloquear e gere comandos aptos para o UFW.
Crie um arquivo chamado /usr/local/sbin/geo-firewall-update.sh:
#!/bin/bash
# Script para gerar regras UFW baseadas em GeoIP
# Autor: Toda Solução
# Licença: MIT
set -e
GEO_DB="/usr/share/GeoIP/GeoLite2-Country.mmdb"
UFW_FILE="/etc/ufw/user.rules"
TEMP_RULES="/tmp/geo_ip_rules.txt"
BLOCKED_COUNTRIES="CN RU KP SY IR" # Códigos ISO dos países para bloquear
# Verifica se o banco de dados existe
if [ ! -f "$GEO_DB" ]; then
echo "Erro: Banco de dados GeoIP não encontrado em $GEO_DB"
exit 1
fi
echo "Iniciando atualização das regras de GeoIP..."
# Utilizamos uma ferramenta Python para extrair os CIDRs.
# Se não tiver python, pode usar ferramentas CLI como 'geoiplookup' ou scripts em Go.
# Abaixo, um exemplo conceitual usando uma biblioteca Python comum: maxminddb e ipaddress.
python3 << EOF
import maxminddb
import ipaddress
import subprocess
import sys
db = maxminddb.open_database("$GEO_DB")
countries_to_block = "$BLOCKED_COUNTRIES".split()
cidrs = []
# Iterar sobre todas as entradas no banco de dados
for record in db.iter_all_records():
# Verifica se o país está na lista de bloqueio
if record.country and record.country.iso_code in countries_to_block:
network = ipaddress.ip_network(record.network)
cidrs.append(str(network))
# Remove duplicatas e ordena
unique_cidrs = sorted(list(set(cidrs)))
with open("$TEMP_RULES", "w") as f:
for cidr in unique_cidrs:
# Gera regras de INPUT DROP para cada CIDR
f.write(f"INPUT DROP {cidr}\n")
print(f"Geradas {len(unique_cidrs)} regras de bloqueio.")
EOF
# Verifica se o arquivo gerado não está vazio
if [ ! -s "$TEMP_RULES" ]; then
echo "Nenhuma regra gerada. Abortando."
exit 1
fi
echo "Aplicando regras ao UFW..."
# Inserir as regras no início da lista de INPUT do UFW
# Nota: A manipulação direta de user.rules pode ser sobrescrita pelo 'ufw enable/disable'.
# A melhor prática é usar 'ufw insert' ou adicionar um arquivo customizado.
# Vamos criar uma abordagem mais segura usando o diretório de regras locais do UFW
sudo cp /etc/ufw/before.rules /etc/ufw/before.rules.bak
# Criar novo bloco para inserção no before.rules
cat > /tmp/geo_insert.txt << INSERT_EOF
# GeoIP Firewall Rules - Managed by geo-firewall-update.sh
:ufw-user-input - [0:0]
INSERT_EOF
# Para cada regra gerada, precisamos injetá-la antes das regras de serviço padrão.
# No entanto, a maneira mais limpa no UFW é usar o arquivo /etc/ufw/user.rules
# com cuidado ou usar iptables diretamente se o UFW for muito restritivo para este caso específico.
# Abordagem Híbrida Recomendada:
# Usar 'ufw insert' para adicionar as regras ao topo da cadeia INPUT.
# Isso garante que sejam verificadas antes das regras de serviço (SSH, etc).
while IFS= read -r line; do
# A linha tem formato "INPUT DROP 1.2.3.0/24"
ACTION=$(echo "$line" | awk '{print $2}')
CIDR=$(echo "$line" | awk '{print $3}')
# Insere no topo da lista de regras do usuário (número 1)
sudo ufw insert 1 deny from $CIDR to any
done < "$TEMP_RULES"
# Limpar arquivo temporário
rm -f "$TEMP_RULES"
echo "Regras aplicadas com sucesso."
sudo ufw status verbose
EOF
Este script utiliza Python para ler o banco de dados MaxMind e, em seguida, usa o comando ufw insert para adicionar cada bloqueio no topo da pilha de regras do UFW. O uso de insert 1 é crucial para garantir que o bloqueio ocorra antes que o serviço SSH seja verificado.
5. Permissões e Execução
O script precisa de permissão de execução e acesso ao banco de dados GeoIP. Ajuste as permissões:
sudo chmod +x /usr/local/sbin/geo-firewall-update.sh
sudo chown root:root /usr/local/sbin/geo-firewall-update.sh
Teste a execução do script manualmente para verificar se não há erros de sintaxe ou permissão:
sudo /usr/local/sbin/geo-firewall-update.sh
Verifique o status do firewall para confirmar que as regras de bloqueio aparecem na lista:
sudo ufw status numbered
Você deverá ver uma longa lista de regras DENY (in) no topo, seguidas pelas suas regras padrão de SSH e HTTP.
6. Automatização com Cron
Os ranges de IP mudam frequentemente. Um bloqueio estático torna-se ineficaz em semanas. Para manter a segurança atualizada, agende a execução do script via Cron.
Edite o crontab do root:
sudo crontab -e
Adicione a seguinte linha para rodar a atualização diariamente às 3:00 da manhã:
0 3 * * * /usr/local/sbin/geo-firewall-update.sh >> /var/log/geo-firewall.log 2>&1
Além disso, atualize o banco de dados GeoIP em si. Se você estiver usando geoipupdate, pode agendar a atualização do arquivo .mmdb separadamente:
0 2 * * * /usr/bin/geoipupdate >> /var/log/geoip-update.log 2>&1
Isso garante que, às 2:00 o banco de dados seja atualizado e, uma hora depois, as regras do firewall sejam recalculadas com base nos novos ranges.
7. Considerações sobre Performance e Limites
O netfilter é otimizado para lidar com milhares de regras, mas adicionar dezenas de milhares de entradas individuais no UFW pode impactar a latência de inicialização do firewall e o consumo de memória.
Opcional: Otimização com IPSET
Se você notar degradação de desempenho ou se o número de IPs bloqueados exceder 50.000, considere migrar para IPSET. O UFW suporta ipsets nativamente.
- Crie um ipset:
sudo ipset create geo_block hash:net
Adicione os CIDRs ao ipset em vez de regras individuais do UFW:
sudo ipset add geo_block 1.0.0.0/8
Crie uma regra única no UFW que bloqueie todo o conjunto:
sudo ufw insert 1 deny from set:geo_block to any
Esta abordagem reduz de milhares de regras para apenas uma, mantendo a eficiência do kernel Linux. O script Python precisaria ser ajustado para adicionar IPs ao ipset em vez de chamar ufw insert.
Evitando Bloqueio Acidental (Whitelist)
Um risco comum no bloqueio por geolocalização é bloquear provedores de CDN legítimos ou serviços de monitoramento que possuem IPs em países estrangeiros. É vital manter uma whitelist.
Configure sempre as regras de whitelist antes das regras de bloqueio. No UFW, isso significa garantir que suas regras de "Allow" tenham prioridade ou estejam posicionadas acima das regras de "Drop" no contexto específico.
# Exemplo: Permitir acesso ao SSH antes do bloqueio global
sudo ufw insert 1 allow 22/tcp
No entanto, como o script insere as regras no topo (número 1), você deve garantir que a whitelist seja inserida antes ou usar uma lógica de script que verifique se o IP está na whitelist antes de gerar a regra de bloqueio.
8. Monitoramento e Logs
Para auditar quais IPs estão sendo bloqueados, monitore os logs do sistema. O UFW encaminha seus logs para o /var/log/ufw.log.
sudo tail -f /var/log/ufw.log | grep "UFW BLOCK"
Você pode criar um script adicional que parseia esses logs e gera relatórios semanais de tentativas de invasão por país, ajudando a ajustar quais países devem estar na lista de bloqueio.
9. Conclusão
A implementação de bloqueio IP por geolocalização é uma camada poderosa de defesa em profundidade para o seu segurança servidor. Ao combinar a simplicidade do UFW com a inteligência dos dados GeoIP, você cria um ambiente que filtra tráfego malicioso conhecido antes mesmo que ele tente estabelecer conexões.
Lembre-se:
- Sempre teste scripts de firewall em um ambiente de staging.
- Mantenha backups das configurações do UFW (
/etc/ufw). - Ajuste a lista de países bloqueados conforme as necessidades do seu negócio e ameaças atuais.
- Priorize a performance usando IPSET se o volume de regras for alto.
Com esta configuração, seu servidor Linux estará significativamente mais resistente a varreduras automáticas, ataques de força bruta originados de regiões específicas e atividades suspeitas de botnets globais.