Hands-On Cloud Security with AWS: VPCs, NACLs, and More

I recently came across an Instagram post, of all places, that outlined a brilliant project idea for getting hands-on with cloud security: build a secure yet accessible infrastructure on AWS. The core components?
- A Virtual Private Cloud (VPC) with a public subnet
- A web server accessible from the internet
- Properly configured Security Groups and Network ACLs
- Security best practices to protect your resources
I’ve decided to take on the challenge. I’ll be using AWS.

First things first: creating a VPC


Above, you can see the settings I used to create my VPC.

With the VPC now created, it’s worth pausing to understand AWS's two main layers of network security:
Security Groups
- Act as virtual firewalls for individual resources
- Stateful: if outbound traffic is allowed, the return traffic is automatically allowed
- Only support allow rules (no explicit deny)
- Rules are evaluated as a whole—if any rule allows traffic, it’s allowed
Network ACLs (NACLs)
- Operate at the subnet level
- Stateless: inbound and outbound rules are evaluated independently
- Support both ALLOW and DENY rules
- Processed in numerical order (lower numbers evaluated first)
- Provide an additional layer of defence
We’ll be implementing both for a defence-in-depth approach.
Let’s start with creating a NACL.


Inbound rules are shown above (with my own IP redacted).

Outbound rules are shown here.
Following security best practices, I explicitly defined allow rules and denied everything else by default. I then associated my subnets with this NACL.

Next step: launching an EC2 instance.


After setting up inbound rules within the Security Group, I added the following script to the EC2 User Data section to bootstrap the web server:
#!/bin/bash
# Update the system packages
yum update -y
# Install Apache web server
yum install -y httpd
# Start the Apache web server
systemctl start httpd
# Configure Apache to start automatically on boot
systemctl enable httpd
# Create a simple HTML page
echo "<html><body><h1>Secure AWS Web Server</h1><p>This server is protected by security groups and NACLs</p></body></html>" > /var/www/html/index.html
All that remained was to launch the instance.

To further improve security, I went back to the VPC dashboard and:
- Created a VPC flow log
- Enabled Amazon GuardDuty
I also:
- Created an IAM role with minimal permissions and attached it to the EC2 instance
- Enabled MFA for the root account
After tightening up these security features, I tested the server.
Here’s a successful HTTP connection.

SSH without the key resulted in a “Permission denied” message (as expected).

Using the correct key resulted in a successful SSH login.

This project has pushed me to consider a number of cloud security best practices, including:
- Network Segmentation: Only expose necessary resources to the internet
- Defence in Depth: Use multiple layers like Security Groups and NACLs
- Principle of Least Privilege: Assign the minimal access necessary
- Regular Updates: Keep the OS and packages patched
- Monitoring and Logging: Enable flow logs and GuardDuty, set up alerts
- Encryption: Use HTTPS for data in transit and enable encryption at rest
- IAM Best Practices: Use roles, avoid hardcoded credentials, enable MFA
Conclusion
Security in the cloud isn’t a one-time task—it’s an ongoing process. By configuring VPCs, subnets, Security Groups, and NACLs with intention, I’ve laid a secure foundation for future cloud projects.
The public subnet architecture I’ve built strikes a balance between accessibility and security, and it provides a practical starting point for anyone looking to learn cloud security hands-on.
For now, I’m pausing the instance. But next steps might include:
- Adding an AWS WAF
- Enabling CloudTrail and AWS Config
- Setting up CloudWatch alarms for suspicious activity
- Or maybe even turning this instance into a honeypot to analyse access attempts
Stay secure out there.