+++
date = '2024-10-20T14:22:33-03:00'
title = 'Dominando o iptables: Configurações básicas de firewall para um servidor GNU/Linux recém-implantado'
description = "Um guia passo a passo para configurar regras de firewall iptables em um servidor GNU/Linux recém-implantado, cobrindo SSH, HTTP/HTTPS, IPv6, ICMP e melhores práticas de segurança."
tags = [
    "webserver",
    "GNU/Linux",
    "Basics Series",
]
canonical = "/posts/iptables-basics"
+++

Ao configurar um novo servidor Linux, uma das primeiras coisas que você deve fazer é protegê-lo configurando um firewall. O iptables, uma poderosa ferramenta de firewall disponível na maioria das distribuições Linux, é uma excelente opção para gerenciar regras de tráfego.

Nesta publicação, vou mostrar algumas configurações básicas do iptables para um servidor recém-implantado. No final, você terá um firewall sólido para proteger seus serviços e, ao mesmo tempo, manter as coisas simples.

## O que é iptables?

iptables é um utilitário de firewall por linha de comando que utiliza "chains" para gerenciar o tráfego. As "chains" são basicamente uma lista de regras que aplicam para pacotes de entrada ou saída. Voce pode fazer as regras baseadas em IPs de origem, portas e protocolos, por exemplo.

Tornar um servidor seguro é a primeira prioridade para qualquer sysadmin, e firewalls são uma das camadas mais importantes de defesa. Com iptables voce pode:

- [ ] Bloquear trafego indesejado
- [ ] Permitir conexões confiáveis (como SSH, HTTP/HTTPS)
- [ ] Proteger contra ataques DoS e port scanning
- [ ] Gerar logs de atividades suspeitas para analise futura

## Como funciona o fluxo de pacotes no iptables

Eu recomendo fortemente que voce leia mais sobre o fluxo de pacotes do iptables antes de aplicar qualquer regra.

