<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sheriff Ademoye</title>
    <description>The latest articles on DEV Community by Sheriff Ademoye (@sheviantos).</description>
    <link>https://dev.to/sheviantos</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3607339%2F42064686-5e6b-41f8-8de1-ab5a3f862d92.png</url>
      <title>DEV Community: Sheriff Ademoye</title>
      <link>https://dev.to/sheviantos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sheviantos"/>
    <language>en</language>
    <item>
      <title>🌐 Build Your Own Virtual Private Cloud (VPC) on Linux</title>
      <dc:creator>Sheriff Ademoye</dc:creator>
      <pubDate>Wed, 12 Nov 2025 16:15:32 +0000</pubDate>
      <link>https://dev.to/sheviantos/build-your-own-virtual-private-cloud-vpc-on-linux-17cf</link>
      <guid>https://dev.to/sheviantos/build-your-own-virtual-private-cloud-vpc-on-linux-17cf</guid>
      <description>&lt;p&gt;I recreated AWS VPC functionality on a single Linux machine using network namespaces, bridges, and iptables. No cloud providers, no Docker - just pure Linux networking. All 13 tests passed, and I learned more about networking in one week than in months of theory.&lt;/p&gt;

&lt;p&gt;🤔 The Challenge&lt;br&gt;
As part of the HNG DevOps Internship Stage 4, I was given this challenge:&lt;/p&gt;

&lt;p&gt;"Build your own Virtual Private Cloud (VPC) using Linux networking primitives. It must support subnets, routing, NAT gateways, VPC isolation, peering, and security groups."&lt;/p&gt;

&lt;p&gt;My first reaction? "Wait, I thought VPCs were a cloud thing?"&lt;br&gt;
Turns out, AWS VPC, Azure VNet, and GCP VPC are all built on the same Linux networking concepts I was about to implement. This project would show me what's really happening under the hood.&lt;/p&gt;

&lt;p&gt;🎯 What I Set Out to Build&lt;br&gt;
Imagine you're building a banking application. You need:&lt;/p&gt;

&lt;p&gt;A web frontend - accessible from the internet&lt;br&gt;
An API backend - talks to frontend and database&lt;br&gt;
A database - completely isolated from the internet&lt;/p&gt;

&lt;p&gt;In AWS, you'd create a VPC with public and private subnets. I was going to build exactly that - but on my laptop.&lt;br&gt;
The Architecture&lt;br&gt;
           ┌──────────────────────────────┐&lt;br&gt;
           │      My Linux Machine        │&lt;br&gt;
           │    (eth0 → Internet)         │&lt;br&gt;
           └────────────┬─────────────────┘&lt;br&gt;
                        │&lt;br&gt;
                ┌───────┴────────┐&lt;br&gt;
                │   Linux Bridge │  ← My "VPC Router"&lt;br&gt;
                │   (10.0.1.1)   │&lt;br&gt;
                └───────┬────────┘&lt;br&gt;
        ┌───────────────┼────────────────┐&lt;br&gt;
        │                               │&lt;br&gt;
┌──────────────┐               ┌────────────────┐&lt;br&gt;
│ Public Subnet│               │ Private Subnet │&lt;br&gt;
│   (10.0.1.2) │               │   (10.0.2.2)  │&lt;br&gt;
│ Internet: ✓  │               │ Internet: ✗    │&lt;br&gt;
└──────────────┘               └────────────────┘&lt;/p&gt;

&lt;p&gt;🛠️ The Building Blocks&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Network Namespaces = Subnets
Think of network namespaces as "mini virtual machines" for networking. Each namespace has its own:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Network interfaces&lt;br&gt;
IP addresses&lt;br&gt;
Routing tables&lt;br&gt;
Firewall rules&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create an isolated network environment
sudo ip netns add my-subnet

# It's completely isolated from the host
sudo ip netns exec my-subnet ip addr

# Only shows loopback interface!

This is how Docker containers get isolated networking!

2. Linux Bridges = VPC Routers

A bridge is like a virtual network switch. It connects multiple network interfaces together.

# Create a bridge (my VPC router)

sudo ip link add br-myvpc type bridge
sudo ip link set br-myvpc up
sudo ip addr add 10.0.1.1/24 dev br-myvpc

