SSD Nodes Learn 🎉 VPS desde $5.50/mês
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-13

firewalld no Rocky e AlmaLinux: regras para VPS

Aprenda a abrir SSH e portas web, fechar serviços e manter regras após reiniciar. Entenda zonas e evite o erro comum da flag --permanent no firewalld.

O que é o firewalld e por que o Rocky e o AlmaLinux o incluem

O firewalld é o gestor de firewall instalado por predefinição no Rocky Linux, AlmaLinux e nas outras reconstruções do Red Hat Enterprise Linux (RHEL). Ele não inspeciona os pacotes diretamente. Mantém uma configuração guardada e transforma essa configuração em regras nftables. O comando firewall-cmd permite editá-la enquanto o servidor continua online.

Se já sabe como funciona o ufw num VPS Ubuntu, conhece a finalidade. O firewalld acrescenta duas ideias que o ufw não tem. A primeira são as zonas: uma política com nome para a qual os pacotes são encaminhados. A segunda é a separação entre as regras ativas e as regras guardadas. Essa separação é controlada pela flag --permanent e é a maior fonte de confusão nesta ferramenta.

Tudo o que se segue são comandos que executa no seu próprio servidor. Teste cada alteração a partir de uma segunda máquina, porque uma regra que parece correta no servidor pode continuar errada quando é avaliada a partir da Internet.

Abra o SSH antes de fazer qualquer outra coisa

A maioria das instalações de Rocky e AlmaLinux já tem o firewalld instalado e em execução, e a configuração fornecida permite SSH. Algumas imagens de cloud minimalistas removem-no. Verifique em vez de presumir.

sudo dnf install -y firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --state

firewall-cmd --state imprime running. Se o serviço estiver parado, todas as outras chamadas firewall-cmd respondem FirewallD is not running e terminam com um código diferente de zero. Esta é a primeira coisa a verificar quando um comando parece não fazer absolutamente nada.

Agora veja o que está atualmente permitido.

sudo firewall-cmd --list-all

A saída real tem mais algumas linhas. Estas são as relevantes:

public (active)
  target: default
  interfaces: eth0
  sources:
  services: cockpit dhcpv6-client ssh
  ports:
  rich rules:

ssh na linha services: é o motivo pelo qual a sua sessão continua a funcionar. Se estiver ausente, adicione-o antes de fazer qualquer outra alteração, porque iniciar um firewall sem uma regra para SSH termina a sessão e não permite voltar a ligar-se.

sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload

target: default significa que um pacote que não corresponde a nenhuma regra é rejeitado com uma resposta ICMP (Internet Control Message Protocol) host-prohibited, por isso um cliente que aceda a uma porta fechada recebe No route to host imediatamente. Definir o destino como DROP faz com que o servidor permaneça silencioso, e os scanners aguardam então até ocorrer um timeout.

sudo firewall-cmd --permanent --zone=public --set-target=DROP
sudo firewall-cmd --reload

Tenha em conta o impacto antes de executar isto: DROP também impede que o servidor responda a ping, pelo que o seu próprio monitoramento também fica silencioso.

Por que a minha regra desapareceu? A opção --permanent

O firewalld mantém duas configurações ao mesmo tempo. A configuração de runtime é a que o kernel aplica neste momento. A configuração permanente é a que fica em /etc/firewalld/zones/public.xml e que volta a ser aplicada depois de um reload ou reboot.

Um comando sem --permanent altera apenas a configuração de runtime. A alteração tem efeito imediato e desaparece no próximo reload ou boot. Um comando com --permanent escreve no ficheiro e não altera o que está em execução, por isso a porta permanece fechada até fazer reload. Nenhum destes comportamentos é um erro. Ambos confundem os administradores porque o comando apresenta success nos dois casos.

Escreva sempre o par.

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload

Pode consultar as duas configurações. Esta é a forma mais rápida de descobrir qual dos dois erros cometeu.

sudo firewall-cmd --list-services
sudo firewall-cmd --permanent --list-services

