🔐 Monitor Failed SSH Login Attempts on Amazon EC2 with CloudWatch and SNS

👋 Welcome to my Hashnode profile! I'm a passionate technologist with expertise in AWS, DevOps, Kubernetes, Terraform, Datree, and various cloud technologies. Here's a glimpse into what I bring to the table: 🌟 Cloud Aficionado: I thrive in the world of cloud technologies, particularly AWS. From architecting scalable infrastructure to optimizing cost efficiency, I love diving deep into the AWS ecosystem and crafting robust solutions. 🚀 DevOps Champion: As a DevOps enthusiast, I embrace the culture of collaboration and continuous improvement. I specialize in streamlining development workflows, implementing CI/CD pipelines, and automating infrastructure deployment using modern tools like Kubernetes. ⛵ Kubernetes Navigator: Navigating the seas of containerization is my forte. With a solid grasp on Kubernetes, I orchestrate containerized applications, manage deployments, and ensure seamless scalability while maximizing resource utilization. 🏗️ Terraform Magician: Building infrastructure as code is where I excel. With Terraform, I conjure up infrastructure blueprints, define infrastructure-as-code, and provision resources across multiple cloud platforms, ensuring consistent and reproducible deployments. 🌳 Datree Guardian: In my quest for secure and compliant code, I leverage Datree to enforce best practices and prevent misconfigurations. I'm passionate about maintaining code quality, security, and reliability in every project I undertake. 🌐 Cloud Explorer: The ever-evolving cloud landscape fascinates me, and I'm constantly exploring new technologies and trends. From serverless architectures to big data analytics, I'm eager to stay ahead of the curve and help you harness the full potential of the cloud. Whether you need assistance in designing scalable architectures, optimizing your infrastructure, or enhancing your DevOps practices, I'm here to collaborate and share my knowledge. Let's embark on a journey together, where we leverage cutting-edge technologies to build robust and efficient solutions in the cloud! 🚀💻
Monitoring SSH activity is one of the simplest and most effective ways to detect unauthorized access attempts on your Linux servers.
In this guide, you’ll learn how to automatically detect and get notified about failed SSH login attempts using Amazon CloudWatch, CloudWatch Agent, and Amazon SNS — all built directly into AWS.
We’ll cover the full setup:
Launching an EC2 instance
Installing and configuring the CloudWatch Agent using user data
Creating CloudWatch log groups and metric filters
Setting up SNS notifications for failed logins
🧭 Step 1: Launch an EC2 Instance
Sign in to the AWS Management Console.
Navigate to EC2 → Instances → Launch instance.
Configure the instance:
Name:
ssh-monitor-instanceAMI: Amazon Linux 2 (latest)
Instance type:
t2.micro(eligible for free tier)Key pair: Select or create a new one
Network settings: Allow SSH (port 22) from your IP only
Expand the Advanced details section.
In the User data box, paste the following script:
📜 User Data Script — Install and Configure CloudWatch Agent
#!/bin/bash
# Update packages
yum update -y
# Install the CloudWatch Agent
yum install -y amazon-cloudwatch-agent
# Create CloudWatch Agent configuration file
cat <<'EOF' > /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
{
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/secure",
"log_group_name": "SSHfail",
"log_stream_name": "{instance_id}-secure-log",
"timestamp_format": "%b %d %H:%M:%S"
}
]
}
},
"log_stream_name": "default-log-stream"
}
}
EOF
# Start and enable the CloudWatch Agent service
systemctl enable amazon-cloudwatch-agent.service
systemctl start amazon-cloudwatch-agent.service
This script does the following automatically when the instance launches:
Updates the system
Installs the CloudWatch Agent
Configures it to forward
/var/log/securelogs (which include SSH attempts)Creates a log group named SSHfail
Starts the agent service
💻 Step 2: Verify the CloudWatch Agent Is Running
Once the instance is running, connect to it using EC2 Instance Connect or your SSH client:
ssh -i your-key.pem ec2-user@<public-ip>
Verify that the agent is active:
sudo systemctl status amazon-cloudwatch-agent.service
You should see a green “active (running)” status.
To confirm logs are being collected, run:
sudo tail -f /var/log/secure
You’ll see real-time authentication messages — including failed login attempts.
⚙️ Step 3: Generate a Failed SSH Attempt
Let’s simulate an invalid SSH login so we have something to detect.
From your terminal, try connecting with a wrong username:
ssh baduser@<public-ip>The connection should fail.
In your EC2 instance terminal, run:
sudo tail -f /var/log/secure
You’ll see an entry similar to:
Invalid user baduser from 108.51.10.24 port 53212
This confirms failed login attempts are being logged.
☁️ Step 4: View Logs in Amazon CloudWatch
Now check that your log data is flowing into CloudWatch.
Open the CloudWatch service in the AWS Console.
Go to Logs → Log groups.
Locate the log group named SSHfail.
Click the group → choose your log stream.
You’ll see the SSH logs from your instance appear here.
🔔 Step 5: Create an SNS Topic for Notifications
We’ll use Amazon Simple Notification Service (SNS) to send email alerts.
In the AWS Console, open SNS → Topics → Create topic.
Choose Standard.
Enter:
Name:
ssh-failsDisplay name:
SSH Fails
Click Create topic.
Next, create a subscription so you can receive alerts:
Go to Subscriptions → Create subscription.
Set:
Topic ARN: Select
ssh-failsProtocol: Email
Endpoint: Your email address
Click Create subscription.
Check your email and confirm the subscription.
📊 Step 6: Create a CloudWatch Metric Filter
Next, we’ll define a filter pattern that tells CloudWatch what to look for in the logs.
In CloudWatch → Log groups, select SSHfail.
Click Actions → Create metric filter.
Use the following pattern:
[Mon, day, timestamp, ip, id, status = Invalid, ...]
This pattern matches log lines that contain the word “Invalid,” which appears when someone tries to SSH with a non-existent username.
Configure:
Filter name:
InvalidSSHUsersMetric namespace:
ssh-failsMetric name:
failed-loginsMetric value:
1
Click Create metric filter.
🚨 Step 7: Create a CloudWatch Alarm
Now that the metric exists, let’s create an alarm to notify you when multiple failed attempts occur.
Go to CloudWatch → Alarms → Create alarm.
Click Select metric → Logs → ssh-fails → failed-logins.
Configure:
Statistic: Sum
Period: 1 minute
Under Conditions, set:
Threshold type: Static
Whenever metric is ≥
3
Under Notifications, select your SNS topic
ssh-fails.Name the alarm
InvalidSSHUsersand click Create alarm.
🧪 Step 8: Test the End-to-End Setup
Try several failed SSH logins within one minute:
ssh baduser@<public-ip>
ssh testuser@<public-ip>
ssh hacker@<public-ip>
Wait a few moments.
Your CloudWatch Alarm should transition to the In alarm state, and you’ll receive an email notification like this:
Subject: ALARM: "InvalidSSHUsers" in us-west-2
Message: Failed SSH login attempts detected on your EC2 instance.
Once no more failed attempts occur, the alarm will return to OK state automatically.
🧱 Step 9: Strengthen Your SSH Security
Monitoring failed logins is just the first step.
To improve your overall security posture, consider:
🔐 Disable root SSH access (
PermitRootLogin noin/etc/ssh/sshd_config)🔑 Use key pairs instead of passwords
🧱 Change the SSH port from 22 to a custom one (e.g., 2222)
🚫 Restrict SSH by IP using Security Groups
🚨 Install Fail2Ban or similar tools to automatically block brute-force attempts
✅ Conclusion
You now have a fully automated SSH login monitoring system powered by AWS:
CloudWatch Agent forwards
/var/log/securelogsMetric filters detect failed login attempts
CloudWatch Alarms evaluate thresholds
SNS sends real-time email alerts
This setup is simple, lightweight, and entirely serverless on the monitoring side — making it suitable for both single EC2 instances and large-scale deployments




