Harden a VPC with Defense-in-Depth
Layer security groups and NACLs to build a hardened VPC on AWS.
Introduction
30 Second Summary
Locking your front door is great, but what if someone leaves a window open? Real security works in layers, so even if one control fails, another catches the threat.
In this project, you will build a hardened AWS VPC where an EC2 instance is protected by two independent security layers. You will start with a wide-open default configuration, then progressively lock it down and prove that layered security catches real-world mistakes.
What You'll Build
Picture this: you deliberately punch a hole in your firewall, simulating a teammate's mistake, and instead of your server being exposed to the world, a second security layer silently blocks the threat.
By the end of this project, you'll have:
- A running EC2 instance inside a VPC you built from scratch that you can SSH into from your local machine, confirming full network connectivity end-to-end.
- A tightened security group that only allows SSH from your personal IP address, blocking the rest of the internet from connecting.
- A live demonstration of defense-in-depth where a custom Network ACL blocks unauthorized traffic even when the security group is deliberately left wide open.
- Secret Mission: Restrict outbound traffic so your instance can only reach the internet for package updates, nothing else.
Are there any prerequisites?
You need an AWS account with free tier eligibility. This project also assumes you have prior experience navigating the AWS Console (for example, from the 7 Day DevOps Challenge).
Before We Start
Before we dive into the AWS Console, let's lock in what you're about to build and why it matters.
You're going to harden a VPC with two independent security layers that protect your instance even when one layer gets misconfigured.
Set Up Your VPC and Launch an Instance
Before you can harden anything, you need something to harden. A VPC with a running EC2 instance gives you a live network to protect.
In this step, you will build the default AWS networking setup. Starting with the out-of-the-box configuration is intentional. It exposes the overly-permissive security posture that the rest of this project fixes.
In this step, get ready to:
- Create a VPC with a public subnet, internet gateway, and route table.
- Launch a free-tier EC2 instance in the public subnet.
- SSH into the instance to confirm connectivity end-to-end.
Create a VPC with a public subnet
The VPC is your isolated virtual network inside AWS. You will use the "VPC and more" wizard, which auto-creates a public subnet, internet gateway, and route table in one go.
- Sign in to the AWS Management Console.
- In the search bar at the top, type VPC and select VPC from the results to open the VPC Console.
- On the VPC dashboard, click Create VPC.
- For Resources to create, choose VPC and more.
- Under Name tag auto-generation, clear the auto-generation checkbox and enter HardenLab as the name.
- For IPv4 CIDR block, enter 10.0.0.0/16.
- Set Number of Availability Zones (AZs) to 1.
- Set Number of public subnets to 1.
- Set Number of private subnets to 0.
- Expand Customize subnets CIDR blocks and set the public subnet CIDR to 10.0.1.0/24.
- For NAT gateways, keep the default None.
- For VPC endpoints, select None.
- Click Create VPC.
AWS takes a few seconds to provision your resources. You should see a success message with a list of created resources including the VPC, subnet, internet gateway, and route table.
- Click View VPC to confirm you see the HardenLab VPC with CIDR 10.0.0.0/16.
- In the left navigation, click Internet gateways. Confirm an internet gateway is listed and its State shows Attached to HardenLab.
- In the left navigation, click Route tables. Select the route table associated with HardenLab. In the Routes tab, confirm there is a route with destination 0.0.0.0/0 targeting the internet gateway.
What did the wizard just create?
The "VPC and more" wizard created four resources in one click. The VPC is your isolated network. The public subnet is a section of the VPC where resources can reach the internet. The internet gateway connects your VPC to the public internet. The route table directs traffic from the subnet to the internet gateway.
Together, these form the networking foundation that lets an EC2 instance communicate with the outside world.
Don't see the internet gateway attached?
Make sure you selected VPC and more (not "VPC only") in the wizard. If you chose "VPC only", delete the VPC and start again with the correct option.
Help me fix my internet gateway
Launch a free-tier EC2 instance in the public subnet
Now you need a server to protect. You will launch a free-tier EC2 instance into your new public subnet. The instance will start with a wide-open security group that allows SSH from anywhere on the internet.
- In the search bar at the top of the console, type EC2 and select EC2 to open the EC2 Console.
- Click Launch instance.
- Under Name and tags, enter HardenLab-Instance.
- Under Application and OS Images (Amazon Machine Image), select Amazon Linux 2023 AMI. Confirm it shows "Free tier eligible".
- Under Instance type, choose t2.micro. If t2.micro is unavailable in your region, choose t3.micro instead. Both are free tier eligible.
- Under Key pair (login), click Create new key pair.
- Name it HardenLab-key, keep the defaults (RSA, .pem format), and click Create key pair.
- The .pem file downloads to your computer automatically. Note where it saves. You will need it for SSH.
Already have a key pair?
If you have a key pair from a previous project and still have the .pem file on your machine, you can select it from the dropdown instead of creating a new one.
- Click Edit next to Network settings.
- For VPC, select your HardenLab VPC from the dropdown.
- For Subnet, select the public subnet you created (it should show 10.0.1.0/24).
- For Auto-assign Public IP, select Enable.
- Under Firewall (security groups), keep Create security group selected. Leave the default SSH rule allowing traffic from 0.0.0.0/0 (Anywhere). This is intentionally insecure. You will fix it in the next step.
- Leave all other settings at their defaults.
- Click Launch instance.
You should see a success message confirming your instance is launching.
- Click View all instances.
- Wait until the Instance state column shows Running and the Status check column shows 2/2 checks passed. This can take 1-2 minutes. Use the refresh button if needed.
Why allow SSH from anywhere?
The default security group the launch wizard creates allows SSH from 0.0.0.0/0. This means anyone on the internet who knows your instance's IP could attempt to connect. AWS even warns you about this.
You are leaving it wide open on purpose. Seeing this permissive default firsthand makes the hardening you do in Step 2 more meaningful.
Instance stuck in Pending?
Instances typically take 30-60 seconds to start. If it stays in Pending for more than 2 minutes, check that you selected the HardenLab public subnet (not a private subnet) and that Auto-assign Public IP is set to Enable.
Help me troubleshoot my pending instance
SSH into the instance to confirm connectivity
The ultimate test is reaching your instance over the network. You will SSH in from your local machine and confirm you get a shell prompt.
- In the EC2 Console, select your HardenLab-Instance.
- In the Details tab, find the Public IPv4 address field and copy the IP address.
Before connecting, you need to set the correct permissions on your key file so SSH accepts it.
macOS
- Open Terminal (press Cmd+Space, type Terminal, and press Enter).
- Set permissions on your key file by running:
chmod 400 ~/Downloads/HardenLab-key.pem
- Connect to your instance by running:
ssh -i ~/Downloads/HardenLab-key.pem ec2-user@[[EC2_PUBLIC_IP="your instance's public IPv4 address"]]
Windows
- Open PowerShell (press the Windows key, type PowerShell, and press Enter).
- Connect to your instance by running:
ssh -i $env:USERPROFILE\Downloads\HardenLab-key.pem ec2-user@[[EC2_PUBLIC_IP="your instance's public IPv4 address"]]
What does this command do?
- ssh starts a Secure Shell connection to a remote server.
- -i tells SSH which private key file to use for authentication.
- ec2-user is the default username for Amazon Linux instances.
- The IP address at the end is your instance's public address, which routes through the internet gateway to reach your VPC.
Before you press Enter, what do you expect to see? You set up a public subnet with an internet gateway and a security group allowing SSH from anywhere. Will the connection succeed?
If prompted "Are you sure you want to continue connecting?", type yes and press Enter.
You should see a shell prompt that looks like this:
[ec2-user@ip-10-0-1-XX ~]$
You are now logged into your EC2 instance. Your VPC networking works end-to-end. Traffic flowed from your laptop through the internet gateway, past the security group, and into the instance.
- Type exit to disconnect from the instance. You will reconnect later.
Connection timed out?
A timeout means traffic is not reaching your instance. Check these common causes:
- Verify Auto-assign Public IP is set to Enable in Network settings. Without a public IP, SSH cannot reach the instance.
- Confirm your route table has a 0.0.0.0/0 route targeting the internet gateway.
- Make sure your key file path is correct and matches the key pair you selected during launch.
Help me troubleshoot my SSH connection
Your VPC is live and your instance is reachable. Right now, anyone on the internet can attempt SSH into your server. In the next step, you will lock down that security group to allow connections only from your personal IP address.
Harden the Security Group
Your EC2 instance is up and running, and you proved you can SSH in. That is great progress. There is one problem though: right now, the security group allows SSH from 0.0.0.0/0. That means the entire internet can attempt to connect to your instance on port 22.
Anyone with a port scanner can find your instance in minutes. In this step, you will lock down the Security Group so that only your personal IP address is allowed to SSH in. This is the principle of least-privilege access: grant only the minimum access required.
In this step, get ready to:
- Find your public IP address.
- Restrict the security group to allow SSH only from your IP.
- Verify SSH still works from your machine.
Find your public IP address
Before you can restrict the security group, you need to know your own public IP address. AWS provides a free service that returns it instantly.
- Open a new browser tab and visit https://checkip.amazonaws.com.
- The page displays a single line of text: your public IPv4 address (for example, 203.0.113.42).
- Write this number down or copy it to your clipboard. You will use it in the next substep.
Why do I need my IP address?
A security group rule needs a source IP to decide who is allowed in. By specifying your exact IP with a /32 suffix, you tell AWS "only this single address may connect." The /32 means the mask covers all 32 bits, narrowing the allowed range to exactly one address.
Edit the security group inbound rules
Now you will replace the wide-open rule with one that only allows your IP.
- Switch back to the AWS Console tab.
- Open the EC2 Console. In the left navigation pane under Network & Security, click Security Groups.
- Select the security group attached to your instance (it will have "launch-wizard" in its name).
- Click the Inbound rules tab at the bottom of the page.
- Click Edit inbound rules.
You should see one rule allowing SSH from 0.0.0.0/0. Time to replace it.
- Click Delete on the existing SSH rule that shows source 0.0.0.0/0.
- Click Add rule.
- Set Type to SSH.
- Confirm Protocol is TCP and Port range is 22.
- In the Source field, enter your IP address followed by /32 (for example, 203.0.113.42/32).
- Click Save rules.
You should see a green banner confirming the inbound rules were updated successfully.
What changed?
Before, the rule said "allow SSH from anywhere" (0.0.0.0/0). Now it says "allow SSH from my IP only" (your /32 address). If someone from a different IP tries to connect on port 22, the security group silently drops the packets.
Don't see the launch-wizard security group?
Make sure you are in the same AWS Region where you launched your instance. Check the region selector in the top-right corner of the console.
If you see multiple security groups, click each one and check the Inbound rules tab. The correct one has an SSH rule on port 22.
Help me find my instance's security group in the EC2 Console.
Verify SSH still works with the tightened rule
You just restricted access to your IP alone. Before moving on, you need to confirm that you can still get in.
Before you run the command below, do you think SSH will succeed or fail? Your IP is now the only one allowed by the security group.
- Return to your terminal and SSH into your instance by running:
ssh -i [[KEYPATH="path to your .pem file"]] ec2-user@[[EC2_PUBLIC_IP="your instance's public IPv4 address"]]
You should see the Amazon Linux shell prompt again. Your IP matches the new rule, so the connection succeeds.
What does this prove?
Your security group is now least-privilege for inbound SSH. Only YOUR machine can connect on port 22. Any other IP address attempting to SSH will be silently dropped by the security group before the traffic ever reaches your instance.
SSH connection timed out?
Double-check the IP you entered in the security group rule matches the one shown at https://checkip.amazonaws.com. If you are on a VPN or your ISP rotated your IP since you wrote it down, the address may have changed.
Return to the security group's Inbound rules and update the source to your current IP.
Help me fix my security group rule so I can SSH into my EC2 instance.
Your first layer of defense is in place. But what happens if someone on your team accidentally adds 0.0.0.0/0 back? In the next step, you will add a second, independent security layer that catches exactly that kind of mistake.
Layer a Custom Network ACL
Your security group is now locked down to your IP only. But security groups have a weakness: if someone accidentally adds a 0.0.0.0/0 rule (a common mistake in teams), your instance is instantly exposed to the entire internet.
A Network ACL operates at the subnet level, evaluating traffic independently of security groups. Even if the security group gets misconfigured, the NACL blocks unauthorized traffic on its own. In this step, you'll create one as a safety net for your public subnet.
In this step, get ready to:
- Create a custom Network ACL in your HardenLab VPC.
- Add inbound and outbound rules for SSH and return traffic.
- Associate the NACL with your public subnet and verify SSH still works.
Create a custom Network ACL
Your public subnet is currently protected by the VPC's default NACL, which allows all traffic in and out. You need a custom NACL with restrictive rules that only permits the traffic you explicitly approve.
- In the AWS Console, open the VPC Console by searching for VPC in the top search bar and selecting the VPC service.
- In the left navigation pane, choose Network ACLs.
- Choose Create network ACL.
- For Name, enter HardenLab-NACL.
- For VPC, select your HardenLab VPC from the dropdown.
- Choose Create network ACL.
You should see your new HardenLab-NACL appear in the Network ACLs list.
Why does a custom NACL block everything by default?
A custom Network ACL starts with only deny-all rules (marked with an asterisk *). This forces you to be explicit about what traffic you allow. The default NACL that comes with your VPC allows everything, which is convenient but offers no protection.
Add inbound and outbound rules
Unlike security groups, NACLs are stateless. This means return traffic (the response packets your SSH session sends back to your computer) is not automatically allowed. You must create rules for both directions.
What are ephemeral ports?
When your computer connects to the instance over SSH (port 22), the response traffic comes back on a random high-numbered port called an ephemeral port. These range from 1024 to 65535. Because the NACL is stateless, you must allow this return traffic explicitly.
Security groups handle this automatically (they are stateful), which is why you didn't need to think about ephemeral ports in the previous step.
First, add the inbound rules:
- Select your HardenLab-NACL in the Network ACLs list.
- Choose the Inbound rules tab.
- Choose Edit inbound rules, then Add new rule.
- For the first rule, enter: Rule number 100, Type SSH, Protocol TCP, Port range 22, Source is your IP address with /32 appended (the same IP you used for the security group), Allow.
- Choose Add new rule again. For the second rule, enter: Rule number 200, Type Custom TCP, Protocol TCP, Port range 1024-65535, Source 0.0.0.0/0, Allow.
- Choose Save changes.
You should see Rules 100 and 200 listed under the Inbound rules tab, along with the default deny-all (*) rule at the bottom.
Now add the outbound rules:
- Choose the Outbound rules tab.
- Choose Edit outbound rules, then Add new rule.
- For the first rule, enter: Rule number 100, Type Custom TCP, Protocol TCP, Port range 1024-65535, Destination 0.0.0.0/0, Allow. This allows ephemeral port responses back to your SSH client.
- Choose Add new rule again. For the second rule, enter: Rule number 110, Type SSH, Protocol TCP, Port range 22, Destination 0.0.0.0/0, Allow. This allows outbound SSH if needed.
- Choose Save changes.
Confirm you see Rules 100 and 110 listed under the Outbound rules tab.
Why does inbound Rule 200 use 0.0.0.0/0 as the source?
Rule 200 allows inbound return traffic on ephemeral ports. The source is 0.0.0.0/0 because responses to outbound connections (like a package download) can come from any IP. This is safe because the high port range (1024-65535) is only used for return traffic to already-established connections.
Associate the NACL with your public subnet
The NACL won't protect anything until you associate it with a subnet. Right now your public subnet is still using the default NACL (which allows everything).
- With your HardenLab-NACL still selected, choose the Subnet associations tab.
- Choose Edit subnet associations.
- Select the Associate checkbox next to your HardenLab public subnet.
- Choose Save changes.
Your public subnet now shows under the Subnet associations tab for this NACL. Traffic entering and leaving the subnet is now evaluated against your custom rules.
Before you test SSH, what do you think will happen? Your IP matches Rule 100 in the inbound rules, and the ephemeral port rule covers the response traffic. Will the connection succeed or fail?
- Open your terminal and SSH into your instance using the same command from earlier:
ssh -i [[PEMPATH="path to your .pem file"]] ec2-user@[[EC2_PUBLIC_IP="your instance public IP address"]]
You should get a shell prompt. Your IP passes both the security group check (instance level) and the NACL check (subnet level). Two independent layers, one access decision.
SSH connection timed out?
- Verify your inbound Rule 100 uses your current IP with /32 appended. Your IP may have changed since the last step. Visit https://checkip.amazonaws.com to confirm.
- Check that inbound Rule 200 has port range 1024-65535 and source 0.0.0.0/0. Missing this rule blocks all response traffic.
- Confirm outbound Rule 100 has port range 1024-65535 and destination 0.0.0.0/0. Without this, your instance cannot send SSH responses back.
- Make sure the NACL is associated with the correct subnet (check the Subnet associations tab).
Still stuck? Help me troubleshoot why SSH times out after I associated my custom NACL with the subnet.
Your instance is now protected by two independent security layers. The security group filters at the instance level, and the NACL filters at the subnet level. Next up, you'll deliberately break one layer to prove the other catches it.
Prove Defense-in-Depth Works
Your VPC now has two independent security layers: a Security Group restricting SSH to your IP, and a Network ACL doing the same at the subnet level.
The real test of defense-in-depth is what happens when one layer fails. In this step, you will deliberately weaken the security group (simulating a teammate's mistake) and prove the NACL catches the misconfiguration independently.
In this step, get ready to:
- Simulate a security group misconfiguration by opening SSH to all IP addresses.
- Prove the NACL independently blocks unauthorized traffic.
- Restore both layers to their secure state.
Deliberately loosen the security group
In a team environment, someone might accidentally change the SSH source to allow all traffic. You will simulate exactly that mistake now.
- Switch to the EC2 Console tab in your browser.
- In the left navigation pane, choose Security Groups.
- Select the security group attached to your instance (the launch-wizard group).
- Choose the Inbound rules tab, then click Edit inbound rules.
- Find the SSH rule. Change the Source from your IP (/32) to Anywhere-IPv4 (0.0.0.0/0).
- Click Save rules.
What did you just do?
You opened SSH access from the entire internet at the security group level. This is a common real-world mistake that exposes instances to anyone with a port scanner.
The security group now allows SSH from 0.0.0.0/0. If the NACL were not there, any IP address could attempt SSH connections to your instance.
Confirm SSH still works from your machine
Before you SSH in, take a moment to predict: do you think SSH will succeed or fail right now? Your security group allows all IPs, and your NACL allows only your IP.
- Open your terminal and SSH into the instance by running:
ssh -i [[PEMPATH="path to your .pem key file"]] ec2-user@[[EC2_IP="your instance public IP"]]
SSH succeeds. Your IP passes both layers: the security group allows it (because it allows everyone) and the NACL allows it (because your IP matches Rule 100).
Why does it still work?
Traffic must pass both the NACL and the security group to reach the instance. Your IP satisfies both. The NACL is currently protecting you from other IPs, but you cannot tell just by logging in from your own machine.
To prove the NACL is independently blocking other traffic, you need to simulate being a different IP. That is what the next substep does.
SSH timed out?
If SSH fails at this point, your NACL rules may have drifted. Confirm Rule 100 in the NACL inbound rules still uses your actual IP with a /32 suffix.
help me debug why SSH is timing out after changing my security group
Prove the NACL blocks traffic independently
To prove the NACL is doing its job, you will temporarily change the NACL's SSH rule to a fake IP address. This simulates what would happen if a different person tried to SSH into your instance.
- Type exit to leave the SSH session.
- In the AWS Console, navigate to the VPC Console.
- In the left navigation pane, choose Network ACLs.
- Select HardenLab-NACL.
- Choose the Inbound rules tab, then click Edit inbound rules.
- Find Rule 100 (SSH, port 22). Change the Source from your IP to 198.51.100.1/32 (a fake test IP that is not yours).
- Click Save changes.
What is 198.51.100.1?
This IP is from a range reserved for documentation and testing. It will never be a real public address. By pointing the NACL rule at this fake IP, you are telling the NACL to allow SSH only from an address that does not exist.
Now predict: what will happen when you try to SSH from your machine? Remember, the security group still allows SSH from 0.0.0.0/0 (everyone). But the NACL now only allows SSH from 198.51.100.1/32 (not you).
- Try to SSH into your instance again by running the same command:
ssh -i [[PEMPATH="path to your .pem key file"]] ec2-user@[[EC2_IP="your instance public IP"]]
The connection times out. Even though the security group allows SSH from your IP, the NACL blocks it because your IP does not match 198.51.100.1/32.
This is defense-in-depth in action
You just proved that the NACL acts as an independent safety net. The security group was wide open to the entire internet, but the NACL still blocked unauthorized traffic at the subnet boundary.
In a real scenario, if a teammate accidentally loosens the security group, the NACL catches the mistake before any attacker can reach your instances.
Now restore both layers to their secure state.
- In the VPC Console, select HardenLab-NACL and go to Inbound rules.
- Click Edit inbound rules.
- Change Rule 100's Source back to your actual public IP with /32 (the same value you used when creating the NACL).
- Click Save changes.
- Switch to the EC2 Console and go to Security Groups.
- Select your launch-wizard security group.
- Choose the Inbound rules tab, then click Edit inbound rules.
- Change the SSH rule's Source from Anywhere-IPv4 (0.0.0.0/0) back to My IP (your IP with /32).
- Click Save rules.
Both layers are now restored to least-privilege. Confirm everything works by SSHing one more time.
- SSH into your instance to verify access is restored:
ssh -i [[PEMPATH="path to your .pem key file"]] ec2-user@[[EC2_IP="your instance public IP"]]
You should get a shell prompt. Your VPC is back to its hardened state with both layers enforcing least-privilege access.
Still timing out after restoring?
Double-check that Rule 100 in the NACL inbound rules uses your current public IP (not the fake 198.51.100.1). Also confirm the security group SSH rule source matches your IP with a /32 suffix.
help me restore SSH access after my defense-in-depth test
You have now seen layered security in action. Even with a wide-open security group, your NACL independently stopped unauthorized traffic from reaching the subnet. Next up, take on the Secret Mission to lock down outbound traffic and complete your professional-grade hardening.
Secret mission
Restrict Outbound Traffic
You've locked down inbound traffic with two independent layers. But what about outbound? An attacker who gains access to your instance can exfiltrate data over any outbound port. Your mission: restrict egress so the instance can only make HTTPS calls for package updates, blocking everything else.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. The VPC, subnet, route table, internet gateway, security groups, and Network ACLs are all free. Only the EC2 instance consumes free tier hours.
Cost warning
Your EC2 instance uses free tier hours (750 hours/month shared across all running instances in your account). If you have other instances running, the combined hours count toward the 750/month limit. Exceeding this triggers standard on-demand charges.
If you are not actively using this instance, stop or terminate it to preserve your free tier balance.
Resources you used:
- 1 VPC (HardenLab) with associated public subnet, route table, and internet gateway.
- 1 EC2 instance (t2.micro or t3.micro) running in the HardenLab public subnet.
- 1 custom Network ACL (HardenLab-NACL).
- 1 security group (launch-wizard) with modified inbound and outbound rules.
- 1 key pair for SSH access.
Keep everything running
No action needed. Choose this if you are still actively experimenting with your VPC security setup or plan to continue hardening the instance.
- Your EC2 instance will continue consuming free tier hours while running.
- All VPC networking components (subnet, route table, internet gateway, NACL, security group) have no hourly charge.
- Your key pair remains stored in your AWS account at no cost.
Pause - I'll come back to this later
Stop the EC2 instance to free up free tier hours while keeping everything in place. You can start the instance again later and pick up where you left off.
- Open the EC2 Console at https://console.aws.amazon.com/ec2/.
- In the navigation pane, choose **Instances**.
- Select your HardenLab instance.
- Choose **Instance state**, then **Stop instance**.
- Choose **Stop** when prompted for confirmation.
- The instance stops consuming free tier hours while stopped. Your VPC, subnet, NACL, and security group configurations remain intact at no cost.
- When you are ready to resume, select the instance and choose **Instance state**, then **Start instance**.
Delete - I don't want to use this again
Remove all project resources to ensure zero ongoing usage. Terminate the instance first, then delete the VPC. Deleting the VPC through the console also removes the subnet, route table, internet gateway, Network ACL, and security group automatically.
Terminate the EC2 instance:
- Open the EC2 Console at https://console.aws.amazon.com/ec2/.
- In the navigation pane, choose **Instances**.
- Select your HardenLab instance.
- Choose **Instance state**, then **Terminate (delete) instance**.
- Choose **Terminate (delete)** when prompted for confirmation.
- Wait for the instance state to show as terminated before proceeding.
Delete the VPC and all associated resources:
- Open the VPC Console at https://console.aws.amazon.com/vpc/.
- In the navigation pane, choose **Your VPCs**.
- Select the HardenLab VPC.
- Choose **Actions**, then **Delete VPC**.
- Review the list of resources that will be deleted (subnet, route table, internet gateway, HardenLab-NACL, and security group).
- Type delete in the confirmation field, then choose **Delete**.
Delete your key pair (optional):
- In the EC2 Console, go to **Key Pairs** in the navigation pane under **Network & Security**.
- Select the key pair you created for this project.
- Choose **Actions**, then **Delete**.
- Delete the corresponding .pem file from your local machine.
Nice Work!
Nice Work!
You just hardened a VPC with real, layered security controls. You built the same defense-in-depth pattern that production AWS environments rely on to catch misconfigurations before they become breaches.
You've learned how to:
- Build a VPC from scratch and harden a security group from wide-open to least-privilege, restricting SSH to a single IP address.
- Create and configure a custom Network ACL with explicit allow rules, handling stateless behavior and ephemeral port return traffic.
- Prove defense-in-depth works by simulating a security group misconfiguration and watching the NACL independently block unauthorized traffic.
- Secret Mission: Locked down outbound traffic so your instance can only reach the internet over HTTPS, blocking all other egress.
Ready to quiz yourself?