Do 'no route to host' ao virtual host: debugging de Nginx standalone e redes na nuvem
Voltar para blog

Do 'no route to host' ao virtual host: debugging de Nginx standalone e redes na nuvem

16/09/2026 · 3 min · Servidores

Do 'no route to host' ao virtual host: debugging de Nginx standalone e redes na nuvem#

Recentemente, configurei uma instância de NGINX standalone para atender diretamente na porta 80 em um ambiente de nuvem. Embora a configuração inicial de um servidor web pareça direta, a realidade do terminal frequentemente envolve detalhes de baixo nível: permissões de binding no kernel, comportamento de filtros de pacotes e regras de borda de firewalls de nuvem.

Abaixo, compartilho o fluxo prático: do ciclo de vida dos processos do NGINX ao diagnóstico do erro No route to host e à implementação modular de Virtual Hosts (server blocks).

1. O ponto de partida: Nginx standalone e portas privilegiadas#

Para escutar na porta HTTP padrão (80), a diretiva básica no bloco server {} é:

server {
    listen 80 default_server;
    listen [::]:80 default_server; # Suporte a IPv6
    server_name _;

    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
}

Para cenários com alta concorrência em sistemas multi-core, a diretiva listen pode ser otimizada com a flag de kernel reuseport:

listen 80 default_server reuseport;

O que acontece no kernel (master-worker e capabilities)#

A porta 80 está na faixa privilegiada do Linux (0 a 1023):

  1. O processo Master do NGINX inicia como root para invocar a syscall socket() e realizar o bind() exigindo a capability CAP_NET_BIND_SERVICE.
  2. Após o listen(), o Master gera os processos Worker via fork() e rebaixa seus privilégios via setuid() e setgid() para o usuário nginx ou www-data, mitigando riscos de segurança.

Se for necessário rodar o binário sem privilégios de root, conceda a capability diretamente ao arquivo:

setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx

2. O sintoma: "no route to host" no IP público#

Ao testar a conectividade externa contra o IP público da instância (203.0.113.10):

telnet 203.0.113.10 80
# Trying 203.0.113.10...
# telnet: Unable to connect to remote host: No route to host

Verificando os sockets ativos no host com ss -tulpn:

tcp   LISTEN 0      511            0.0.0.0:80        0.0.0.0:*    users:(("nginx",pid=4356,fd=5))
tcp   LISTEN 0      511               [::]:80           [::]:*    users:(("nginx",pid=4356,fd=6))

Testando localmente na interface de loopback:

telnet 127.0.0.1 80
# Connected to 127.0.0.1.

Análise da causa raiz#

Se o socket responde em 127.0.0.1:80, o NGINX está funcionando perfeitamente. O erro No route to host (ICMP Type 3, Code 1) indicava rejeição ativa na camada de rede.

Inspecionando a tabela de roteamento e regras do iptables:

# Verificar contadores do iptables na porta 80
iptables -L INPUT -n -v | grep :80
# 0     0 ACCEPT     6    --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80

Três fatores explicavam o bloqueio:

  1. Contador zerado no iptables: A regra da porta 80 acumulava 0 pkts, provando que o tráfego era descartado antes dessa linha ou fora do host.
  2. Falta de Hairpin NAT: A rota local enviava pacotes para o IP público através do gateway padrão (10.0.0.1), que não fazia loopback para a própria interface.
  3. Firewall de borda da nuvem: Em provedores como Oracle Cloud, AWS ou GCP, as Security Lists ou Network Security Groups bloqueiam tráfego de entrada na porta 80 por padrão até que uma regra explícita de Ingress seja criada.

3. Desbloqueio e ajustes de firewall#

  1. Precedência no iptables local:

Insira a regra de liberação na primeira posição da chain para ficar acima de qualquer regra genérica de REJECT:

   iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
   netfilter-persistent save
  1. Liberação nas Security Lists da nuvem:

No painel da nuvem (VCN > Security Lists), adicione uma regra de entrada:

4. Implementando virtual hosts modulares#

Com a conectividade restabelecida, o passo seguinte foi estruturar vHosts limpos e modulares.

Inclusão no /etc/Nginx/nginx.conf#

No bloco http {}:

http {
    include /etc/nginx/sites-enabled/*;
}

Configuração do vhost (/etc/Nginx/sites-available/meusite.com.br.conf)#

server {
    listen 80;
    listen [::]:80;

    server_name meusite.com.br www.meusite.com.br;

    access_log /var/log/nginx/meusite.access.log combined buffer=16k;
    error_log /var/log/nginx/meusite.error.log warn;

    root /var/www/meusite.com.br/public_html;
    index index.html index.php;

    # Bloqueio de arquivos ocultos (.git, .env, .htaccess)
    location ~ /\.(?!well-known).* {
        deny all;
        access_log off;
        log_not_found off;
    }

    location / {
        try_files $uri $uri/ /index.html;
        sendfile on;
        tcp_nodelay on;
        keepalive_timeout 65;
    }
}
Performance: sendfile on transfere dados diretamente do descritor de arquivo no disco para o socket de rede no Kernel Space, eliminando cópias desnecessárias na memória do User Space.

Ativação e recarga segura#

# 1. Criar o symlink
ln -s /etc/nginx/sites-available/meusite.com.br.conf /etc/nginx/sites-enabled/

# 2. Testar sintaxe
nginx -t

# 3. Recarregamento gracioso (SIGHUP)
nginx -s reload

Validando a resposta do vhost localmente#

Para testar o roteamento antes da propagação do DNS:

curl -H "Host: meusite.com.br" http://127.0.0.1

O NGINX processa o cabeçalho Host e entrega o conteúdo exato do vHost configurado.

Boas práticas de rede e vhosts no Nginx#

  1. Valide em etapas: Teste primeiro em 127.0.0.1 antes de depurar a rede pública. Se a loopback responde, o serviço está saudável e o bloqueio é de firewall ou roteamento.
  2. Cuidado com a ordem do iptables: Regras adicionadas com -A ficam no final da chain, muitas vezes atrás de uma regra padrão de descarte (REJECT-with-icmp-host-prohibited). Use -I para garantir precedência.
  3. Use sendfile e buffers: Diretivas como sendfile on e buffers em logs de acesso reduzem o impacto de I/O em servidores com grande volume de requisições.

Este artigo foi útil?

Deixe uma reação rápida para apoiar o conteúdo:

CC BY-NC

Este post está licenciado sob CC BY-NC.

Comentários

Participe da discussão abaixo.

0 comentários