EC2 SSH Connection Timeout: Quais Regras do Security Group Verificar

Você acabou de lançar uma instância EC2, tenta conectar via SSH e recebe ssh: connect to host X.X.X.X port 22: Connection timed out. Esse erro específico — timeout, não recusa — quase sempre aponta para bloqueio de rede antes mesmo do pacote chegar ao sistema operacional. O culpado mais comum é o Security Group, mas não é o único.

TL;DR — EC2 SSH Connection Timeout: O Que Verificar

CamadaO Que VerificarImpacto se Errado
Security GroupRegra inbound TCP/22 com source corretoPacote descartado silenciosamente
Network ACLRegra allow na porta 22 e portas efêmeras no outboundTimeout sem log de erro
Rota da SubnetInternet Gateway associado à route tablePacote sem caminho de retorno
IP Público / EIPInstância tem endereço IP público atribuídoDestino inalcançável
Firewall do SOiptables / firewalld bloqueando porta 22Conexão recusada ou timeout

Como o Tráfego SSH Chega à Instância EC2

Antes de sair clicando em regras aleatórias, vale entender o caminho completo do pacote. Um timeout significa que o SYN saiu do seu cliente e nunca recebeu SYN-ACK — o pacote foi descartado em algum ponto do trajeto. Conhecer cada camada elimina o chute e transforma o diagnóstico em processo linear.

graph LR Client["Cliente SSH"] -->|"SYN TCP/22"| IGW["Internet Gateway"] IGW --> NACL["Network ACL (stateless)"] NACL -->|"Regra ALLOW?"| SG["Security Group (stateful)"] SG -->|"Regra inbound TCP/22?"| SSHD["sshd na instância porta 22"] SSHD -->|"SYN-ACK"| SG SG --> NACL2["Network ACL Outbound"] NACL2 -->|"Portas efêmeras ALLOW?"| Client style NACL fill:#f0ad4e,color:#000 style SG fill:#5bc0de,color:#000 style SSHD fill:#5cb85c,color:#000
  1. Cliente SSH envia SYN para o IP público da instância na porta 22.
  2. O pacote entra pela Internet Gateway da VPC e é roteado até a subnet.
  3. O Network ACL (stateless) avalia o pacote contra suas regras numeradas.
  4. O Security Group (stateful) avalia as regras inbound associadas à instância.
  5. O pacote chega ao sistema operacional, onde sshd escuta na porta 22.
  6. A resposta percorre o caminho inverso — Network ACL outbound também é avaliado.

Security Group é stateful: se o inbound permite, o retorno é automático. Network ACL é stateless: você precisa de regras explícitas nos dois sentidos.

Passo 1 — Verificar a Regra Inbound do Security Group (SSH Connection Timeout EC2)

O Security Group é a primeira coisa a checar porque é onde a maioria dos erros acontece. Uma instância recém-criada sem regra inbound explícita para TCP/22 descarta o pacote sem nenhum log visível — exatamente o comportamento de timeout que você está vendo.

Liste as regras do Security Group associado à instância:

aws ec2 describe-security-groups \
  --group-ids sg-0123456789abcdef0 \
  --query 'SecurityGroups[*].IpPermissions' \
  --region us-east-1

Procure por um objeto com FromPort: 22, ToPort: 22, IpProtocol: tcp e um IpRanges que inclua seu IP. Se não existir, adicione a regra:

aws ec2 authorize-security-group-ingress \
  --group-id sg-0123456789abcdef0 \
  --protocol tcp \
  --port 22 \
  --cidr 203.0.113.10/32 \
  --region us-east-1

Use /32 para restringir ao seu IP específico. Usar 0.0.0.0/0 funciona, mas expõe a porta 22 para a internet inteira — em produção, prefira um bastion host ou AWS Systems Manager Session Manager.

Pense no Security Group como um porteiro stateful: ele lembra de quem deixou entrar e abre a saída automaticamente. O Network ACL é o segurança do prédio que verifica cada pessoa individualmente, sem memória de interações anteriores.

Passo 2 — Confirmar que a Instância Tem IP Público

Regra de Security Group correta, mas ainda timeout? Verifique se a instância realmente tem um endereço IP público. Instâncias em subnets privadas ou criadas com 'Auto-assign public IP' desabilitado não têm IP público — você está tentando conectar em um endereço que não existe ou não é roteável.

aws ec2 describe-instances \
  --instance-ids i-0123456789abcdef0 \
  --query 'Reservations[*].Instances[*].{PublicIP:PublicIpAddress,State:State.Name,SubnetId:SubnetId}' \
  --region us-east-1

Se PublicIP retornar null, a instância não tem IP público. Você pode associar um Elastic IP:

aws ec2 allocate-address --domain vpc --region us-east-1

aws ec2 associate-address \
  --instance-id i-0123456789abcdef0 \
  --allocation-id eipalloc-0123456789abcdef0 \
  --region us-east-1

Passo 3 — Verificar a Route Table da Subnet

Mesmo com IP público e Security Group correto, se a subnet não tiver rota para um Internet Gateway, o tráfego não tem como chegar à instância. Esse é o erro clássico de 'subnet pública que não é pública de verdade' — a subnet tem IP público atribuído automaticamente, mas a route table nunca foi atualizada com a rota padrão para o IGW.

aws ec2 describe-route-tables \
  --filters Name=association.subnet-id,Values=subnet-0123456789abcdef0 \
  --query 'RouteTables[*].Routes' \
  --region us-east-1

Procure por uma rota com DestinationCidrBlock: 0.0.0.0/0 e GatewayId começando com igw-. Se não existir, a subnet é efetivamente privada do ponto de vista de roteamento.

Para adicionar a rota padrão via Internet Gateway:

aws ec2 create-route \
  --route-table-id rtb-0123456789abcdef0 \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id igw-0123456789abcdef0 \
  --region us-east-1

Passo 4 — Checar o Network ACL da Subnet

Network ACLs são frequentemente ignorados porque a maioria das VPCs usa as regras padrão que permitem todo o tráfego. O problema aparece quando alguém modificou o NACL da subnet para restringir tráfego — e como NACLs são stateless, bloquear as portas efêmeras de retorno (1024-65535) no outbound quebra conexões TCP mesmo que o inbound esteja correto.

aws ec2 describe-network-acls \
  --filters Name=association.subnet-id,Values=subnet-0123456789abcdef0 \
  --query 'NetworkAcls[*].{Inbound:Entries[?Egress==`false`],Outbound:Entries[?Egress==`true`]}' \
  --region us-east-1

Verifique se existe uma regra ALLOW para TCP/22 no inbound e uma regra ALLOW para o range de portas efêmeras (1024-65535) no outbound. NACLs processam regras em ordem numérica crescente — uma regra DENY com número menor que um ALLOW bloqueia o tráfego mesmo que o ALLOW exista.

graph TD A["Pacote TCP/22 chega na subnet"] --> B{"NACL: existe regra com número menor que faz DENY?"} B -->|"Sim"| C["Pacote descartado Timeout no cliente"] B -->|"Não"| D{"NACL: existe regra ALLOW para TCP/22?"} D -->|"Não"| C D -->|"Sim"| E["Pacote passa para Security Group"] E --> F{"SG: regra inbound TCP/22 com source correto?"} F -->|"Não"| C F -->|"Sim"| G["Pacote entregue ao sshd"] style C fill:#d9534f,color:#fff style G fill:#5cb85c,color:#fff

Passo 5 — Verificar o Estado da Instância e o sshd

Se todas as camadas de rede estão corretas e o timeout persiste, o problema pode estar dentro da instância. Isso é menos comum para timeout puro (que geralmente indica bloqueio de rede), mas acontece quando o firewall do sistema operacional está ativo ou o sshd não está rodando.

Use o EC2 Instance Connect ou o Systems Manager Session Manager para acessar a instância sem SSH e verificar o estado do serviço:

aws ec2-instance-connect send-ssh-public-key \
  --instance-id i-0123456789abcdef0 \
  --instance-os-user ec2-user \
  --ssh-public-key file://~/.ssh/id_rsa.pub \
  --availability-zone us-east-1a \
  --region us-east-1

Ou acesse via SSM Session Manager (sem necessidade de porta 22 aberta):

aws ssm start-session \
  --target i-0123456789abcdef0 \
  --region us-east-1

Dentro da instância, verifique o sshd e o firewall local:

# Verificar se sshd está rodando
sudo systemctl status sshd

# Verificar regras de iptables
sudo iptables -L INPUT -n -v

# Verificar firewalld (Amazon Linux 2023 / RHEL)
sudo firewall-cmd --list-all

O Diagnóstico que Quase Todo Mundo Erra

Aqui está um padrão que aparece com frequência: o engenheiro cria a instância, adiciona a regra TCP/22 no Security Group com source 0.0.0.0/0, e ainda assim recebe timeout. Depois de 20 minutos olhando para o Security Group, descobre que a instância foi lançada em uma subnet privada — sem rota para IGW e sem IP público.

A instância estava perfeitamente configurada. O Security Group estava correto. Mas o pacote nunca chegou porque não havia caminho de rede. O timeout era da camada de roteamento, não do filtro de pacotes.

