Hands-On: Understanding Security Groups and NACLs in AWS
In the previous article we learned the theory behind:
Security Groups
NACLs(Network Access Control List)
Now it is time to see them in action.
In this hands-on lab we will:
Create a VPC
Launch an EC2 instance
Run a simple python web server
Allow traffic using security group
Block traffic using NACL.
Understand how both security layers work together.
By the end of this lab, you will clearly understand the difference between Security Groups and NACLs.
Let's dive into the hands-on now.
Step 1: Create VPC
Login to the AWS console using your credentials.
Search for VPC -> click Create VPC
Here, select: VPC and more
This automatically creates:
VPC
Public Subnet
Private Subnet
Route Table
Internet Gateway
Now, give your VPC a name: vpc-test
For the IPv4 CIDR block, choose the IP range that you want.
In my case I entered: 10.0.0.0/16
Click Create VPC.
After creating the VPC, click on view VPC and check the Resource Map for your understanding and see what AWS has created for you.
This will help you understand how all networking components are connected.
Step 2: Launch an EC2 Instance
Navigate to EC2 -> Instances -> Launch Instance
Now provide:
EC2 instance name
Operating System
Key-Pair
Now under the Network settings:
Select the VPC you created: vpc-test
Under the subnet section select the Public subnet.
Note: Normally production subnets should use private subnet whenever possible. However for learning purpose we will use public subnet.
In the Auto assign public IP option choose: Enable
In the Firewall (security groups) option select Create new Security Group
Then click Launch Instance
Step 3: Connect to EC2 Instance
Now copy the public IP address of your EC2 instance.
Open terminal and connect using SSH.
Example:
ssh -i test_app.pem ubuntu@[Public_IP]
Now replace [Public_IP] with your EC2 instance public IP.
Step 4: Update packages
Whenever you launch a new Linux server, make sure to update the packages. It is considered a good practice.
Run:
sudo apt update
Step 5: Verify Python Installation
Now check whether python is installed.
Run:
python3
Step 6: Start a Simple Python Web Server
Python provides built-in web server.
Run:
python3 -m http.server 8000
Your application is now running on port 8000
Step 7: Try Accessing the Application
Open your browser and type this:
http://54.xx.xx.xx:8000
Here you will notice that the application will not open.
Why?
Let's check what is blocking the application.
Step 8: Check NACL
Go to AWS Console -> VPC -> Network ACLs
Open the NACL which is associated with your subnet.
Check the inbound Rules
Here you will notice something interesting.
AWS already allows traffic through NACL.
Example:
Rule 100: Allow All Traffic
This means NACL is not blocking us.
So, why can't we access the application?
Because there is another Security Layer: Security group
Now we saw in NACL the rules with the number like 100 and * symbol, let us try to understand that.
Understanding NACL Rule Priority
NACL rules are processed in order.
Small numbers have high priority.
Example:
100 -> Checked first
200 -> Checked second
300 -> Checked third
... it goes on and on and then
* -> Checked last
Step 9: Allow Port 8000 in Security Group
Navigate to EC2 -> Instance -> Click the instance Id -> Security
Open the attached Security Group.
Click on edit inbound rules
Now if you see here you will see by default Security Group blocks all incoming traffic and only allows the SSH.
Now, lets add our rule.
Click on Add Rule
Type: Custom TCP
Port 8000
Source: anywhere IPv4
Save the rule
Step 10: Test Again
Return to your browser and refresh http://<PUBLIC_IP>:8000
This time the application loads successfully.
what changed?
The Security Group now allows traffic on Port 8000
Flow:
Internet
↓
NACL(Allowed)
↓
Security Group(Allowed)
↓
EC2 Instance
Now, since we understood how NACL and Security Groups work.
Let us try to do some more changes and see what happens.
Step 11: Block Traffic using NACL
Now let's see how NACL and override access.
Navigate to:
VPC → Network ACLs
Click on edit inbound rules.
Now Create:
Rule Number: 100
Type: TCP Custom
Port: 8000
Source: 0.0.0.0/0
Action: Deny
Save the Rule
Now Refresh the browser: http://<PUBLIC_IP>:8000 and you will see the application is not accessible now.
why?
Because traffic is blocked at subnet level before it reaches Security Group.
Flow:
Internet
↓
NACL(Denied)
❌
Security Group
❌
EC2 Instance
Even though the Security Group allows PORT 8000, the NACL blocks the request first.
Step 13: Understanding Rule Priority
Now let's restore the access.
Edit the NACL again.
Navigate to VPC → Network ACLs
Click on edit inbound rules
Create:
Rule Number: 100 Allow all traffic
rule number: 200
Type: Customer TCP
Port range: 8000
Source: 0.0.0.0/0
Allow/deny: Deny
Save the changes.
Now try to guess what will happen if you try to access the http server.
Yes, you are correct the application works successfully.
why?
Because AWS Checks:
Rule 100 first.
Since Rule 100 allows all traffic, AWS never evaluates Rule number 2
Flow:
Rule Number 100 → Match Found → Allow
Rule Number 200 → Ignored
This demonstrates, one of the NACL important concepts.
Lower Number Rules have high Priority
Key Takeaways:
Security Group:
Works at Instance level
Stateful
Allows traffic
Network ACLs:
Works at subnet level
Stateless
Allows and Denies traffic
Uses Rule priority
Request Flow:
Internet
↓
NACL
↓
Security Group
↓
EC2 Instance
If either layers blocks the traffic, the request never reaches the server
Conclusion:
In this hands-on lab, we created a VPC, launched an EC2 Instance, and deployed a simple python web server.
We observed how:
Security Groups Control Traffic at instance level
NACLs controls traffic at subnet level.
NACL rule priority affects the traffic flow
Multiple security layers work together to protect AWS resources.