Recomendo que voce inicie por esses diagramas muito bem feitos nesse gist do [nerdalert no GitHub](https://gist.github.com/nerdalert/a1687ae4da1cc44a437d)

## Comandos básicos do iptables

Vamos começar com uma overview dos comandos essenciais do iptables:

### Mostrar regras atuais

```bash
iptables -L
```

### Deletar regras atuais

```bash
iptables -F
```

### Salvar regras atuais

Se voce está rodando Debian, voce precisa primeiro instalar o pacote `iptables-persistent`, depois disso voce pode usar os seguintes comandos:

```bash
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
```

Restaurar regras:

```bash
iptables-restore < /etc/iptables/rules.v4
ip6tables-restore < /etc/iptables/rules.v6
```

## Configurar iptables em um servidor novo

Agora, vamos passar por algumas regras básicas que voce pode aplicar no seu servidor logo de inicio. Vamos permitir trafego essencial como SSH e HTTP/HTTPs e bloquear todo o resto.

### Passo 1: Limpar regras existentes

Antes de começar a definir regras, é uma boa ideia limpar as regras existentes para começar do zero:

```bash
iptables -F
```

Isso nos garante que estamos iniciando em um estado limpo.

Tome cuidado com os próximos comandos, para voce não se trancar para fora do seu próprio servidor! Isso já aconteceu com todos sysadmins mais cedo ou mais tarde. A forma mais simples de garantir que isso não ocorra é fazendo tudo isso fisicamente, ou através de uma conexão por KVM por exemplo.

### Passo 2: Definir as politicas default

Agora, vamos definir o comportamento padrão para conexões de entrada (INPUT), saída (OUTPUT) e encaminhadas (FORWARD). Por padrão, é uma boa ideia bloquear toda a entrada e permitir toda a saída.

```bash
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
```

Isso faz com que todas as conexões sejam dropadas a menos que uma regra as permita. O trafego de saída por sua vez, é liberado por padrão.

### Passo 3: Permitir trafego SSH (Porta 22)

Voce vai precisar de SSH para acessar o seu servidor, então vamos permitir trafego na porta 22. É importante que voce proteja esse acesso permitindo que somente seus IPs confiáveis possam acessar, por simplicidade vamos iniciar permitindo todas as conexões SSH:

```bash
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
```

O "-A" significa "Append", isso insere a regra no final da lista, para colocar no topo use a flag "-I".

É uma boa ideia sempre adicionar comentários nas regras, para no futuro facilitar o nosso troubleshooting.

No iptables, podemos adicionar comentários com a seguinte sintaxe:

```bash
iptables -m comment --comment "Seu comentario aqui"
```

Se voce quiser restringir seu acesso SSH para apenas um IP de origem (por exemplo, o IP da sua casa), faça assim:

```bash
iptables -A INPUT -p tcp -s <seu-ip-de-casa> -m comment --comment "Permite SSH de casa" --dport 22 -j ACCEPT
```

### Passo 4: Permitir HTTP e HTTPs (portas 80 e 443)

Se voce estiver rodando um webserver, voce vai querer liberar o trafego nessas portas:

```bash
iptables -A INPUT -m comment --comment "Permite HTTP" -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -m comment --comment "Permite HTTPS" -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -m comment --comment "Permite QUIC" -p udp --dport 443 -j ACCEPT
```

Isso permite o trafego ao seu servidor via HTTP (porta 80) e HTTPS (porta 443).

Note que eu adicionei a porta 443/udp, que é para o protocolo QUIC, QUIC é um protocolo de camada de transporte desenvolvido pelo Google, feito para ser mais rápido, e mais seguro combinando features do TCP, TLS e HTTP/2 para melhorar a latência e performance. Eu recomendo que voce pesquise mais sobre esse assunto, talvez eu faça um artigo sobre ele no futuro.

### Passo 5: Permitir trafego loopback

O seu servidor precisa se comunicar com ele mesmo pela interface loopback. Garanta que esse trafego seja permitido:

```bash
iptables -A INPUT -m comment --comment "Permite trafego loopback" -i lo -j ACCEPT
```

### Passo 6: Dropar pacotes inválidos

Pacotes inválidos podem ser erros de configuração ou até mesmo ataques, então é uma boa pratica sempre dropar:

```bash
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
```

### Passo 7: Permitir conexões estabelecidas e relacionadas

Para permitir respostas a conexões de saída (como quando o seu servidor solicita algum update), voce vai precisar aplicar essa regra:

```bash
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
```

Isso garante que o servidor aceite respostas para requisições que ele mesmo fez.

### Passo 8: Não esqueça o IPv6

Para IPv6, a sintaxe é a mesma, voce apenas precisa mudar o comando de `iptables` para `ip6tables`

A maior diferença é no protocolo ICMP, voce deve sempre permitir ICMPv6 para que o seu servidor funcione corretamente.

Essas são algumas regras iniciais, onde permitimos explicitamente pacotes de controle ICMPv6 e dropamos o resto.

```bash
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type echo-reply -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j DROP
```

### Passo 9: Salve suas regras

Quando voce terminou de aplicar as suas regras, não se esqueça de salvar elas. Isso garante que elas sejam aplicadas novamente no proximo reboot:

```bash
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
```

### Passo 10: Testar tudo

Depois de configurar todas as suas regras, é bom sempre valida-las conectando em seu servidor. Nesse exemplo voce deve conseguir se comunicar via SSH, HTTP e HTTPS, todo o resto deve estar bloqueado.

## Sumario

Em sumario, essas são algumas regras básicas para iniciar, sempre revise e altere conforme a sua necessidade!

### IPv4

```bash
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -p tcp -s <seu-ip-de-casa> -m comment --comment "Permite SSH de casa" --dport 22 -j ACCEPT
iptables -A INPUT -m comment --comment "Permite HTTP" -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -m comment --comment "Permite HTTPS" -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -m comment --comment "Permite QUIC" -p udp --dport 443 -j ACCEPT
iptables -A INPUT -m comment --comment "Permite trafego loopback" -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables-save > /etc/iptables/rules.v4
```

### IPv6

```bash
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -p tcp -s <seu-ip-de-casa> -m comment --comment "Permite SSH de casa" --dport 22 -j ACCEPT
ip6tables -A INPUT -m comment --comment "Permite HTTP" -p tcp --dport 80 -j ACCEPT
ip6tables -A INPUT -m comment --comment "Permite HTTPS" -p tcp --dport 443 -j ACCEPT
ip6tables -A INPUT -m comment --comment "Permite QUIC" -p udp --dport 443 -j ACCEPT
ip6tables -A INPUT  -m comment --comment "Permite trafego loopback" -i lo -j ACCEPT
ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
ip6tables-save > /etc/iptables/rules.v6
```

## Conclusão

Parabéns! Voce acabou de configurar o iptables em seu novo servidor GNU/Linux. Por bloquear todo o trafego exceto o que é confiável voce adicionou uma camada de segurança a seu servidor.
