# Firewall para servidores web: abrir só as portas necessárias

> Firewall para servidor web: verificar portas abertas, libertar só 80 e 443, restringir SSH, limitar ligações de saída. Com nftables e ufw.

Fonte: https://phpsos.de/pt/blog/firewall-fuer-webserver/  
Atualizado em: 25/10/2026  
Prestador: PHP SOS, Assistência de emergência PHP e segurança de servidores. Ajuda imediata por WhatsApp: https://wa.me/491736494914?text=Ol%C3%A1%2C%20PHP%20SOS%2C%20precisamos%20de%20ajuda%20com%20o%20nosso%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Site%3A%20%E2%80%A6

**Em resumo:** Uma firewall para servidores web permite à entrada apenas TCP 80 e 443, no HTTP/3 também UDP 443, e o SSH apenas a partir de redes conhecidas. Tudo o resto é descartado: bases de dados, caches, PHP-FPM e interfaces de administração não pertencem à Internet. Verifique primeiro com `ss -tulpn` o que está à escuta, construa depois um conjunto de regras com a predefinição «descartar» e teste o resultado a partir de fora. Restringir as ligações de saída limita adicionalmente as consequências de uma intrusão.

## As portas esquecidas ao lado da porta de casa

No PHP2Shell, o olhar dirigiu-se ao próprio servidor web, às portas 80 e 443. Essas têm de estar abertas, caso contrário não há site. Nos levantamentos feitos após vulnerabilidades como esta, nota-se porém muitas vezes outra coisa: ao lado da porta de casa há outras portas abertas. Uma base de dados à escuta em todas as interfaces de rede, um pool PHP-FPM na porta 9000, um serviço de cache sem palavra-passe, uma interface de administração da fase de configuração.

