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

Introdução

A implantação de componentes discretos na configuração da sua aplicação em diferentes nós é uma forma 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 existam várias vantagens nessa configuração, conectar-se por meio de uma rede envolve um novo conjunto de preocupações com segurança.

Neste guia, vamos demonstrar 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 outros tráfegos.

Você também pode configurar os Firewalls da 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 deles terá uma aplicação web servida com o Nginx e o outro hospedará o banco de dados MySQL para a aplicação. Embora estejamos utilizando essa configuração como exemplo, você deve ser capaz de extrapolar as técnicas envolvidas para atender aos requisitos do seu próprio servidor.

Pré-requisitos

Para começar, você precisará ter dois servidores Ubuntu 22.04 novos. Adicione uma conta de usuário regular com privilégios de 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 no tutorial. Caso contrário, você pode usar este artigo como referência geral.

Passo 1 — Configurando um Firewall

Você começará implementando uma configuração básica do firewall para cada um de seus servidores. A política que estaremos implementando segue uma abordagem de segurança em primeiro lugar. Vamos restringir quase tudo, exceto o tráfego SSH, e em seguida, abriremos brechas 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, então 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 tráfego de saída, mas bloquear pacotes de entrada e 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

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

# Encaminhar tráfego para cadeias específicas de protocolo
## Permitir apenas novas conexões (estabelecidas e relacionadas já devem ser tratadas)
## Para TCP, permitir apenas novos pacotes SYN, pois essa é a única maneira válida
## de 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 chegado a este ponto
## Tente ser específico ao protocolo com a 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, pressione Y e depois Enter.

Se estiver implementando isso em um ambiente de produção, não recarregue suas regras de firewall ainda. Carregar o conjunto de regras descrito aqui imediatamente cortará 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 os seus componentes, é necessário conhecer as portas de rede que estão sendo utilizadas. 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 por IPv4, adicionaremos o argumento -4, mas você pode removê-lo se estiver usando também IPv6. Os outros argumentos que você precisa 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 divididos da seguinte maneira:

  • 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

No seu servidor web, sua saída pode ser assim:

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. 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.

No seu servidor de banco de dados, sua saída pode ser assim:

  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 exatamente 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 pré-requisito, você restringiu o MySQL à interface privada por motivos de segurança.

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

No seu servidor web, você precisa garantir que as seguintes portas sejam 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 deverá 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 de porta de 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 usarão 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

. . .

O seu servidor web irá iniciar a conexão com o servidor de banco de dados. O tráfego de saída não é restrito no 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 esta conexão.

Salve e feche o arquivo quando terminar. Agora, o seu servidor web possui uma política de firewall que permitirá todo o tráfego legítimo enquanto bloqueia todo o resto.

Teste o seu arquivo de regras para 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 de 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 combinando com a interface que possui 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 de 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

Novamente, você irá 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 hospeda esse endereço, você 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 sempre deve 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, dê uma olhada nos seguintes guias:

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