O primeiro comando apresenta o conjunto ativo. O segundo apresenta o conjunto guardado. Se o conjunto ativo tiver um serviço que não existe no conjunto guardado, essa regra desaparece no próximo reload. Se o conjunto guardado tiver uma regra que não existe no conjunto ativo, esqueceu-se de fazer reload. sudo firewall-cmd --runtime-to-permanent copia tudo o que está ativo para o ficheiro guardado. Isto é útil depois de uma sessão de testes.

--reload mantém o estado de acompanhamento das ligações, por isso a sua sessão SSH continua ativa. --complete-reload também recarrega os módulos do kernel e perde esse estado, o que normalmente termina todas as ligações abertas, incluindo a sua. Use o reload normal.

Existe uma rede de segurança integrada. Uma regra de runtime pode expirar sozinha.

sudo firewall-cmd --add-service=http --timeout=5m

Essa regra remove-se ao fim de cinco minutos. Não pode ser combinada com --permanent. Esse é precisamente o objetivo: testar uma alteração sobre a qual não tem a certeza. A rede de segurança mais antiga é melhor. Mantenha uma segunda sessão SSH aberta enquanto edita as regras e não a feche até um novo login confirmar que as regras novas funcionam.

Zonas e por que apenas a zona predefinida importa numa VPS

Uma zona é um conjunto nomeado de permissões associado a um nível de confiança. O firewalld coloca cada pacote recebido exatamente numa zona. Primeiro, compara o endereço de origem do pacote com a lista sources: de cada zona. Se não houver correspondência, usa a zona à qual a interface de entrada está associada. Se a interface não estiver associada a nenhuma zona, o pacote vai para a zona predefinida.

sudo firewall-cmd --get-default-zone
sudo firewall-cmd --get-active-zones

Numa VPS com uma interface de rede, a primeira resposta é quase sempre public, e essa é a única zona que usará. firewall-cmd sem o argumento --zone= atua sobre a zona predefinida. É por isso que todos os comandos curtos deste guia funcionam sem indicar uma zona.

Este é o erro que pode consumir uma tarde inteira. Se a interface estiver associada a outra zona, as suas regras são adicionadas a public, mas o tráfego é processado noutra zona. Por isso, nada do que adicionar terá efeito e nenhum aviso será apresentado. --get-active-zones mostra a associação:

public
  interfaces: eth0

Se a interface aparecer com outro nome de zona, escreva as regras nessa zona usando --zone= ou mova a interface.

sudo firewall-cmd --permanent --zone=public --change-interface=eth0
sudo firewall-cmd --reload

O NetworkManager gere as interfaces em Rocky e AlmaLinux e reaplica a zona quando a ligação é ativada. Configure também essa associação no NetworkManager para que um reboot não desfaça o trabalho. Obtenha o nome da ligação no primeiro comando, porque raramente é igual ao nome do dispositivo.

sudo nmcli connection show
sudo nmcli connection modify "System eth0" connection.zone public

A correspondência por origem tem prioridade sobre a correspondência por interface. É assim que um endereço pode receber uma política diferente. A zona predefinida trusted aceita tudo.

sudo firewall-cmd --permanent --zone=trusted --add-source=203.0.113.10/32
sudo firewall-cmd --reload

Tenha cuidado com essa zona. Ela abre todas as portas do servidor para esse endereço, incluindo a base de dados que considerava privada. Use uma regra rica quando quiser permitir uma porta específica, e não um host inteiro.

O que é um serviço do firewalld?

Um serviço é um conjunto nomeado de portas distribuído como um ficheiro XML. --add-service=https abre 443/tcp porque /usr/lib/firewalld/services/https.xml define o que https significa.

sudo firewall-cmd --get-services
sudo firewall-cmd --info-service=https

--info-service mostra as portas associadas ao nome:

https
  ports: 443/tcp

Use o nome quando existir. A configuração fica clara em --list-all mesmo seis meses depois, e pacotes como o Cockpit instalam o seu próprio ficheiro de serviço. Use --add-port para tudo o que não tenha uma definição.

