Ssh To Ec2 Instance

Ssh To Ec2 Instance

Reading time1 min
#Cloud#Security#AWS#EC2#SSH#DevOps

Mastering Secure SSH Access to EC2 Instances: Beyond the Basics

SSH remains the default entry point to most AWS EC2 Linux workloads. That makes SSH not just a convenience, but the primary security boundary between public networks and your infrastructure. Far too often, security on EC2 comes down to “just set a key pair and open port 22,” which exposes operations to avoidable risk—especially at scale or under active threat models.

This guide covers how experienced operators lock down SSH, blending AWS-native controls, modern Linux best practices, and operational patterns that survive real-world audits.


Threat Model: Why SSH to EC2 is a Priority Target

Default EC2 SSH access patterns are a case study in “works by default, insecure by default.” Direct exposure of port 22 to the internet or using weak keys can quickly turn one mistake into an incident. Even a small lapse in credential management (stale key, old IAM account, open security group) is enough.

Key objectives:

ObjectiveAttack Prevented
Narrow SSH ingress (security group)Opportunistic scanning/bruteforce
Key-only auth, no passwordsCredential stuffing
Disable root loginPrivilege escalation
Session loggingSilent breaches
Rotate/revoke access efficientlyInsider threats, leaky keys

1. Security Groups & Network Access Control

There’s no reason to allow 0.0.0.0/0 on port 22. Either restrict SSH access to office/VPN CIDRs or, better, use temporary access per-session via AWS SSM Session Manager.

Example: Harden a security group from day zero.

aws ec2 revoke-security-group-ingress \
  --group-id sg-xxxxxxx \
  --protocol tcp \
  --port 22 \
  --cidr 0.0.0.0/0

aws ec2 authorize-security-group-ingress \
  --group-id sg-xxxxxxx \
  --protocol tcp \
  --port 22 \
  --cidr 203.0.113.42/32

Note: That /32 locks access to a single IP. With remote teams, control ingress via an IPsec VPN or AWS VPN endpoint.

Side note: Some users proxy SSH through AWS Client VPN or OpenVPN bastions; trade-off is added latency and operational overhead.


2. Bastion Host Pattern (or skip SSH, use SSM)

Bastions (jump hosts) box SSH entry to a hardened EC2 instance, usually with extra monitoring and locked-down IAM access. All internal EC2 nodes only allow SSH from the bastion’s private IP.

Diagram:

[User Workstation] --> [Bastion:22] --> [Private EC2:22]
                         ^
         SSH keys, MFA, IPS, Logging

Alternatives (preferred):
AWS Systems Manager Session Manager. Removes the SSH port surface area entirely. SSM can use IAM, audit all sessions, and works over HTTPS, sidestepping outbound firewall rules.

Gotcha: SSM needs the AmazonSSMManagedInstanceCore role on targets, plus agent installed and running; otherwise, fallback to bastion pattern.


3. SSH Key Management: Strength, Storage, and Rotation

  • Disable password logins post-provisioning.
  • Use minimum 2048-bit RSA or Ed25519 keys (ssh-keygen -t ed25519 -a 100 …).
  • Store private keys in secure storage: YubiKey (PKCS11), HashiCorp Vault, or encrypted disk.
  • Avoid reusing keys across environments; track key lifetimes.
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/aws-ec2-prod

Inject public keys using launch templates, or push to ~/.ssh/authorized_keys via user data (cloud-init).

Disable password authentication and root login:

# /etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin no
ChallengeResponseAuthentication no
sudo systemctl reload sshd  # Or 'restart' if necessary

Practical issue: AWS EC2 injects ssh keys only for the default user (ec2-user, ubuntu, etc). Custom AMIs may behave differently.


4. Harden the SSH Daemon

Non-defaults that actually reduce attack viability:

  • Port 2222 or randomized: Obscures but does not protect; only marginally helpful under high scan noise.
  • AllowUsers ec2-user devopsadmin - restricts accounts.
  • LoginGraceTime 20, MaxAuthTries 3 - slows brute force.
  • PermitRootLogin no (already set above).
  • AllowTcpForwarding no; X11Forwarding no unless required.
  • LogLevel VERBOSE - more actionable login logs.

