Secure SSH Access for AWS EC2: From Keys to Production Hardening

SSH security is foundational to your infrastructure. Passwords are risky; public-key authentication is the standard. This guide covers the essentials for managing keys, onboarding developers safely, and hardening SSH on an EC2 instance, plus architectural defenses for production.

Part 1: The Foundation — Understanding Your .pem Key

What AWS Gives You

When you launch an EC2 instance with a key pair, you download a .pem file. This is your private key. AWS injects the matching public key into the instance’s default user account at boot.

Key Analogy

  • Public key = the lock. Safe to share; installed on the server in authorized_keys.
  • Private key (.pem) = the key. Secret. Never share, email, or upload publicly.

How Authentication Works

Your SSH client proves possession of the private key via a cryptographic challenge without sending the key over the network.

Golden Rule

Treat your .pem like a root-level secret. Restrict file permissions locally (chmod 400 your-key.pem) and never store it in public places.

Part 2: Securely Verifying Your Keys

Never paste private keys into online tools. Use local utilities.

Derive the public key from a .pem private key

ssh-keygen -y -f /path/to/your-key.pem

The output begins with ssh-rsa or ssh-ed25519 and should match what’s on the instance in the default user’s ~/.ssh/authorized_keys.

Non-EC2 generic Linux VM login setup

Generate a key pair if you don’t have one:

ssh-keygen -t ed25519 -C "Ali's Key"

Note: Prefer ed25519 for modern security and smaller keys. If needed, RSA 4096 is acceptable:

ssh-keygen -t rsa -b 4096 -C "Ali's Key"

Copy your public key to the server:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@serverIP

If ssh-copy-id isn’t available:

ssh user@serverIP "mkdir -p ~/.ssh && chmod 700 ~/.ssh"
cat ~/.ssh/id_ed25519.pub | ssh user@serverIP "cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Log in:

ssh user@serverIP

Part 3: Onboarding a Developer — One User, One Key

Step 1: Developer generates their key pair

ssh-keygen -t ed25519

The developer keeps their private key private and sends only the public key (id_ed25519.pub).

Step 2: Admin creates a dedicated Unix user on the EC2 instance

sudo adduser Ali

On Amazon Linux 2/2023 and Ubuntu, this creates the user and home directory.

Step 3: Install the developer’s public key with correct permissions

sudo su - Ali
mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
echo "ssh-ed25519 AAAA...developer-public-key" >> ~/.ssh/authorized_keys
exit

Developer connects using their private key and username

ssh -i /path/to/private_key Ali@EC2_PUBLIC_IP

Note: The -i flag points to the private key (not the public key). Ensure file permission is restricted, e.g., chmod 600 /path/to/private_key.

Why not reuse ec2-user?

Using unique users provides accountability and easy revocation. The default ec2-user commonly has passwordless sudo for automation.

Cloud-init sudoers snippet

View the file that grants ec2-user passwordless sudo:

sudo cat /etc/sudoers.d/90-cloud-init-users

Typical content:

ec2-user ALL=(ALL) NOPASSWD:ALL

This modular drop-in is managed by cloud-init, which keeps system sudoers intact while enabling automation.

Part 4: Hardening SSH for Production (/etc/ssh/sshd_config)

Edit the daemon config, then restart SSH to apply. Always keep an active session while testing changes so you don’t lock yourself out.

Disable password authentication

PasswordAuthentication no

Disable root login

PermitRootLogin no

Change the default port to reduce noise

Port 2222

Remember to update the EC2 Security Group to allow the new port and remove 22 if no longer used.

Limit who can SSH

AllowUsers Ali ec2-user

Or by group:

AllowGroups ssh_users

Set idle timeout

ClientAliveInterval 900
ClientAliveCountMax 5

Disable X forwarding

X11Forwarding no

Optional but recommended

PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
MaxSessions 10
LoginGraceTime 30

KexAlgorithms, Ciphers, MACs: use modern defaults unless you need legacy compatibility. On modern distros, defaults are already strong.

Apply changes safely

sudo systemctl reload sshd

If reload fails, use:

sudo systemctl restart sshd

Architectural and External Security Layers

Bastion host (jump box)

Keep app and DB servers private. Expose only a hardened bastion in a public subnet. Use ProxyJump for convenience:

ssh -J ec2-user@bastion_ip Ali@private_instance_ip

Rate limiting with fail2ban

Protects against brute-force attempts by banning offending IPs based on log patterns.

  • Install fail2ban
  • Enable sshd jail
  • Tune bantime, findtime, maxretry

Security groups and network ACLs

Restrict SSH to trusted CIDRs (office, VPN). Avoid 0.0.0.0/0 to the extent possible. Consider AWS Network Firewall or third-party WAF/VPN solutions for layered protection.

AWS Systems Manager Session Manager (portless access)

Eliminate inbound SSH entirely.

  • How it works: SSM Agent initiates an outbound connection; sessions tunnel via AWS.
  • Benefits: No open ports, IAM-controlled access, session logging to CloudWatch or S3, strong auditing.
  • Requirements: SSM Agent installed, IAM role with SSM permissions, VPC endpoints recommended for private subnets.

Operational Best Practices

  • Keep an emergency break-glass path: either a bastion or SSM access with a tested runbook.
  • Rotate and revoke keys promptly: Remove user entries from authorized_keys and, if needed, disable or delete the user.
  • Enforce local key protection: passphrase-protect private keys, use ssh-agent, and set strict file permissions.
  • Use IAM and SSO for SSM access: For SSH, consider short-lived certs via SSH CA (e.g., Smallstep, HashiCorp Vault, or AWS Certificate Manager for SSH via IAM roles) for scalable ephemeral access.
  • Monitor auth logs: Amazon Linux/Ubuntu typically at /var/log/secure or /var/log/auth.log. Ship to CloudWatch or a SIEM.
  • Backup and test your sshd_config rollback plan: Keep the current session open; verify a second session before closing the original.
Ali Alrahbe
Ali Alrahbe

Hi, 👋 I'm Ali Alrahbe, a cybersecurity professional passionate about building cloud infrastructures that are both secure and resilient.

I got my start in tech on the front lines of IT support. That experience didn't just teach me how to solve complex problems—it showed me that proactive security is the bedrock of any successful digital system. That realization drove me to specialize in cloud security.
I'm AWS Certified Solutions Architect Associate, I hold a Bachelor's degree in computer systems engineering and currently pursuing a Master's in Cybersecurity in Berlin, focusing on Cloud Security, DevSecOps, and Infrastructure as Code (IaC).

On my website, Corefortify.com, I document my journey, share hands-on projects, and break down complex security concepts in the evolving world of cloud technology.

Feel free to connect with me on LinkedIn!

Articles: 14