This bridge becomes the gateway for all my subnets.

3. veth Pairs = Virtual Network Cables

veth pairs are like virtual ethernet cables - always come in pairs, what goes in one end comes out the other.

# Create a virtual cable
sudo ip link add veth0 type veth peer name veth1

# One end goes in the namespace (subnet)
sudo ip link set veth1 netns my-subnet

# Other end connects to the bridge (router)
sudo ip link set veth0 master br-myvpc

This is the same concept Docker uses to connect containers!

4. iptables = NAT Gateway + Firewall

To give subnets internet access, I needed NAT (Network Address Translation):

# Enable IP forwarding
sudo sysctl -w net.ipv4.ip_forward=1

# Add NAT rule (the magic that gives internet access)
sudo iptables -t nat -A POSTROUTING \
  -s 10.0.1.0/24 -o eth0 -j MASQUERADE

# Allow forwarding

sudo iptables -A FORWARD \
  -s 10.0.1.2/32 -o eth0 -j ACCEPT

What this does: Changes the source IP from 10.0.1.2 (private) to my laptop's public IP when packets go to the internet.

💻 Building the CLI Tool
I automated everything into a Python CLI tool called vpcctl. Here's a glimpse:

### Creating a VPC

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;def create_vpc(name, cidr):&lt;br&gt;
    bridge = f"br-{name}"&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create bridge
subprocess.run(["ip", "link", "add", bridge, "type", "bridge"])
subprocess.run(["ip", "link", "set", bridge, "up"])
subprocess.run(["ip", "addr", "add", cidr, "dev", bridge])

