Pesquisa de site

Como configurar um firewall Iptables para proteger o tráfego entre seus servidores


Introdução

A implantação de componentes discretos na configuração do aplicativo em nós diferentes é uma maneira comum de diminuir a carga e começar a dimensionar horizontalmente. Um exemplo típico é configurar um banco de dados em um servidor separado de seu aplicativo. Embora haja uma série de vantagens com essa configuração, a conexão em uma rede envolve um novo conjunto de preocupações de segurança.

Neste guia, demonstraremos como configurar um firewall em cada um de 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 Cloud Firewalls da DigitalOcean, que são executados como uma camada externa adicional para seus servidores na infraestrutura da DigitalOcean. Dessa forma, você não precisa configurar um firewall nos próprios servidores.

Para a demonstração neste guia, usaremos dois servidores Ubuntu 22.04. Um terá um aplicativo da Web servido com Nginx e o outro hospedará o banco de dados MySQL para o aplicativo. Embora estejamos usando essa configuração como exemplo, você deve ser capaz de extrapolar as técnicas envolvidas para atender aos seus próprios requisitos de servidor.

Pré-requisitos

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

A configuração do aplicativo que iremos proteger é baseada neste guia. Se você quiser seguir esse exemplo, configure seu aplicativo e servidores de banco de dados conforme indicado por esse tutorial. Caso contrário, você pode usar este artigo como uma referência geral.

Passo 1 — Configurando um Firewall

Você começará implementando uma configuração básica de firewall para cada um de seus servidores. A política que iremos implementar tem uma abordagem de segurança em primeiro lugar. Estaremos bloqueando quase tudo, exceto o tráfego SSH, e abrindo brechas no firewall para nosso aplicativo específico.

Este guia segue a sintaxe iptables. iptables é instalado automaticamente no Ubuntu 22.04 usando um back-end nftables, então você não deve ter que instalar nenhum pacote adicional.

Usando 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:

*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]

# Acceptable UDP traffic

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT

# Acceptable ICMP traffic

# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-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

# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-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

# Commit the changes
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

Salve e feche o arquivo. Se você estiver usando nano, pressione Ctrl+X para sair e, quando solicitado, Y e depois Enter.

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

Etapa 2 — Descubra as portas usadas pelos seus serviços

Para permitir a comunicação entre seus componentes, você precisa conhecer as portas de rede que estão sendo usadas. Você pode encontrar as portas de rede corretas examinando seus arquivos de configuração, mas um método independente de aplicativo para encontrar as portas corretas é apenas 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 seu aplicativo está se comunicando apenas por IPv4, adicionaremos o argumento -4, mas você pode removê-lo se estiver usando IPv6 também. 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 forma:

  • p: Mostra o PID e o nome do programa ao qual cada soquete pertence.
  • l: Mostra apenas soquetes de escuta.
  • u: Mostra o tráfego UDP.
  • n: mostra saída numérica em vez de nomes de serviço.
  • t: mostra o tráfego TCP.

  1. sudo netstat -4plunt

Em seu servidor web, sua saída pode ser semelhante a esta:

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á escutando. O endereço especial 0.0.0.0 significa que o serviço em questão está escutando em todos os endereços disponíveis.

Em seu servidor de banco de dados, sua saída pode ser semelhante a esta:

  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 forma. Neste exemplo, o endereço 192.0.2.30 representa o endereço IP privado do servidor de banco de dados. No tutorial de pré-requisito, você restringiu o MySQL à interface privada por motivos de segurança.

Anote os valores encontrados nesta etapa. Estes são os detalhes de rede que você precisará para ajustar sua configuração de firewall.

Em seu servidor web, você precisa garantir que as seguintes portas estejam acessíveis:

  • Porta 80 em todos os endereços
  • Porta 22 em todos os endereços (já contabilizada nas regras de 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 ela)
  • Porta 22 em todos os endereços (já contabilizada nas regras de firewall)

Etapa 3 — Ajuste as regras de firewall do servidor Web

Agora que você tem as informações de porta necessárias, você ajustará o conjunto de regras de firewall do seu servidor web. Abra o arquivo de regras em seu editor com privilégios 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á escutando em todos os endereços disponíveis — os servidores da 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. Sua estrutura já possui uma cadeia personalizada chamada TCP para exceções de aplicativo TCP. Você pode adicionar a porta 80 a essa cadeia, logo abaixo da exceção para sua porta SSH:

*filter
. . .

# Acceptable TCP traffic
-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 é restrito em seu firewall e o tráfego de entrada associado a conexões estabelecidas é permitido, portanto não precisamos abrir nenhuma porta adicional neste servidor para permitir esta 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 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

Etapa 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. Nesse caso, esse endereço era 192.0.2.30. Você pode limitar o acesso destinado a esse endereço especificamente ou pode limitar o acesso comparando com a interface atribuída a 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 sudo em seu servidor de banco de dados:

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

Novamente, você adicionará uma regra à nossa cadeia TCP para formar uma exceção para a conexão entre os servidores da Web e do banco de dados.

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

*filter
. . .

# Acceptable TCP traffic
-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:

*filter
. . .

# Acceptable TCP traffic
-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 se há erros de sintaxe com este comando:

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

Quando estiver pronto, recarregue as regras de firewall:

  1. sudo service iptables-persistent reload

Ambos os servidores agora devem estar protegidos sem restringir o fluxo de dados necessário entre eles.

Conclusão

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

Para aprender mais sobre firewalls e iptables especificamente, dê uma olhada nos seguintes guias:

  • Como escolher uma política de firewall eficaz para proteger seus servidores
  • Um mergulho profundo na arquitetura Iptables e Netfilter
  • Como testar sua configuração de firewall com Nmap e Tcpdump