A diferença que deve verificar: o serviço ssh significa 22/tcp e nada mais. Se mudou o SSH para outra porta ao reforçar o acesso SSH ao servidor, então --add-service=ssh não abre a porta que realmente utiliza.

sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload

Numa reinstalação do RHEL, existe um segundo bloqueio nessa porta. O SELinux (security-enhanced Linux) atribui etiquetas aos números de porta, e sshd não tem permissão para associar-se a uma porta fora das etiquetas atribuídas. Nesse caso, recusa iniciar e o log mostra error: Bind to port 2222 on 0.0.0.0 failed: Permission denied. Atribua primeiro a etiqueta à porta.

sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222

Como vejo o que está aberto agora?

sudo firewall-cmd --list-all
sudo firewall-cmd --list-rich-rules
sudo nft list table inet firewalld | head -n 40

Os dois primeiros comandos mostram o que o firewalld considera permitido. O terceiro lê as regras que o kernel mantém efetivamente, na tabela gerida pelo firewalld. Os resultados devem coincidir.

Nada disso é uma prova. Teste a partir de outra máquina:

nc -zv 203.0.113.20 443

Não execute o teste no próprio servidor. O firewalld aceita tudo o que chega pela interface de loopback, por isso curl http://localhost:8080 é bem-sucedido independentemente das regras configuradas. Esse teste mostra que o serviço está ativo. Não fornece qualquer informação sobre o firewall.

Permitir uma porta web

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services

O último comando deve agora listar http https juntamente com o que já estava presente. Se o site continuar sem responder, o firewall pode não ser o problema. Uma regra permite a passagem de um pacote. Ainda tem de existir um processo a escutar nessa porta.

sudo ss -tlnp

Um socket apresentado como 0.0.0.0:443 ou *:443 aceita ligações de qualquer endereço. Um apresentado como 127.0.0.1:443 responde apenas na interface de loopback, e nenhuma regra de firewall o tornará acessível a partir do exterior. Portas e sockets em escuta no Linux explica esta diferença com mais detalhe.

Como volto a fechar uma porta?

sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload

A regra --permanent também se aplica aqui, e tem consequências mais graves neste sentido. Remova um serviço apenas do estado em execução e a porta parecerá fechada. No próximo reload ou reboot, ela será reaberta a partir do ficheiro guardado. Isto cria uma falha que não detetará, porque a verificação que executou foi bem-sucedida.

Remover algo que nunca esteve presente apresenta Warning: NOT_ENABLED: http e, ainda assim, termina com o código 0. Adicionar o mesmo elemento duas vezes apresenta Warning: ALREADY_ENABLED: http. Ambos os casos são seguros. Um nome escrito incorretamente é diferente: Error: INVALID_SERVICE significa que o firewalld não tem nenhuma definição com esse nome e que nada foi alterado.

Se --list-all apresentar cockpit e não utilizar a consola Web Cockpit na porta 9090, remova-o. Cada porta aberta corresponde a um serviço que tem de manter atualizado com patches.

Restringir uma porta a um endereço de origem

As rich rules são a forma completa de definir regras, quando um nome de serviço simples não consegue expressar o que pretende. Restringir o SSH a um endereço do escritório requer dois comandos, e o segundo é o que muitas pessoas esquecem.

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" service name="ssh" accept'
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload

Uma zona é um conjunto de permissões, não uma lista numerada que para na primeira correspondência. A rich rule adiciona uma permissão para um endereço. Não nega o acesso a ninguém. Enquanto ssh continuar na linha services:, toda a Internet continuará a alcançar a porta 22 e a rich rule não alterará nada que possa medir. Remova a entrada abrangente, caso contrário a regra restrita será apenas decorativa.

Para uma porta sem nome de serviço, indique a porta diretamente.

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" port port="5432" protocol="tcp" accept'

Para descartar uma rede ruidosa e manter um registo, coloque o elemento de log antes da ação. Essa é a ordem esperada pela linguagem de rich rules.

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.0/24" log prefix="fw-drop " level="info" limit value="3/m" drop'
sudo firewall-cmd --reload
sudo journalctl -k -g fw-drop

