Como Configurar um Firewall Iptables para Proteger o Tráfego Entre seus Servidores

Introdução

Implantar componentes discretos na configuração da sua aplicação em diferentes nós é uma maneira comum de diminuir a carga e começar a escalar horizontalmente. Um exemplo típico é configurar um banco de dados em um servidor separado da sua aplicação. Embora haja várias vantagens com essa configuração, a conexão por meio de uma rede envolve um novo conjunto de preocupações com segurança.

Neste guia, demonstraremos como configurar um firewall em cada um dos seus servidores em uma configuração distribuída. Vamos configurar nossa política para permitir o tráfego pretendido entre nossos componentes, enquanto negamos outro tráfego.

Você também pode configurar os Firewalls na Nuvem da DigitalOcean, que funcionam como uma camada adicional e externa aos seus servidores na infraestrutura da DigitalOcean. Desta forma, você não precisa configurar um firewall nos seus servidores em si.

Para a demonstração neste guia, estaremos utilizando dois servidores Ubuntu 22.04. Um terá uma aplicação web servida com o Nginx e o outro hospedará o banco de dados MySQL para a aplicação. Embora estejamos usando essa configuração como exemplo, você deverá ser capaz de extrapolar as técnicas envolvidas para atender aos requisitos do seu próprio servidor.

Pré-requisitos

Para começar, você precisará de dois servidores Ubuntu 22.04 recém-criados. Adicione uma conta de usuário comum com privilégios sudo em cada um. Para fazer isso, siga nosso guia de configuração inicial do servidor Ubuntu 22.04.

A configuração da aplicação que estaremos protegendo é baseada neste guia. Se desejar seguir esse exemplo, configure seus servidores de aplicação e banco de dados conforme indicado nesse tutorial. Caso contrário, você pode usar este artigo como referência geral.

Etapa 1 — Configurando um Firewall

Começaremos implementando uma configuração básica do firewall para cada um dos seus servidores. A política que implementaremos segue uma abordagem de segurança em primeiro lugar. Vamos restringir quase tudo, exceto o tráfego SSH, e em seguida, abriremos buracos no firewall para nossa aplicação específica.

Este guia segue a sintaxe do iptables. O iptables é instalado automaticamente no Ubuntu 22.04 usando um backend nftables, portanto, você não precisará instalar pacotes adicionais.

Usando o nano ou seu editor de texto favorito, abra o arquivo /etc/iptables/rules.v4:

  1. sudo nano /etc/iptables/rules.v4

Cole a configuração do guia de modelo de firewall:

/etc/iptables/rules.v4
*filter
# Permitir todo o tráfego de saída, mas bloquear pacotes de entrada e de encaminhamento por padrão
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Cadeias personalizadas por protocolo
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]

# Tráfego UDP aceitável

# Tráfego TCP aceitável
-A TCP -p tcp --dport 22 -j ACCEPT

# Tráfego ICMP aceitável

# Política de aceitação padrão
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Descartar pacotes inválidos
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Encaminhar tráfego para cadeias específicas do protocolo
## Permitir apenas novas conexões (estabelecidas e relacionadas devem ser tratadas previamente)
## Para TCP, adicionalmente, permitir apenas novos pacotes SYN, pois esse é o único método válido
## para estabelecer uma nova conexão TCP
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

# Rejeitar qualquer coisa que tenha passado até este ponto
## Tentar ser específico de protocolo com mensagem de rejeição
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable

# Confirmar as alterações
COMMIT

*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

Salvar e fechar o arquivo. Se estiver usando nano, pressione Ctrl+X para sair, depois, quando solicitado, Y e então Enter.

Se estiver implementando isso em um ambiente real, não recarregue suas regras de firewall ainda. Carregar o conjunto de regras delineado aqui imediatamente interromperá a conexão entre sua aplicação e o servidor de banco de dados. Você precisará ajustar as regras para refletir nossas necessidades operacionais antes de recarregar.

Passo 2 — Descubra as Portas Usadas por Seus Serviços

Para permitir a comunicação entre seus componentes, é necessário conhecer as portas de rede em uso. Você pode encontrar as portas corretas examinando seus arquivos de configuração, mas um método independente de aplicação para encontrar as portas corretas é verificar quais serviços estão ouvindo conexões em cada uma de nossas máquinas.

Você pode usar a ferramenta netstat para descobrir isso. Como sua aplicação está se comunicando apenas via IPv4, adicionaremos o argumento -4, mas você pode removê-lo se estiver usando IPv6 também. Os outros argumentos necessários para encontrar seus serviços em execução são -p, -l, -u, -n e -t, que você pode fornecer como -plunt.

Esses argumentos podem ser decompostos da seguinte forma:

  • p: Show the PID and name of the program to which each socket belongs.
  • l: Show only listening sockets.
  • u: Show UDP traffic.
  • n: Show numeric output instead of service names.
  • t: Show TCP traffic.
  1. sudo netstat -4plunt

Em seu servidor web, a saída pode se parecer com o seguinte:

Output
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1058/sshd tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx

A primeira coluna destacada mostra o endereço IP e a porta em que o serviço destacado no final da linha está ouvindo conexões. O endereço especial 0.0.0.0 significa que o serviço em questão está ouvindo em todos os endereços disponíveis.