Cada uma destas portas é uma superfície de ataque própria, com vulnerabilidades próprias. Uma firewall que permite apenas o necessário fecha-as com poucas regras. É uma das medidas mais eficazes ao proteger um servidor próprio, como também descreve a página [Proteger por si próprio servidores root e vServers](https://phpsos.de/pt/server/root-server-vserver/).

## O que deve estar aberto e o que não

O princípio é uma lista de permissões: tudo fechado, e apenas os serviços libertados de forma consciente são acessíveis. O quadro seguinte ajuda no enquadramento.

| Serviço | Porta típica | Acessível a partir de fora? |
|---|---|---|
| HTTP e HTTPS | TCP 80, TCP 443 | sim |
| HTTP/3 (QUIC) | UDP 443 | só se utilizado |
| SSH | TCP 22 | só a partir de redes conhecidas ou por VPN |
| Painel de alojamento | consoante o produto | só a partir de redes conhecidas |
| MySQL/MariaDB, PostgreSQL | TCP 3306, TCP 5432 | não |
| Redis, Memcached | TCP 6379, TCP 11211 | não |
| PHP-FPM | TCP 9000 ou socket Unix | não, melhor apenas socket |
| Servidor de correio | TCP 25, 465, 587, 993 | só se o servidor receber ou disponibilizar correio |

Um serviço que não precisa de ir para o exterior deve, além disso, ficar à escuta apenas em `127.0.0.1` ou num socket Unix. Assim, permanece inacessível mesmo numa falha da firewall. Para acessos de administração servem libertações de IP ou uma VPN; os pormenores estão no artigo [Proteger áreas de administração por IP, VPN ou proteção adicional](https://phpsos.de/pt/blog/admin-bereiche-abschirmen/).

## Passo 1: determinar o que está à escuta

Antes de escrever regras, obtenha uma visão geral. Os comandos seguintes apenas leem:

```bash
# Todas as portas TCP e UDP à escuta, com processo
sudo ss -tulpn
# Conjunto de regras atual do nftables
sudo nft list ruleset
# Estado do ufw, se utilizado
sudo ufw status verbose
```

Na saída do `ss`, atenção ao endereço antes da porta. `0.0.0.0` ou `[::]` significa: o serviço está à escuta em todas as interfaces. `127.0.0.1` significa: apenas localmente. Anote para cada serviço se tem de ser acessível a partir de fora. Esta lista é também uma parte do seu inventário de servidores.

## Firewall para servidores web com nftables

O nftables é o atual filtro de pacotes no Linux. O conjunto de regras seguinte baseia-se no exemplo do wiki oficial do nftables e acrescenta uma libertação de SSH apenas a partir de uma rede de administração. Os endereços são exemplos de documentação e têm de ser substituídos.

```nft
#!/usr/sbin/nft -f
flush ruleset

table inet filter {
    set verwaltung_v4 {
        type ipv4_addr
        flags interval
        elements = { 203.0.113.0/28 }
    }

    chain input {
        type filter hook input priority 0; policy drop;

        ct state vmap { established : accept, related : accept, invalid : drop }
        iifname lo accept

        # O IPv6 precisa de deteção de vizinhos
        icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
        icmp type echo-request limit rate 5/second accept
        icmpv6 type echo-request limit rate 5/second accept

        # Site
        tcp dport { 80, 443 } accept
        # apenas no HTTP/3:
        # udp dport 443 accept

        # SSH apenas a partir da rede de administração
        ip saddr @verwaltung_v4 tcp dport 22 accept
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }
}
```

Verifique o conjunto de regras antes de o carregar com `nft -c -f /etc/nftables.conf`. A primeira linha `flush ruleset` apaga todas as regras existentes, também as que o Docker ou o Fail2ban registaram. Em servidores com Docker ou outros serviços que definem regras próprias, adapte por isso o conjunto de regras, em vez de o substituir de forma generalizada. Como o Fail2ban colabora com a firewall está em [Configurar o Fail2ban para servidores web](https://phpsos.de/pt/blog/fail2ban-fuer-webserver/).

Quem preferir algo mais simples usa, no Ubuntu, o `ufw`. Importante é a ordem: primeiro a libertação do SSH, depois ativar.

```bash
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow proto tcp from 203.0.113.0/28 to any port 22
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
```

> **Importante:**
> Altere regras de firewall em servidores remotos apenas com uma segunda via de acesso, por exemplo a consola do seu fornecedor. Uma regra SSH errada deixa-o, caso contrário, bloqueado a si próprio.

## Ligações de saída: a metade subestimada

A maioria das firewalls permite tudo à saída. Para um servidor web, isso é generoso. Após uma intrusão, os atacantes usam ligações de saída para carregar ferramentas, extrair dados ou receber comandos. Processos do servidor web ou do PHP que estabelecem ligações inesperadas são por isso considerados um sinal de alerta.

Limitar as ligações de saída dá mais trabalho, porque é preciso conhecer cada ligação legítima: fontes de pacotes para atualizações, serviços de pagamento, interfaces, envio de correio, servidores de tempo. Um caminho pragmático é começar por registar as ligações de saída, formar depois uma lista de permissões e só então bloquear. Como verificar ligações existentes é descrito em [Verificar as ligações de saída de um servidor](https://phpsos.de/pt/blog/ausgehende-verbindungen-pruefen/); que outros vestígios apontam para uma intrusão está em [Será que já fui comprometido?](https://phpsos.de/pt/php2shell/bin-ich-gehackt-anzeichen/).

Por fim, teste a partir de fora, a partir de outro computador e apenas contra os seus próprios sistemas, que portas são realmente acessíveis. Só este teste mostra se o Docker, a firewall do fornecedor e as regras do servidor dão em conjunto o quadro pretendido.

## Conclusão: poucas regras, grande efeito

Uma firewall de servidor web não tem de ser complicada. Portas web abertas, administração apenas a partir de redes conhecidas, tudo o resto descartado: com estas regras de base, bases de dados, caches e serviços esquecidos desaparecem da Internet. É uma das medidas com a melhor relação entre esforço e benefício.

Contra vulnerabilidades no servidor web ou no próprio PHP, a firewall não ajuda, pois precisamente essas portas têm de permanecer abertas. A sua força está em manter pequena a restante superfície de ataque e em conter, com uma limitação das ligações de saída, as consequências de uma intrusão.

Decisiva é a manutenção. Cada novo serviço, cada contentor e cada alteração no fornecedor pode deslocar o quadro. Repita por isso a verificação a partir de fora após cada alteração maior e a intervalos fixos, por exemplo uma vez por trimestre.

## Como ajuda concretamente a PHP SOS?

- **Fazer o levantamento:** registamos todos os serviços à escuta e verificamos a partir de fora o que é realmente acessível.
- **Construir o conjunto de regras:** elaboramos uma lista de permissões para ligações de entrada e, onde faz sentido, de saída, articulada com o Docker, o Fail2ban e a firewall do fornecedor.
- **Alterar com segurança:** aplicamos as alterações com uma segunda via de acesso e um plano de recuo.
- **Documentar:** registamos portas, libertações e motivos no âmbito do [reforço de segurança de servidores](https://phpsos.de/pt/leistungen/server-haertung/).


## Perguntas frequentes

**Que portas precisa um servidor web?**  
Para os visitantes, em regra apenas TCP 80 e 443 e, no HTTP/3, adicionalmente UDP 443. O SSH e as interfaces de administração só devem ser acessíveis a partir de redes conhecidas ou por VPN. As portas de bases de dados, caches e PHP-FPM não pertencem à Internet.

**Uma firewall protege contra o PHP2Shell?**  
Não. O PHP2Shell é explorado através do servidor web, ou seja, precisamente através das portas que têm de estar abertas. Mas a firewall reduz a restante superfície de ataque, e uma limitação das ligações de saída pode conter as consequências de uma intrusão.

**Por que mostra o ufw portas como fechadas que, ainda assim, são acessíveis?**  
Um caso conhecido são os contentores Docker: o Docker regista as portas publicadas diretamente nas regras do filtro de pacotes, contornando o ufw. Verifique por isso as portas abertas sempre também a partir de fora.

**A firewall do meu fornecedor de alojamento basta?**  
Uma firewall do fornecedor, colocada antes, é uma boa segunda camada. Mas não substitui a firewall no servidor, porque não atua em caso de erro na configuração do fornecedor ou em ligações internas. O melhor é usar ambas com as mesmas regras de base.

## Fontes

- [Wiki do nftables: conjunto de regras simples para um servidor](https://wiki.nftables.org/wiki-nftables/index.php/Simple_ruleset_for_a_server)
- [Ubuntu Server: firewall (ufw)](https://ubuntu.com/server/docs/how-to/security/firewalls/)
- [BSI IT-Grundschutz](https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Standards-und-Zertifizierung/IT-Grundschutz/it-grundschutz_node.html)
- [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks)