O valor limit impede que uma inundação de pacotes encha o journal. Antes de restringir o SSH a um único endereço, confirme que esse endereço é estável. Uma ligação doméstica com um endereço IP dinâmico pode bloquear o seu acesso no dia em que o endereço mudar. Por isso, teste primeiro o acesso à consola do fornecedor e confirme que está a funcionar.

comandos do ufw e equivalentes do firewall-cmd

As tarefas são as mesmas, mas a ferramenta é diferente. Cada linha --permanent precisa de um sudo firewall-cmd --reload depois dela. Esta é a única informação que uma lista como esta não consegue mostrar.

  • sudo ufw enable torna-se sudo systemctl enable --now firewalld
  • sudo ufw disable torna-se sudo systemctl disable --now firewalld
  • sudo ufw status verbose torna-se sudo firewall-cmd --list-all
  • sudo ufw allow OpenSSH torna-se sudo firewall-cmd --permanent --add-service=ssh
  • sudo ufw allow 443/tcp torna-se sudo firewall-cmd --permanent --add-port=443/tcp
  • sudo ufw delete allow 443/tcp torna-se sudo firewall-cmd --permanent --remove-port=443/tcp
  • sudo ufw allow from 203.0.113.10 to any port 22 torna-se a rich rule apresentada acima
  • sudo ufw reload torna-se sudo firewall-cmd --reload
  • sudo ufw default deny incoming já corresponde ao comportamento da zona public, e --set-target=DROP é a sua versão silenciosa
  • sudo ufw logging on torna-se sudo firewall-cmd --set-log-denied=all

É importante indicar claramente uma diferença. O ufw mantém uma lista numerada, e pode inserir uma regra na posição 1. O firewalld não tem números de regras, por isso "colocar esta regra primeiro" não tem significado neste caso. Quando duas entradas do firewalld parecem entrar em conflito, a aceitação abrangente prevalece, porque nada no conjunto nega o tráfego. A entrada abrangente tem de ser removida manualmente.

Por que meu container Docker está acessível quando o firewall parece fechado?

Porque uma porta publicada pelo container nunca passa pela parte do firewall controlada pela sua zona. docker run -d -p 8080:80 nginx instrui o Docker a criar as próprias regras de NAT (network address translation) e encaminhamento. Um pacote recebido na porta 8080 é reescrito e encaminhado para o container, portanto é encaminhado em vez de ser entregue ao host. As linhas services: e ports: da sua zona controlam os pacotes entregues ao host. As regras do Docker controlam o caminho de encaminhamento e aceitam esses pacotes.

O resultado é um servidor em que sudo firewall-cmd --list-all não mostra a porta 8080, mas nc -zv 203.0.113.20 8080 a partir de outra máquina estabelece a ligação mesmo assim. Veja o que o Docker instalou:

sudo iptables -t nat -L DOCKER -n

A correção está na flag de publicação. Vincule a porta ao loopback e coloque um reverse proxy à frente dela.

docker run -d -p 127.0.0.1:8080:80 nginx

Agora o container responde a curl http://127.0.0.1:8080 no servidor, e nada responde externamente. Os utilizadores do Ubuntu enfrentam o mesmo problema, descrito em por que os containers Docker publicam portas diretamente através do ufw. O Podman rootful, que o Rocky e o AlmaLinux disponibilizam nos repositórios base, publica portas usando a mesma abordagem de NAT. Por isso, teste a partir de outra máquina em vez de confiar na lista da zona.

Fazer a configuração sobreviver a um reboot e os erros que verá

sudo systemctl is-enabled firewalld
sudo systemctl status firewalld

enabled e active (running) são o que pretende. Um firewall em execução, mas não ativado, protege-o apenas até ao primeiro reboot. Essa verificação deve fazer parte da lista que segue nos primeiros dez minutos num VPS novo, juntamente com as chaves SSH e as atualizações.