Config example:

# /etc/ssh/sshd_config
Port 2222
AllowUsers ec2-user devopsuser
LoginGraceTime 20
MaxAuthTries 3
PermitRootLogin no
LogLevel VERBOSE
AllowTcpForwarding no
X11Forwarding no

Known issue: Changing SSH port regularly triggers alert fatigue (“why can’t I log in?”). Standardize requirements at team level.


5. SSH Certificate-Based Authentication (for scale or high security)

Managing piles of SSH keys across hundreds of devs and CI/CD systems quickly gets out of hand. Solution: short-lived, signed SSH certificates backed by a trusted CA.

Workflow:

  • Create an SSH CA key; keep private portion offline.
  • Developers generate their own SSH keys; org operators sign them (via ssh-keygen -s ...) with expiration and role info.
  • Place CA public key on all EC2 sshd_config:
    TrustedUserCAKeys /etc/ssh/ca_user.pub
  • Only signed keys are accepted—grant, rotate, and revoke via cert lifecycle, not file distribution.

Example:

ssh-keygen -f ca_user -C "Org SSH CA"
ssh-keygen -s ca_user -I ops1-jdoe -n ec2-user -V +1d jdoe.pub
  • Rotate certificates on schedule (e.g., 24h).
  • Rapid revocation: Remove CA pubkey, or expire user cert.

Non-obvious pain: CA key management is critical. If it leaks, anyone can issue certs.


6. Multi-Factor SSH Authentication

SSH with MFA is feasible but painful in heterogeneous Linux environments. Typical implementation: PAM Google Authenticator, Duo, or hardware tokens (Yubikey in OTP mode).

Install the google-authenticator PAM module (tested on Amazon Linux 2):

sudo yum install -y google-authenticator
sudo -u ec2-user google-authenticator

Edit /etc/pam.d/sshd:

auth required pam_google_authenticator.so nullok

Adjust /etc/ssh/sshd_config:

ChallengeResponseAuthentication yes

Not perfect: Many SSH clients cache agent responses, bypassing challenge step unless configured properly. Test thoroughly, especially for automation/batch jobs.


7. Logging, Monitoring, and Audit

  • Set LogLevel VERBOSE in sshd to log key identity and attempted logins.
  • Forward auth logs /var/log/secure (CentOS/AL2) or /var/log/auth.log (Ubuntu) to CloudWatch, ELK, or SIEM for centralized analysis.
  • Use fail2ban or similar tools for basic intrusion response:
sudo yum install -y fail2ban
sudo systemctl enable --now fail2ban

Default config blocks common brute-force vectors. Tune jail parameters as needed.

Cloud-native note: Use AWS CloudTrail alongside SSM to log session connections for all managed nodes.


8. Automating Secure SSH on Provision: User Data Example

Automate SSH hardening at boot with user-data. Useful for short-lived or spot instances:

#!/bin/bash
# Only accept key auth, no root login.
sed -i '/^PasswordAuthentication/d' /etc/ssh/sshd_config
echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config
sed -i '/^PermitRootLogin/d' /etc/ssh/sshd_config
echo 'PermitRootLogin no' >> /etc/ssh/sshd_config

# Insert deployer key (rotate as needed)
install -d -m 700 /home/ec2-user/.ssh
echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...' > /home/ec2-user/.ssh/authorized_keys
chown -R ec2-user:ec2-user /home/ec2-user/.ssh
chmod 600 /home/ec2-user/.ssh/authorized_keys

systemctl reload sshd

Note: For more robust automation, move to Ansible, SSM RunCommand, or bake configs into AMIs.


Securing SSH into EC2 instances means prioritizing defense in depth—not just keeping port 22 closed, but also hardening at the daemon, network, identity, and audit layers. Adopt key/cert rotation and disable passwords on day one. SSM Session Manager is mature enough to replace most direct SSH use cases and simplifies controls and compliance.

Not every pattern will fit every environment, but even partial adoption significantly reduces risk.
For Terraform or CloudFormation templates automating these patterns, review the AWS examples—or refactor for your CI/CD context.

Gotchas discovered late are expensive. Assume every open port or stale key will be exploited—eventually, one will.