A complete implementation of AWS-style Virtual Private Cloud (VPC) functionality using Linux networking primitives.
NOTE: This repo includes both an automated demo driven by the Makefile (run
make demoormake test) and a set of individual scripts/commands (quick_setup.sh,test_vpc.sh,create_examples.shandvpcctl.py) so you can either run the full demo end-to-end or execute the steps manually for finer control. The project is intentionally structured this way to make it easy to reproduce the demo or dig into each operation step-by-step.
This project creates isolated virtual networks on a single Linux host using:
- Network Namespaces: Isolated network environments (subnets)
- Linux Bridges: Virtual switches connecting subnets
- veth Pairs: Virtual ethernet connections
- iptables: Firewall rules and NAT gateway
- Routing Tables: Inter-subnet and inter-VPC routing
Host System
βββ VPC 1 (10.0.0.0/16)
β βββ Bridge: vpc1-br0
β βββ Public Subnet (10.0.1.0/24) [Namespace]
β β βββ Web Server (NAT enabled)
β βββ Private Subnet (10.0.2.0/24) [Namespace]
β βββ Web Server (No internet)
β
βββ VPC 2 (172.16.0.0/16)
βββ Bridge: vpc2-br0
βββ Public Subnet (172.16.1.0/24) [Namespace]
βββ Web Server
- Linux system with root/sudo access
- Python 3.6+
- Standard Linux networking tools:
iproute2(ip command)iptablesbridge-utils
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y iproute2 iptables bridge-utils python3
# RHEL/CentOS
sudo yum install -y iproute iptables bridge-utils python3git clone <your-repo-url>
cd vpc-on-linux
chmod +x vpcctl.py test_vpc.sh# Create VPC
sudo ./vpcctl.py create-vpc my-vpc 10.0.0.0/16
# Add public subnet with NAT
sudo ./vpcctl.py add-subnet my-vpc web-subnet 10.0.1.0/24 --type public
# Add private subnet
sudo ./vpcctl.py add-subnet my-vpc db-subnet 10.0.2.0/24 --type private
# Deploy web servers
sudo ./vpcctl.py deploy-app my-vpc web-subnet --port 8000
sudo ./vpcctl.py deploy-app my-vpc db-subnet --port 8001
# List all VPCs
sudo ./vpcctl.py list# Get subnet IPs
WEB_IP=$(sudo ip netns exec my-vpc-web-subnet ip addr show veth-ns-web-subnet | grep "inet " | awk '{print $2}' | cut -d'/' -f1)
DB_IP=$(sudo ip netns exec my-vpc-db-subnet ip addr show veth-ns-db-subnet | grep "inet " | awk '{print $2}' | cut -d'/' -f1)
# Test from host
curl http://$WEB_IP:8000
# Test inter-subnet communication
sudo ip netns exec my-vpc-web-subnet curl http://$DB_IP:8001
# Test internet access from public subnet
sudo ip netns exec my-vpc-web-subnet ping -c 3 8.8.8.8
# Test internet access from private subnet (should fail)
sudo ip netns exec my-vpc-db-subnet ping -c 3 8.8.8.8sudo ./vpcctl.py create-vpc <vpc-name> <cidr-block> [--interface <interface>]
# Example
sudo ./vpcctl.py create-vpc production 10.0.0.0/16 --interface eth0sudo ./vpcctl.py add-subnet <vpc-name> <subnet-name> <cidr> [--type public|private]
# Examples
sudo ./vpcctl.py add-subnet production public-web 10.0.1.0/24 --type public
sudo ./vpcctl.py add-subnet production private-db 10.0.2.0/24 --type privatesudo ./vpcctl.py deploy-app <vpc-name> <subnet-name> [--port <port>]
# Example
sudo ./vpcctl.py deploy-app production public-web --port 8080Create a JSON file with rules:
{
"subnet": "10.0.1.0/24",
"ingress": [
{"port": 80, "protocol": "tcp", "action": "allow"},
{"port": 443, "protocol": "tcp", "action": "allow"},
{"port": 22, "protocol": "tcp", "action": "deny"}
]
}Apply rules:
sudo ./vpcctl.py apply-firewall <vpc-name> <subnet-name> <rules-file>
# Example
sudo ./vpcctl.py apply-firewall production public-web firewall_rules.jsonsudo ./vpcctl.py peer-vpcs <vpc1-name> <vpc2-name>
# Example
sudo ./vpcctl.py peer-vpcs production stagingsudo ./vpcctl.py listsudo ./vpcctl.py delete-vpc <vpc-name>
# Example
sudo ./vpcctl.py delete-vpc productionsudo ./vpcctl.py cleanupRun the complete test suite:
sudo ./test_vpc.shThis script will:
- Create two VPCs with multiple subnets
- Deploy web servers in each subnet
- Test intra-VPC connectivity
- Verify VPC isolation
- Create VPC peering
- Apply and verify firewall rules
- Test NAT gateway functionality
- Display all resources
# Create VPC with two subnets
sudo ./vpcctl.py create-vpc test-vpc 192.168.0.0/16
sudo ./vpcctl.py add-subnet test-vpc subnet-a 192.168.1.0/24
sudo ./vpcctl.py add-subnet test-vpc subnet-b 192.168.2.0/24
sudo ./vpcctl.py deploy-app test-vpc subnet-a --port 8000
sudo ./vpcctl.py deploy-app test-vpc subnet-b --port 8001
# Test connectivity
IP_A=$(sudo ip netns exec test-vpc-subnet-a ip addr show veth-ns-subnet-a | grep "inet " | awk '{print $2}' | cut -d'/' -f1)
IP_B=$(sudo ip netns exec test-vpc-subnet-b ip addr show veth-ns-subnet-b | grep "inet " | awk '{print $2}' | cut -d'/' -f1)
# Subnet A -> Subnet B
sudo ip netns exec test-vpc-subnet-a ping -c 3 $IP_B
sudo ip netns exec test-vpc-subnet-a curl http://$IP_B:8001
# Expected: Success β# Create two VPCs
sudo ./vpcctl.py create-vpc vpc-a 10.1.0.0/16
sudo ./vpcctl.py add-subnet vpc-a subnet-a 10.1.1.0/24 --type public
sudo ./vpcctl.py create-vpc vpc-b 10.2.0.0/16
sudo ./vpcctl.py add-subnet vpc-b subnet-b 10.2.1.0/24 --type public
# Try to ping across VPCs
IP_A=$(sudo ip netns exec vpc-a-subnet-a ip addr show veth-ns-subnet-a | grep "inet " | awk '{print $2}' | cut -d'/' -f1)
IP_B=$(sudo ip netns exec vpc-b-subnet-b ip addr show veth-ns-subnet-b | grep "inet " | awk '{print $2}' | cut -d'/' -f1)
sudo ip netns exec vpc-a-subnet-a ping -c 3 $IP_B
# Expected: Failure (timeout) β# Public subnet should have internet access
sudo ip netns exec test-vpc-public-subnet ping -c 3 8.8.8.8
sudo ip netns exec test-vpc-public-subnet curl -I https://www.google.com
# Expected: Success β
# Private subnet should NOT have internet access
sudo ip netns exec test-vpc-private-subnet ping -c 3 8.8.8.8
# Expected: Failure β# Create rule file
cat > /tmp/test_rules.json <<EOF
{
"subnet": "10.0.1.0/24",
"ingress": [
{"port": 8000, "protocol": "tcp", "action": "allow"},
{"port": 8080, "protocol": "tcp", "action": "deny"}
]
}
EOF
sudo ./vpcctl.py apply-firewall test-vpc public-subnet /tmp/test_rules.json
# Verify rules are applied
sudo ip netns exec test-vpc-public-subnet iptables -L -n
# Expected: Rules visible in iptables β# Create peering
sudo ./vpcctl.py peer-vpcs vpc-a vpc-b
# Test connectivity after peering
sudo ip netns exec vpc-a-subnet-a ping -c 3 $IP_B
# Expected: Success β# List all network namespaces
sudo ip netns list
# List all bridges
sudo ip link show type bridge
# Check routes in a namespace
sudo ip netns exec <namespace> ip route
# Check iptables rules in namespace
sudo ip netns exec <namespace> iptables -L -n
# Check NAT rules
sudo iptables -t nat -L -n
# Monitor traffic on bridge
sudo tcpdump -i vpc1-br0 -n
# Check active connections
sudo ss -tunap# Check bridge is up
sudo ip link show vpc1-br0
# Check veth pairs exist
sudo ip link | grep veth
# Check namespace has correct IP
sudo ip netns exec <namespace> ip addr# Check IP forwarding is enabled
sudo sysctl net.ipv4.ip_forward
# Check NAT rules exist
sudo iptables -t nat -L -n | grep MASQUERADE
# Check default route in namespace
sudo ip netns exec <namespace> ip route# Check bridge has correct IP
sudo ip addr show vpc1-br0
# Check routes in namespace
sudo ip netns exec <namespace> ip route
# Test connectivity to bridge
sudo ip netns exec <namespace> ping <bridge-ip>sudo ./vpcctl.py delete-vpc <vpc-name>sudo ./vpcctl.py cleanup
# Manual cleanup if needed
sudo ip -all netns delete
sudo ip link delete $(ip link show type bridge | grep vpc | awk '{print $2}' | tr -d ':')
sudo iptables -t nat -F
sudo iptables -FThe tool maintains state in /tmp/vpcctl_state.json:
{
"vpcs": {
"vpc1": {
"cidr": "10.0.0.0/16",
"bridge": "vpc1-br0",
"bridge_ip": "10.0.0.1",
"subnets": {
"public-subnet": {
"cidr": "10.0.1.0/24",
"type": "public",
"namespace": "vpc1-public-subnet",
"ip": "10.0.1.1"
}
}
}
}
}- All operations require root/sudo privileges
- Firewall rules are enforced at the namespace level
- NAT provides isolation from external networks
- Private subnets have no internet access by default
- VPC isolation prevents unauthorized cross-VPC traffic
Each subnet is a network namespace - an isolated network environment with its own routing table, firewall rules, and network interfaces.
The bridge acts as a virtual switch, connecting all subnets within a VPC and handling packet forwarding between them.
Virtual ethernet pairs connect namespaces to bridges. One end is in the namespace, the other is attached to the bridge.
For public subnets, iptables MASQUERADE rules translate private IPs to the host's public IP for outbound traffic.
A veth pair connects two bridges, with static routes allowing traffic flow between VPC CIDR blocks.
- β Create and manage VPCs with CIDR blocks
- β Add public and private subnets
- β Enable routing between subnets
- β Implement NAT for public subnet internet access
- β Demonstrate VPC isolation
- β Implement VPC peering
- β Apply firewall rules (Security Groups)
- β Automate with CLI tool
- β Clean resource teardown
- β Comprehensive logging
Feel free to submit issues and enhancement requests!
This project is for educational purposes as part of the DevOps Internship program.