Home / AWS

AWSTroubleshootingBeginner

Customer can't SSH to an EC2 instance: timeout vs refused vs permission denied

The error message tells you which layer is broken. Here's how to check each one, from security groups and route tables to sshd, keys and EC2 Instance Connect.

Deepak Bhardwaj3 min read

Applies toAmazon EC2 Linux instances, AWS CLI v2

Read the error

SSH says Layer Look at
Connection timed out Network: packets never arrive Security group, NACL, route table, public IP, local firewall
Connection refused Instance reached, nothing listening on 22 sshd stopped, wrong port, host firewall REJECT
Permission denied (publickey) sshd reached, auth failed Wrong key, wrong user name, file permissions
Host key verification failed The client's known_hosts has an old key IP was reused. Remove the old entry.

Timeout: walk the network path

ID=i-0abc123
aws ec2 describe-instances --instance-ids $ID \
  --query "Reservations[].Instances[].{state:State.Name,publicIp:PublicIpAddress,subnet:SubnetId,sgs:SecurityGroups[].GroupId}" --output table
  • The instance has a public IP (or you connect over VPN or Direct Connect to the private IP).
  • The security group allows TCP 22 from the customer's current public IP. Home IPs change.
    aws ec2 describe-security-groups --group-ids sg-0123 --query "SecurityGroups[].IpPermissions[?ToPort==\`22\`]"
    
  • The subnet's route table has 0.0.0.0/0 → igw-... for public access.
  • The network ACL allows inbound 22 and outbound ephemeral ports 1024–65535. NACLs are stateless, so the return traffic needs its own rule.
  • Reachability Analyzer can test the path from the IGW to the instance ENI on port 22, and names the blocking component.

Refused: the instance side

Use a channel that doesn't need SSH:

aws ssm start-session --target $ID                     # if the SSM agent and role are in place
aws ec2-instance-connect send-serial-console-ssh-public-key --instance-id $ID --serial-port 0 --ssh-public-key file://~/.ssh/id_ed25519.pub

Then check:

sudo systemctl status sshd
sudo ss -ltnp | grep ':22'
sudo journalctl -u sshd --since "1 hour ago" | tail -30
sudo sshd -t            # validates sshd_config syntax

A typo in sshd_config is a common cause after hardening scripts run.

Permission denied

  • Use the default user for the AMI: ec2-user (Amazon Linux, RHEL), ubuntu (Ubuntu), admin (Debian), centos, or rocky.
  • Make sure the key file is private: chmod 400 key.pem.
  • Confirm the key pair matches the instance:
    aws ec2 describe-instances --instance-ids $ID --query "Reservations[].Instances[].KeyName"
    
  • Push a temporary key with EC2 Instance Connect (valid for 60 seconds):
    aws ec2-instance-connect send-ssh-public-key --instance-id $ID --instance-os-user ec2-user --ssh-public-key file://~/.ssh/id_ed25519.pub
    

Lost key: recovery

  1. Use SSM Session Manager or the serial console to add a new key to ~/.ssh/authorized_keys.
  2. Without those, run AWSSupport-ResetAccess automation, or detach the root volume, attach it to a rescue instance, edit authorized_keys, and reattach (see the EC2 status check runbook).

Tip

Make Session Manager the default access path: no inbound port 22 and no keys to lose, with every session logged.