A lição: timeout significa que o pacote foi descartado ou não encontrou rota. Recusa de conexão (Connection refused) significa que chegou ao destino e o SO rejeitou. Esses dois erros têm diagnósticos completamente diferentes — não trate um como o outro.

Diagnóstico rápido para confirmar qual camada está bloqueando: use traceroute ou mtr do seu cliente para o IP da instância. Se os pacotes pararem no gateway da sua rede ou na borda da AWS sem chegar ao destino, o problema é roteamento ou NACL. Se chegarem perto mas não completarem o handshake, é Security Group ou sshd.

IAM Mínimo para Executar os Diagnósticos

Para rodar os comandos de diagnóstico acima, o usuário ou role precisa das seguintes permissões mínimas:

🔽 Clique para expandir — IAM Policy de Diagnóstico
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DescribeNetworkResources",
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeInstances",
        "ec2:DescribeRouteTables",
        "ec2:DescribeNetworkAcls",
        "ec2:DescribeSubnets",
        "ec2:DescribeInternetGateways"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ModifySecurityGroup",
      "Effect": "Allow",
      "Action": [
        "ec2:AuthorizeSecurityGroupIngress"
      ],
      "Resource": "arn:aws:ec2:us-east-1:123456789012:security-group/sg-0123456789abcdef0"
    },
    {
      "Sid": "SSMSessionAccess",
      "Effect": "Allow",
      "Action": [
        "ssm:StartSession"
      ],
      "Resource": "arn:aws:ec2:us-east-1:123456789012:instance/i-0123456789abcdef0"
    }
  ]
}

As ações Describe geralmente requerem "Resource": "*" porque não suportam restrição por ARN específico — verifique o Service Authorization Reference da AWS para confirmar o suporte a resource-level permissions de cada ação antes de restringir.

Próximos Passos e Conclusão — EC2 SSH Connection Timeout

Se você seguiu todos os passos e o SSH ainda não conecta, o fluxo de diagnóstico abaixo resume a ordem de verificação recomendada:

graph TD Start["SSH timeout ao conectar na EC2"] --> Q1{"Instância tem IP público?"} Q1 -->|"Não"| Fix1["Associar EIP ou habilitar auto-assign"] Q1 -->|"Sim"| Q2{"Security Group tem regra TCP/22 para seu IP?"} Q2 -->|"Não"| Fix2["Adicionar regra inbound TCP/22"] Q2 -->|"Sim"| Q3{"Route table da subnet tem rota 0.0.0.0/0 para IGW?"} Q3 -->|"Não"| Fix3["Adicionar rota para Internet Gateway"] Q3 -->|"Sim"| Q4{"NACL permite TCP/22 inbound e portas efêmeras outbound?"} Q4 -->|"Não"| Fix4["Corrigir regras do Network ACL"] Q4 -->|"Sim"| Q5{"sshd rodando? iptables bloqueando?"} Q5 -->|"Problema no SO"| Fix5["Usar SSM Session Manager para acessar e corrigir"] Q5 -->|"Tudo OK"| Fix6["Verificar logs: /var/log/auth.log ou /var/log/secure"] style Fix1 fill:#5cb85c,color:#fff style Fix2 fill:#5cb85c,color:#fff style Fix3 fill:#5cb85c,color:#fff style Fix4 fill:#5cb85c,color:#fff style Fix5 fill:#5cb85c,color:#fff style Fix6 fill:#f0ad4e,color:#000

Para ambientes de produção, considere eliminar a dependência de SSH completamente usando o AWS Systems Manager Session Manager — sem porta 22 exposta, sem gerenciamento de chaves SSH, com log de sessão integrado ao CloudTrail. O EC2 Instance Connect é uma alternativa mais simples para acesso pontual sem abrir a porta 22 permanentemente no Security Group.

Documentação de referência: EC2 Security Groups | Network ACLs | Route Tables.

Glossário

TermoDefinição
Security GroupFirewall stateful no nível da instância EC2. Regras inbound permitem tráfego; retorno é automático.
Network ACL (NACL)Firewall stateless no nível da subnet. Regras inbound e outbound são avaliadas independentemente.
Internet Gateway (IGW)Componente da VPC que permite comunicação entre instâncias com IP público e a internet.
Portas EfêmerasRange de portas temporárias (1024-65535) usadas pelo cliente TCP para receber respostas do servidor.
Elastic IP (EIP)Endereço IPv4 público estático que pode ser associado a uma instância EC2 ou interface de rede.

Comentários

Postagens mais visitadas deste blog

EC2 Sem Acesso à Internet em VPC Customizada: Como Configurar Internet Gateway e Route Table

S3 Access Denied: Por que 'Bloquear Acesso Público' impede seu objeto mesmo após torná-lo público