Em seu servidor de banco de dados, a saída pode se parecer com o seguinte:

  1. sudo netstat -4plunt
Output
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1097/sshd tcp 0 0 192.0.2.30:3306 0.0.0.0:* LISTEN 3112/mysqld

Você pode ler essas colunas da mesma maneira. Neste exemplo, o endereço 192.0.2.30 representa o endereço IP privado do servidor de banco de dados. No tutorial anterior, você restringiu o MySQL à interface privada por razões de segurança.

Observe os valores que você encontra nesta etapa. Esses são os detalhes de rede que você precisará ajustar na configuração do seu firewall.

Em seu servidor web, certifique-se de que as seguintes portas estejam acessíveis:

  • Porta 80 em todos os endereços
  • Porta 22 em todos os endereços (já considerada nas regras do firewall)

Seu servidor de banco de dados teria que garantir que as seguintes portas estejam acessíveis:

  • Porta 3306 no endereço 192.0.2.30 (ou a interface associada a ele)
  • Porta 22 em todos os endereços (já considerada nas regras do firewall)

Passo 3 — Ajustar as Regras do Firewall do Servidor Web

Agora que você tem as informações da porta que precisa, ajustará o conjunto de regras do firewall do seu servidor web. Abra o arquivo de regras no seu editor com privilégios de sudo:

  1. sudo nano /etc/iptables/rules.v4

No servidor web, você precisa adicionar a porta 80 à sua lista de tráfego aceitável. Como o servidor está ouvindo em todos os endereços disponíveis — servidores web geralmente esperam ser acessíveis de qualquer lugar — você não restringirá a regra por interface ou endereço de destino.

Seus visitantes da web estarão usando o protocolo TCP para se conectar. Seu framework já possui uma cadeia personalizada chamada TCP para exceções de aplicativos TCP. Você pode adicionar a porta 80 a essa cadeia, logo abaixo da exceção para sua porta SSH:

/etc/iptables/rules.v4
*filter
. . .

# Tráfego TCP aceitável
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 80 -j ACCEPT

. . .

Seu servidor web iniciará a conexão com seu servidor de banco de dados. Seu tráfego de saída não está restrito em seu firewall e o tráfego de entrada associado a conexões estabelecidas é permitido, então não precisamos abrir nenhuma porta adicional neste servidor para permitir essa conexão.

Salve e feche o arquivo quando terminar. Seu servidor web agora tem uma política de firewall que permitirá todo o tráfego legítimo enquanto bloqueia todo o resto.

Teste seu arquivo de regras em busca de erros de sintaxe:

  1. sudo iptables-restore -t < /etc/iptables/rules.v4

Se nenhum erro de sintaxe for exibido, recarregue o firewall para implementar o novo conjunto de regras:

  1. sudo service iptables-persistent reload

Passo 4 — Ajuste as Regras do Firewall do Servidor de Banco de Dados

No seu servidor de banco de dados, você precisa permitir o acesso à porta 3306 no endereço IP privado do seu servidor. Neste caso, esse endereço era 192.0.2.30. Você pode limitar o acesso destinado a este endereço especificamente, ou pode limitar o acesso correspondendo à interface que tem esse endereço.

Para encontrar a interface de rede associada a esse endereço, execute ip -4 addr show scope global:

  1. ip -4 addr show scope global
Output
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 203.0.113.5/24 brd 104.236.113.255 scope global eth0 valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 192.0.2.30/24 brd 192.0.2.255 scope global eth1 valid_lft forever preferred_lft forever

As áreas destacadas mostram que a interface eth1 está associada a esse endereço.

Em seguida, você ajustará as regras do firewall no servidor de banco de dados. Abra o arquivo de regras com privilégios de sudo no seu servidor de banco de dados:

  1. sudo nano /etc/iptables/rules.v4

Mais uma vez, você adicionará uma regra à nossa cadeia TCP para formar uma exceção para a conexão entre seus servidores web e de banco de dados.

Para restringir o acesso com base no endereço real em questão, você adicionaria a regra assim:

/etc/iptables/rules.v4
*filter
. . .

# Tráfego TCP Aceitável
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -d 192.0.2.30 -j ACCEPT

. . .

Se preferir permitir a exceção com base na interface que abriga esse endereço, pode adicionar uma regra semelhante a esta:

/etc/iptables/rules.v4
*filter
. . .

# Tráfego TCP Aceitável
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -i eth1 -j ACCEPT

. . .

Salve e feche o arquivo quando terminar.

Verifique erros de sintaxe com este comando:

  1. sudo iptables-restore -t < /etc/iptables/rules.v4

Quando estiver pronto, recarregue as regras do firewall:

  1. sudo service iptables-persistent reload

Agora, ambos os seus servidores devem estar protegidos sem restringir o fluxo necessário de dados entre eles.

Conclusão

Implementar um firewall adequado deve sempre fazer parte do seu plano de implantação ao configurar uma aplicação. Embora tenhamos demonstrado essa configuração usando dois servidores executando Nginx e MySQL, as técnicas demonstradas acima são aplicáveis, independentemente das suas escolhas tecnológicas específicas.

Para saber mais sobre firewalls e iptables especificamente, confira os seguintes guias:

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-an-iptables-firewall-to-protect-traffic-between-your-servers