Comandos nftables diretos e firewalld não são compatíveis. O firewalld gere uma tabela chamada inet firewalld. sudo nft flush ruleset elimina-a, deixando o servidor aberto a tudo, enquanto firewall-cmd --list-all continua a mostrar a configuração pretendida, porque o firewalld apresenta aquilo que considera estar configurado, e não o que o kernel mantém. sudo firewall-cmd --reload reinstala as regras. Escreva as regras com firewall-cmd para que voltem a ser aplicadas depois de um reload.

Dois gestores de firewall no mesmo servidor. Instalar ufw ou iptables-services juntamente com o firewalld coloca dois programas a escrever regras sem conhecimento um do outro. O resultado depende de qual serviço arrancou por último. Escolha apenas um. No Rocky e no AlmaLinux, o firewalld é o que tem suporte da distribuição.

O firewall do fornecedor à frente do servidor. Muitos painéis de VPS têm um firewall de rede separado. Se --list-all mostrar uma porta aberta e uma ligação externa continuar a falhar, verifique o painel antes de alterar alguma coisa no servidor. O inverso também acontece: uma regra aberta no painel não produz efeito enquanto o firewalld rejeitar o pacote.

Executar firewall-cmd sem sudo. Todas as alterações exigem root. Sem esse privilégio, o pedido é recusado por uma verificação de autorização e nada é alterado. À primeira vista, isto pode parecer que o comando foi ignorado.

Seis comandos cobrem a maioria das situações: --list-all para consultar o estado, --permanent --add-service ou --add-port para abrir algo, --permanent --remove-service para fechar, --reload para aplicar o ficheiro guardado e --runtime-to-permanent depois de uma ronda de testes. A zona é public, a opção é --permanent e a única verificação fiável vem de outra máquina.

FAQ

Porque é que a regra do firewalld desapareceu depois de um reboot?

A regra foi adicionada apenas à configuração de runtime. sudo firewall-cmd --add-service=http aplica a alteração imediatamente, mas ela é descartada no reload ou no boot seguinte, porque a configuração guardada em /etc/firewalld/zones/public.xml nunca foi alterada. Adicione --permanent e execute sudo firewall-cmd --reload. Para manter regras que já adicionou manualmente, execute sudo firewall-cmd --runtime-to-permanent, que copia o conjunto ativo para o ficheiro guardado.

Porque é que nada muda depois de adicionar uma regra com --permanent?

Porque --permanent escreve no ficheiro e não altera o firewall em execução. A porta permanece fechada até sudo firewall-cmd --reload carregar a configuração guardada no kernel. Compare sudo firewall-cmd --list-services com sudo firewall-cmd --permanent --list-services: se a lista guardada tiver uma entrada que não existe na lista ativa, falta executar o reload.

Devo usar --add-service ou --add-port?

Use --add-service quando existir um nome para o serviço que executa. Isto declara a intenção, e sudo firewall-cmd --info-service=https mostra exatamente que portas o nome abrange. Use --add-port quando nada definir o seu serviço ou quando ele escutar numa porta não padrão. O serviço ssh significa apenas 22/tcp, por isso, se o SSH tiver sido movido para 2222, precisa de --add-port=2222/tcp e de um label SELinux para essa porta.

Porque é que o meu contentor Docker está acessível quando firewall-cmd mostra a porta fechada?

Uma porta publicada é reescrita pelas próprias regras NAT do Docker e encaminhada para o contentor. Por isso, o pacote nunca é entregue ao host, e as listas de serviços e portas de uma zone abrangem apenas os pacotes entregues ao host. O contentor responde a partir da Internet enquanto --list-all não mostra nada. Publique a porta apenas na loopback com docker run -d -p 127.0.0.1:8080:80 nginx e coloque um reverse proxy à frente do serviço.

Posso instalar ufw no Rocky Linux em vez do firewalld?

Dois gestores de firewall no mesmo servidor escrevem regras sem conhecimento um do outro, e o conjunto que permanece depende de qual serviço arrancou por último. O firewalld é a ferramenta suportada no Rocky Linux e no AlmaLinux, já está instalado e utiliza o mesmo backend nftables que o ufw utilizaria. Aprenda uma vez a zone predefinida e a flag --permanent para dominar toda a ferramenta.