4.2
Security Groups in Practice, SSH and Session Manager
Classic ports, a WordPress rule set, SSH and Instance Connect, and keyless access with Session Manager.
24 min Reading + animations
Tip: tap or hover any dotted-underlined term to see what it means.
By the end of this lesson you will be able to
- Set up security groups for a real instance: the right ports, the right sources, and a separate group for admin access.
- Recognise the classic ports on sight, including the database and file-sharing ports the exam uses.
- Create and protect a key pair, and SSH into a Linux instance from Linux, Mac or Windows.
- Read an SSH failure and know where to look: timeout, connection refused, permission denied, key file too open, host key changed.
- Choose between direct SSH, a bastion, EC2 Instance Connect, the Instance Connect Endpoint and Session Manager.
- Give applications on EC2 access to AWS with an IAM role instead of access keys, and reach Windows instances over RDP or without it.
#From theory to a running instance
Lesson 3.5 explained how security groups work: allow rules only, stateful, attached to network interfaces, able to reference other groups. Lesson 3.4 showed bastion hosts and introduced Session Manager. This lesson is the hands-on side: you have just launched an instance, and now you need to let the right traffic in, log in to it, and keep everyone else out.
There are two different questions, and beginners often mix them up:
- Who can reach the instance over the network? That is the security group (plus the network ACL, routes and a public IP).
- Who can log in once they reach it? That is the key pair for SSH, the Windows password for RDP, or IAM for Instance Connect and Session Manager.
A login needs both. Most “I can’t connect” problems are solved by working out which of the two failed.
#Security groups on a real instance
When you launch an instance, the console asks for a security group. A few habits make life easier:
- One group per purpose. For example
sg-web(80 and 443 from anywhere) andsg-admin(22 only from your office). An instance can carry up to 5 groups per network interface, and their rules are combined. To cut off admin access everywhere, you detach or emptysg-adminwithout touching the web rules. - Use “My IP” carefully. The console can fill in your current address as a
/32. Home connections often get a new public address after a router restart, so yesterday’s rule may stop matching today. Offices with fixed addresses can be grouped into a managed prefix list and referenced from every group. - Changes are live. Editing a rule or attaching a group affects a running instance at once; no restart.
- Outbound is open by default. A new group allows all outbound traffic. Tighten it only if you know every destination the instance needs (updates, APIs, Systems Manager).
#Ports you must know
| Port | Protocol | Used for |
|---|---|---|
| 21 | FTP | Plain file transfer, no encryption |
| 22 | SSH | Log in to a Linux instance |
| 22 | SFTP | File transfer that runs inside SSH, on the same port |
| 80 | HTTP | Unencrypted websites |
| 443 | HTTPS | Encrypted websites and APIs |
| 3389 | RDP | Remote Desktop to a Windows instance |
| 3306 | MySQL, MariaDB, Aurora MySQL | Database connections |
| 5432 | PostgreSQL, Aurora PostgreSQL | Database connections |
| 1433 | Microsoft SQL Server | Database connections |
| 1521 | Oracle | Database connections |
| 2049 | NFS | Shared Linux file systems |
| 445 | SMB | Shared Windows file systems |
On the exam, the port is often the whole question: “cannot log in to a Linux instance” → check port 22 in the security group; “cannot log in to a Windows instance” → port 3389.
#A WordPress rule set
A small business runs WordPress on one instance. Visitors can be anywhere; only the owner maintains the server.
| Type | Port | Source | Why |
|---|---|---|---|
| HTTP | 80 | 0.0.0.0/0 | Visitors, and the redirect to HTTPS |
| HTTPS | 443 | 0.0.0.0/0 | Visitors |
| SSH | 22 | 203.0.113.25/32 | Only the owner’s office address |
0.0.0.0/0 means any IPv4 address in the world; /32 means exactly one address. Two variations matter:
- MySQL on the same instance: WordPress talks to it over
localhost, so port 3306 is not opened at all. - MySQL on a separate database server: that server’s group allows 3306 from the WordPress server’s security group, never from
0.0.0.0/0.
Better still, drop the SSH rule entirely and use Session Manager (below): then the server has only 80 and 443 open.
#Key pairs
Linux instances on AWS do not use passwords for SSH. They use a key pair:
- the public key is placed on the instance, in the default user’s
~/.ssh/authorized_keys, by cloud-init at first boot; - the private key stays with you, in a file on your laptop.
When you log in, ssh proves that you hold the private key by signing a challenge with it; the instance checks the signature against the public key. The private key itself never crosses the network.
What you need to know about EC2 key pairs:
| Fact | Detail |
|---|---|
| AWS keeps only the public key | When AWS creates the pair, you download the private key once. It cannot be downloaded again. |
| Two key types | RSA and Ed25519. Ed25519 is not supported for Windows instances (the Windows password is encrypted with RSA). |
| Two file formats | .pem for OpenSSH (Linux, Mac, Windows 10 and later) and .ppk for PuTTY. You choose the format when you create the pair; PuTTYgen converts between them. |
| Regional | A key pair exists in one Region. To use it elsewhere, import the same public key there. |
| Bring your own | You can generate a key pair yourself and import just the public key; the private key then never touches AWS. |
| Set at launch | The key pair is chosen when the instance is launched. Changing it later means editing authorized_keys on the instance. |
#Protect the file: chmod 400
ssh refuses to use a private key that other users on your computer can read. If the file is too open, you see a warning that the private key file is unprotected, and the login fails. Fix it once:
chmod 400 my-key.pem # Linux and Mac: read-only, for you only
On Windows, remove inherited permissions so only your account can read the file (in the file’s Properties → Security → Advanced, or with icacls).
#Losing the private key
AWS cannot give it back. For a Linux instance with an EBS root volume, the usual ways back in are:
- Session Manager or EC2 Instance Connect, if they were already working: log in and add a new public key to
authorized_keys; - stop the instance, detach its root volume, attach it to a helper instance, add a new public key to the file, then put the volume back and start the instance.
#SSH from Linux, Mac and Windows
| Your computer | Tool | Key format |
|---|---|---|
| Linux, Mac | ssh in the terminal (OpenSSH) | .pem |
| Windows 10 and later | ssh in PowerShell or the terminal (OpenSSH is built in) | .pem |
| Older Windows, or if you prefer it | PuTTY | .ppk (convert with PuTTYgen) |
| Any | EC2 Instance Connect in the browser | No key file needed |
The command is the same everywhere OpenSSH runs:
ssh -i my-key.pem ec2-user@198.51.100.10
Three parts: the private key (-i), the user name, and the instance’s public IP or DNS name. The user name depends on the image:
| Image | Default user |
|---|---|
| Amazon Linux 2023, Amazon Linux 2 | ec2-user |
| Ubuntu | ubuntu |
| Debian | admin |
| RHEL | ec2-user |
The first time you connect, ssh shows the server’s host key fingerprint and asks whether to trust it. Your answer is stored in ~/.ssh/known_hosts, so next time ssh can tell if a different machine is answering on that address.
SSH into an instance, and the errors that tell you why not
ssh -i key.pem ec2-user@198.51.100.10. The security group allows SSH only from 203.0.113.25/32. Pick a scenario and read where it stops.
Scenario
The private key was downloaded once, when the key pair was created. chmod 400 makes it readable only by you; ssh refuses a private key that other users could read.
#When SSH fails: read the error
Each message points at a different layer. Lesson 3.5 explained why timeouts mean a firewall and refusals mean the application; here is the full checklist for SSH.
| What you see | What it means | Where to look |
|---|---|---|
| Connection timed out | Nothing answered: the packets were dropped on the way | Security group (is your current IP allowed on 22?), network ACL, a public IP on the instance, a route to the internet gateway, your own office firewall blocking outbound 22 |
| Connection refused | The instance answered “nothing is listening on this port” | sshd stopped or crashed, the instance is still booting, sshd moved to another port |
| Permission denied (publickey) | The network is fine; the login failed | Wrong user name for the image, or the private key of a different key pair |
| Unprotected private key file | Your client refused to use the key | chmod 400 the key file |
| Remote host identification has changed | A different machine now answers on this address | Expected after you launch a new instance behind the same Elastic IP: remove the old entry with ssh-keygen -R <address> |
Self-checkQuestion
You run ssh -i key.pem ec2-user@198.51.100.10 and, after a long wait, see ‘Connection timed out’. Which check comes first?
#EC2 Instance Connect
EC2 Instance Connect lets you open an SSH session without keeping a key file. You click Connect in the console (a terminal opens in the browser) or use the CLI. Behind the scenes:
- IAM checks that you may push a key to this instance for this OS user (
ec2-instance-connect:SendSSHPublicKey). - The service pushes a temporary public key into the instance metadata. It is valid for 60 seconds, just long enough to log in.
- A normal SSH connection on port 22 is made. The
ec2-instance-connectpackage on the instance lets sshd accept the temporary key.
What it requires:
- a supported image: the package comes pre-installed on Amazon Linux 2023, Amazon Linux 2 and Ubuntu 20.04 and later; other Linux images need it installed;
- port 22 open in the security group. For the browser method, the connection comes from the EC2 Instance Connect service’s address range for that Region, not from your laptop, so allow it with the managed prefix list
com.amazonaws.<region>.ec2-instance-connect; - a public IP for the browser method (for private instances, use the endpoint below).
From the CLI, Instance Connect can push a key from your own computer, and your SSH then comes from your own address:
aws ec2-instance-connect ssh --instance-id i-0123456789abcdef0
#EC2 Instance Connect Endpoint: SSH and RDP to private instances
An EC2 Instance Connect Endpoint is an endpoint you create in a subnet of your VPC. AWS tunnels your connection from the console or CLI, through the endpoint, to an instance’s private IP:
- no public IP, no internet gateway, no bastion host on the path;
- IAM decides who may open a tunnel (
ec2-instance-connect:OpenTunnel), and every tunnel is recorded in CloudTrail; - it carries SSH (22) and RDP (3389); each tunnel lasts at most one hour;
- there is no extra charge for the endpoint;
- you still log in with a key, your own or a temporary one pushed by Instance Connect.
The endpoint is the client of your instances, so the security groups follow from that: the instance allows 22 (or 3389) from the endpoint’s security group, and the endpoint is allowed to send that port to the instances.
EC2 Instance Connect: a temporary key, but still SSH
A public web server and a private app server. The browser path needs port 22 open to the service’s address range; the endpoint path reaches private instances.
Scenario
Web server SG: SSH 22 from the EC2 Instance Connect prefix list.
The admin clicks Connect in the console. IAM checks that this user may push a key to this instance for this OS user. No .pem file is involved.
#Session Manager
AWS Systems Manager Session Manager gives you a shell on an instance with no inbound port at all. Lesson 3.4 introduced it as the modern replacement for a bastion; here is what makes it work.
- The SSM Agent runs on the instance. It is pre-installed on Amazon Linux 2023, Amazon Linux 2, Ubuntu and the Windows Server images AWS publishes.
- The instance has permission to talk to Systems Manager: usually an IAM role (instance profile) with the
AmazonSSMManagedInstanceCoremanaged policy. Alternatively, Default Host Management Configuration grants it to every instance in the account and Region. - The agent has a path out on HTTPS 443: to the internet through a NAT gateway or internet gateway, or privately through interface VPC endpoints for
ssm,ssmmessagesandec2messages. That is the safe set; since SSM Agent 3.3.40.0 the agent usesssmmessagesinstead ofec2messageswhen its permissions allow it, sossmandssmmessagesare the two it cannot do without (lesson 25.3). - You have IAM permission to start a session on that instance (
ssm:StartSession), and open it from the console or withaws ssm start-session(the CLI needs the Session Manager plugin).
The agent keeps an outbound connection to Systems Manager, and your session travels down it. The instance’s security group needs no inbound rules, and there is no SSH key to create, share or lose.
What else Session Manager gives you:
- Logging. Session output can be streamed to CloudWatch Logs and stored in an S3 bucket, and sessions can be encrypted with your own key in AWS Key Management Service.
- Fine-grained access. IAM policies can limit sessions to instances with certain tags, for example
env=dev. - Port forwarding. Reach a port on the instance (or a database behind it) from your laptop, still without opening anything inbound.
- SSH and file copies (scp) through it, for tools that expect SSH, still with no port 22 open.
- Windows too: PowerShell sessions, and graphical RDP in the browser through Fleet Manager.
- No extra cost for EC2 instances.
Session Manager: the instance calls out, you never call in
A private instance with no public IP and no inbound security group rules. The SSM Agent keeps an outbound channel to Systems Manager.
Scenario
At boot, the SSM Agent uses the instance role’s credentials to register with Systems Manager. It connects outbound on HTTPS 443 through the interface VPC endpoints; the default outbound security group rule allows it.
#Comparing the ways in
| SSH direct | Bastion host | Instance Connect (browser) | Instance Connect Endpoint | Session Manager | |
|---|---|---|---|---|---|
| Inbound port on the instance | 22 from your IP | 22 from the bastion’s SG | 22 from the service’s range | 22 or 3389 from the endpoint’s SG | None |
| Instance needs a public IP | Yes | No (the bastion does) | Yes | No | No |
| Long-lived SSH key | Yes | Yes | No (60-second key) | Your own or a pushed one | No |
| Who controls access | Whoever has the key | Key + bastion rules | IAM | IAM | IAM, per instance and tag |
| Audit | sshd logs on the instance | Bastion logs | CloudTrail (key pushes) | CloudTrail (tunnels) | CloudTrail + full session logs in S3 / CloudWatch Logs |
| Extra servers to run | None | The bastion | None | None (free endpoint) | None |
| Needs on the instance | sshd | sshd | sshd + Instance Connect package | sshd (or RDP) | SSM Agent + instance permissions + path to the service |
Self-checkQuestion
Security policy forbids any inbound rule on the application servers and any shared SSH key. Administrators still need an interactive shell, and every command must be logged. What should you use?
#Never put access keys on an instance
Sooner or later an application on your instance needs AWS itself: reading from S3, writing to a queue, querying DynamoDB. The tempting shortcut is to run aws configure on the instance and paste in an access key. Never do this. The keys:
- are long-lived: they work from any computer in the world until someone deactivates them;
- travel with the disk: into images, snapshots, backups and, by mistake, code repositories;
- usually carry far more permissions than the application needs;
- must be rotated by hand on every instance.
Instead, attach an IAM role to the instance (through an instance profile):
- The AWS CLI and the AWS software libraries on the instance find the role’s temporary credentials automatically, through the instance metadata (lesson 4.3 covers how to read metadata safely).
- AWS rotates them automatically, hours before they expire. Nothing secret is stored on the disk.
- The role’s policy gives the application exactly what it needs, for example “read this one bucket”.
- An instance has one role at a time. You can attach, replace or remove it on a running instance, with no restart.
Give the instance a role, never your access keys
An application on EC2 must read files from an S3 bucket. Compare a role with long-term keys stored on the disk.
Scenario
The instance was given an IAM role (through an instance profile) that may only read this one bucket. Nothing secret is written to the disk.
#Windows instances: the RDP path
Windows instances are administered with Remote Desktop (RDP, port 3389) and a user name and password, not an SSH key.
- Allow 3389 in the security group, only from your address (never
0.0.0.0/0). - Wait a few minutes after launch, then choose Get Windows password in the console. At first boot, Windows generated a random Administrator password and encrypted it with your key pair’s public key; you provide the private key (
.pem) to decrypt it. This is why Windows needs an RSA key pair. - Open your RDP client (Remote Desktop Connection on Windows, Windows App on Mac), connect to the public IP, and log in as Administrator with that password.
Ways in without opening 3389 to the internet:
- Fleet Manager Remote Desktop (part of Systems Manager): a graphical RDP session in the browser, carried by Session Manager.
- Session Manager for a PowerShell session.
- EC2 Instance Connect Endpoint for RDP to a private instance.
#How it is used in design
A production setup usually looks like this:
- No SSH from the internet. Application servers sit in private subnets; their security groups allow only the load balancer on the application port. Port 22 is not open anywhere.
- Session Manager for people, through VPC endpoints so even management traffic stays off the internet, with session logs to an S3 bucket that has a retention policy, and IAM rules by tag (developers on
env=dev, a small group on production). - IAM roles for software. Every instance gets a role with just the permissions its application needs. No access keys anywhere.
- Fewer logins at all. Instances are built from images and configured automatically (lesson 4.3), so nobody needs to log in to fix things by hand; a broken instance is replaced, not repaired.
- A break-glass path. Keep one documented emergency route, for example an Instance Connect Endpoint, with tight IAM permissions and alerts on every use.
#Try it yourself
# 1. Create a key pair and protect the private key
aws ec2 create-key-pair --key-name lab-key --key-type ed25519 \
--query KeyMaterial --output text > lab-key.pem
chmod 400 lab-key.pem
# 2. An admin security group: SSH only from your current address
MYIP=$(curl -s https://checkip.amazonaws.com)
ADMIN=$(aws ec2 create-security-group --group-name admin --description "SSH from my IP" \
--vpc-id $VPC --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id $ADMIN --protocol tcp --port 22 --cidr $MYIP/32
# 3. Log in (debug output shows TCP, host key and authentication stages)
ssh -v -i lab-key.pem ec2-user@198.51.100.10
# Optional: a shortcut in ~/.ssh/config, then just "ssh lab"
# Host lab
# HostName 198.51.100.10
# User ec2-user
# IdentityFile ~/lab-key.pem
# 4. EC2 Instance Connect: push a temporary key and connect (no key file)
aws ec2-instance-connect ssh --instance-id i-0123456789abcdef0
# 5. Instance Connect Endpoint for a private instance
aws ec2 create-instance-connect-endpoint --subnet-id $PRIVATE_SUBNET --security-group-ids $EICE_SG
aws ec2-instance-connect ssh --instance-id i-0abcdef1234567890 --connection-type eice
# 6. Session Manager: give the instance a role, then open a shell (needs the Session Manager plugin)
aws ec2 associate-iam-instance-profile --instance-id i-0abcdef1234567890 \
--iam-instance-profile Name=ssm-core-profile
aws ssm describe-instance-information --query "InstanceInformationList[].InstanceId"
aws ssm start-session --target i-0abcdef1234567890
# 7. Close SSH entirely once Session Manager works
aws ec2 revoke-security-group-ingress --group-id $ADMIN --protocol tcp --port 22 --cidr $MYIP/32
#Summary
Key takeaways
- Reaching an instance (security group, NACL, public IP, route) and logging in (key, password, IAM) are separate checks; a login needs both.
- Keep admin access in its own security group, open 22 or 3389 only from known addresses, and never from
0.0.0.0/0. Watch for home IPs that change. - Ports: 21 FTP, 22 SSH and SFTP, 80 HTTP, 443 HTTPS, 3389 RDP, 3306 MySQL/Aurora, 5432 PostgreSQL, 1433 SQL Server, 1521 Oracle, 2049 NFS, 445 SMB.
- AWS keeps only the public key; the private key is downloaded once.
.pemfor OpenSSH (including Windows 10+),.ppkfor PuTTY. chmod 400 the file. Default user:ec2-useron Amazon Linux,ubuntuon Ubuntu. - Timeout → network path (often your IP changed). Refused → sshd not listening. Permission denied → wrong user or wrong key.
- Instance Connect pushes a 60-second key through IAM but still needs port 22 (from the service’s range). The Instance Connect Endpoint reaches private instances over SSH or RDP without public IPs or a bastion.
- Session Manager: SSM Agent + instance permissions + an outbound path (NAT or VPC endpoints) + IAM for users. No inbound port, no keys, sessions logged to S3/CloudWatch Logs (CloudTrail only records who started them).
- Applications on EC2 use an IAM role, never access keys stored on the instance.
- Windows: RDP on 3389, password decrypted with the key pair’s private key; Fleet Manager gives RDP without opening 3389.
Answer on your own first, then read the explanation, even when you got it right.
Self-checkQuestion
You launched an instance from the Amazon Linux 2023 image. Which user name do you use with ssh?
Self-checkQuestion
You let AWS create a new key pair in the console. What does AWS keep?
Self-checkQuestion
A partner must upload files securely to a Linux instance whose security group allows only SSH. Which port does SFTP use?
Self-checkQuestion
Which two port and service pairs are correct defaults?
Choose 2
Self-checkQuestion
An application server must connect to a Microsoft SQL Server database on another instance. Which port should the database’s security group allow from the application server’s security group?
Self-checkQuestion
ssh prints a warning that your private key file is unprotected and its permissions are too open, then fails. What fixes it?
Self-checkQuestion
ssh reaches the instance, the host key is shown, and then the login fails with ‘Permission denied (publickey)’. Which two causes fit?
Choose 2
Self-checkQuestion
An SSH attempt fails immediately with ‘Connection refused’. What is the most likely cause?
Self-checkQuestion
Yesterday you could SSH to your instance from home. Today ssh waits and then reports a timeout. Nobody changed anything in AWS. What is the most likely cause?
Self-checkQuestion
A new instance runs in a public subnet with a route to the internet gateway. Its security group allows port 22 from your IP, but SSH to the instance times out, and the console shows no public IPv4 address for it. What is wrong?
Self-checkQuestion
You terminated an instance and launched a new one behind the same Elastic IP. ssh now warns that the remote host identification has changed and refuses to connect. What should you do?
Self-checkQuestion
Which statement about EC2 Instance Connect (the browser method) is NOT true?
Self-checkQuestion
EC2 Instance Connect from the console fails for an instance whose security group allows SSH only from the office address 203.0.113.25/32. What fixes it with the least access?
Self-checkQuestion
Engineers need SSH to instances in private subnets. The instances have no public IPs, there must be no bastion host, access must be controlled with IAM, and the engineers want to keep using their normal SSH client. What should you use?
Self-checkQuestion
You created an EC2 Instance Connect Endpoint, but SSH to a private instance through it fails. The instance’s security group allows port 22 only from the administrators’ home addresses. What should the inbound rule allow instead?
Self-checkQuestion
Which two are required on the instance side for Session Manager to work?
Choose 2
Self-checkQuestion
An instance in a private subnet has the SSM Agent and a correct instance role, but it never appears in Session Manager. The subnet has no NAT gateway. What is the most likely fix?
Self-checkQuestion
A company must not open any inbound ports or distribute SSH keys, and every command administrators type on instances must be kept for audit. Which solution meets all three?
Self-checkQuestion
Where can you find the commands an administrator typed during a Session Manager session?
Self-checkQuestion
A developer’s Session Manager request to a production instance is denied, although the instance is online and other administrators can connect to it. What is the most likely reason?
Self-checkQuestion
An application on EC2 must read and write items in a DynamoDB table. What is the most secure way to give it access?
Self-checkQuestion
During a review you find a developer’s long-term access key in ~/.aws/credentials on several instances. Which two actions should you take?
Choose 2
Self-checkQuestion
A running instance needs a different IAM role. What must you do?
Self-checkQuestion
You launched a Windows Server instance with an RSA key pair. How do you get the Administrator password for RDP?
Self-checkQuestion
Administrators need a graphical desktop on Windows instances in private subnets, but port 3389 must not be opened to the internet and no bastion is allowed. What fits best?
Self-checkQuestion
You lost the private key for a running Amazon Linux instance with an EBS root volume. Session Manager is working on it. Which two are valid ways to restore SSH access?
Choose 2
Self-checkQuestion
WordPress runs on one instance and its MySQL database on a second instance. Which inbound rule should the database instance’s security group have?
Self-checkQuestion
Why keep SSH access in its own security group (sg-admin) instead of adding port 22 to the web servers’ security group?
Self-checkQuestion
A company removes every inbound rule for port 22 from all security groups. Administrators must still get a shell on the Linux instances. What should they use?
Self-checkQuestion
Which statement about EC2 key pairs is false?