print(f"✓ VPC '{name}' created with bridge {bridge}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Create a VPC
&lt;/h1&gt;

&lt;p&gt;sudo ./vpcctl.py create-vpc --name production --cidr 10.0.1.1/24&lt;/p&gt;
&lt;h1&gt;
  
  
  Add public subnet (with internet)
&lt;/h1&gt;

&lt;p&gt;sudo ./vpcctl.py add-subnet \&lt;br&gt;
  --vpc production \&lt;br&gt;
  --subnet web \&lt;br&gt;
  --ip 10.0.1.2 \&lt;br&gt;
  --gateway 10.0.1.1 \&lt;br&gt;
  --nat&lt;/p&gt;
&lt;h1&gt;
  
  
  Add private subnet (no internet)
&lt;/h1&gt;

&lt;p&gt;sudo ./vpcctl.py add-subnet \&lt;br&gt;
  --vpc production \&lt;br&gt;
  --subnet database \&lt;br&gt;
  --ip 10.0.2.2 \&lt;br&gt;
  --gateway 10.0.2.1&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# The Challenges 

Challenge #1: iptables Rules Were Invisible

I was adding iptables rules, seeing success messages, but when I checked:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;sudo iptables -L FORWARD&lt;/p&gt;

&lt;h1&gt;
  
  
  Chain FORWARD (policy ACCEPT)
&lt;/h1&gt;

&lt;h1&gt;
  
  
  (Empty!)
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The problem: I was suppressing errors with stderr=subprocess.DEVNULL. The rules were failing silently!

The fix: Removed the suppression, saw the real error, fixed the issue.
Lesson learned: Never hide errors during development. Debug first, clean up later.

Challenge #2: VPC Isolation Not Working
My two VPCs could communicate even though they shouldn't!

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  This should fail but didn't
&lt;/h1&gt;

&lt;p&gt;sudo ip netns exec vpc1-subnet ping 10.1.1.2&lt;/p&gt;

&lt;h1&gt;
  
  
  64 bytes from 10.1.1.2 ✗ (shouldn't work!)
&lt;/h1&gt;

&lt;p&gt;The problem: My ACCEPT rules were too broad. They were matching ALL traffic, not just internet traffic.&lt;/p&gt;

&lt;p&gt;The fix: Made ACCEPT rules specific to the internet interface:&lt;/p&gt;

&lt;h1&gt;
  
  
  Before (matches everything)
&lt;/h1&gt;

&lt;p&gt;iptables -A FORWARD -s 10.0.1.2/32 -j ACCEPT&lt;/p&gt;

&lt;h1&gt;
  
  
  After (only matches internet traffic)
&lt;/h1&gt;

&lt;p&gt;iptables -A FORWARD -s 10.0.1.2/32 -o eth0 -j ACCEPT&lt;/p&gt;

&lt;p&gt;Lesson learned: Firewall rules need to be specific. General rules create security holes.&lt;/p&gt;

&lt;p&gt;Challenge #3: WSL2 iptables Issues&lt;/p&gt;

&lt;p&gt;On Windows WSL2, my iptables commands weren't working at all!&lt;/p&gt;

&lt;p&gt;The fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Switch to iptables-legacy
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lesson learned: Different environments have different quirks. Always test in your target environment.&lt;/p&gt;

&lt;p&gt;🎉 The Results&lt;br&gt;
After days of debugging, I finally got all 13 tests passing:&lt;br&gt;
[1]  VPC Creation                              ✓ PASS&lt;br&gt;
[2]  Subnet Creation                           ✓ PASS&lt;br&gt;
[3]  List VPCs and Subnets                     ✓ PASS&lt;br&gt;
[4]  Intra-VPC Communication                   ✓ PASS&lt;br&gt;
[5]  Public Subnet Internet Access             ✓ PASS&lt;br&gt;
[6]  Private Subnet Blocked from Internet      ✓ PASS&lt;br&gt;
[7]  VPC Isolation                             ✓ PASS&lt;br&gt;
[8]  VPC Peering Creation                      ✓ PASS&lt;br&gt;
[9]  Cross-VPC Communication After Peering     ✓ PASS&lt;br&gt;
[10] App Deployment                            ✓ PASS&lt;br&gt;
[11] Access App from Host                      ✓ PASS&lt;br&gt;
[12] Firewall Rules Application                ✓ PASS&lt;br&gt;
[13] Configuration Export                      ✓ PASS&lt;/p&gt;

&lt;p&gt;Result: 13/13 (100% Success Rate!) 🎉&lt;br&gt;
What Works:&lt;br&gt;
✅ VPC isolation - Different VPCs can't communicate by default&lt;br&gt;
✅ NAT gateway - Public subnets have internet, private don't&lt;br&gt;
✅ VPC peering - Can enable controlled cross-VPC communication&lt;br&gt;
✅ Security groups - Firewall rules work perfectly&lt;br&gt;
✅ Clean teardown - No orphaned resources&lt;/p&gt;

&lt;p&gt;🧠 What I Actually Learned&lt;br&gt;
Technical Skills&lt;/p&gt;

&lt;p&gt;Network Namespaces - The foundation of container networking&lt;br&gt;
Linux Bridges - How virtual routers work&lt;br&gt;
iptables - NAT, forwarding, and firewall rules&lt;br&gt;
veth Pairs - Virtual network connections&lt;br&gt;
IP Routing - How packets move between networks&lt;/p&gt;

&lt;p&gt;Bigger Insights&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cloud providers aren't magic
AWS VPC, Azure VNet - they're all using these same Linux primitives under the hood. Now when I use cloud VPCs, I know what's really happening.&lt;/li&gt;
&lt;li&gt;Docker and Kubernetes make more sense now
Every Docker container uses network namespaces. Kubernetes CNI plugins are just automating what I built manually. Suddenly, all those networking concepts in the docs make sense!&lt;/li&gt;
&lt;li&gt;Debugging is a superpower
I spent more time debugging than coding. But each bug taught me something:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Read error messages carefully&lt;br&gt;
Test in isolation&lt;br&gt;
Don't hide errors during development&lt;br&gt;
Check assumptions (my iptables rules existed, but weren't working!)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Documentation is hard but essential
Writing this blog post helped me understand my own project better. Explaining concepts forced me to really understand them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🎓 For Anyone Wanting to Try This&lt;br&gt;
Start Here&lt;/p&gt;

&lt;p&gt;Learn the basics first&lt;/p&gt;

&lt;p&gt;What is a network namespace?&lt;br&gt;
What is a Linux bridge?&lt;br&gt;
How does NAT work?&lt;/p&gt;

&lt;p&gt;Build incrementally&lt;/p&gt;

&lt;p&gt;Create one namespace&lt;br&gt;
Connect it to a bridge&lt;br&gt;
Add internet access (NAT)&lt;br&gt;
Then add isolation, peering, etc.&lt;/p&gt;

&lt;p&gt;Test everything&lt;/p&gt;

&lt;p&gt;Write tests before adding features&lt;br&gt;
Test in isolation&lt;br&gt;
Verify expected failures (isolation should block traffic!)&lt;/p&gt;

&lt;p&gt;Don't hide errors&lt;/p&gt;

&lt;p&gt;Let yourself see what's breaking&lt;br&gt;
Read error messages&lt;br&gt;
Google is your friend&lt;/p&gt;

&lt;p&gt;Resources That Helped Me&lt;/p&gt;

&lt;p&gt;Linux Network Namespaces Man Page&lt;br&gt;
iptables Tutorial&lt;br&gt;
How Docker Networking Works&lt;br&gt;
Stack Overflow (obviously 😄)&lt;/p&gt;

&lt;p&gt;💡 Real-World Applications&lt;br&gt;
This project isn't just academic. Understanding these concepts helps with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Troubleshooting Docker&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Now I understand what this actually does
&lt;/h1&gt;

&lt;p&gt;docker network inspect bridge&lt;/p&gt;

&lt;h1&gt;
  
  
  And this makes sense
&lt;/h1&gt;

&lt;p&gt;docker run --network=host&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kubernetes Networking&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  CNI plugins are doing what I just built
&lt;/h1&gt;

&lt;p&gt;apiVersion: v1&lt;br&gt;
kind: NetworkPolicy&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cloud VPC Design&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  I now understand why this matters
&lt;/h1&gt;

&lt;p&gt;aws ec2 create-vpc --cidr-block 10.0.0.0/16&lt;/p&gt;

&lt;p&gt;🚀 The Code&lt;br&gt;
Full project on GitHub: github.com/Sheviantos1/hng13-devops-stage4-vpc&lt;/p&gt;

&lt;p&gt;Quick Start&lt;/p&gt;

&lt;h1&gt;
  
  
  Clone the repo
&lt;/h1&gt;

&lt;p&gt;git clone &lt;a href="https://github.com/Sheviantos1/hng13-devops-stage4-vpc.git" rel="noopener noreferrer"&gt;https://github.com/Sheviantos1/hng13-devops-stage4-vpc.git&lt;/a&gt;&lt;br&gt;
cd hng13-devops-stage4-vpc&lt;/p&gt;

&lt;h1&gt;
  
  
  Run the test suite
&lt;/h1&gt;

&lt;p&gt;./test.sh&lt;/p&gt;

&lt;h1&gt;
  
  
  Try it yourself
&lt;/h1&gt;

&lt;p&gt;sudo ./vpcctl.py create-vpc --name test --cidr 10.0.1.1/24&lt;/p&gt;

&lt;p&gt;🎯 Key Takeaways&lt;/p&gt;

&lt;p&gt;Cloud services use the same Linux primitives you can learn and use yourself&lt;br&gt;
Network isolation is fundamental to modern infrastructure&lt;br&gt;
iptables is powerful but needs careful, specific rules&lt;br&gt;
Building from scratch teaches you way more than using abstractions&lt;br&gt;
Debugging skills are more valuable than coding speed&lt;/p&gt;

&lt;p&gt;🙏 Acknowledgments&lt;/p&gt;

&lt;p&gt;HNG Internship for the challenging project&lt;br&gt;
The Linux networking community for amazing documentation&lt;br&gt;
Stack Overflow for saving me countless times&lt;br&gt;
Everyone who helped debug those iptables issues&lt;/p&gt;

&lt;p&gt;💬 Let's Connect&lt;br&gt;
If you found this helpful or have questions:&lt;/p&gt;

&lt;p&gt;GitHub: @Sheviantos1&lt;br&gt;
Twitter: [&lt;a class="mentioned-user" href="https://dev.to/sheviantos"&gt;@sheviantos&lt;/a&gt;]&lt;br&gt;
LinkedIn: [@Ademoye-sheriff]&lt;/p&gt;

&lt;p&gt;Building something similar? Drop a comment - I'd love to hear about your approach!&lt;/p&gt;

</description>
      <category>networking</category>
      <category>devops</category>
      <category>linux</category>
      <category>cloudcomputing</category>
    </item>
  </channel>
</rss>
