Google Cloudadvanced

GCP VPC Network Segmentation: Subnets, Firewall Rules, and VPC Service Controls

Complete guide to implementing network segmentation in Google Cloud. Covers VPC design, subnet planning, firewall rules, Shared VPC architecture, and VPC Service Controls for data exfiltration prevention.

14 min readUpdated 2026-01-13

Want us to handle this for you?

Get expert help →

Network segmentation is a critical defense-in-depth strategy that limits an attacker's ability to move laterally after initial compromise. A flat network allows attackers to pivot from a compromised web server to databases containing sensitive data. Proper segmentation creates security boundaries that contain breaches.

This guide covers VPC architecture, firewall configuration, and advanced controls like VPC Service Controls. This expands on Tip 11 from our 30 Cloud Security Tips for 2026 guide on implementing network segmentation.

GitHub Repository: All scripts and configurations from this guide are available at github.com/InventiveHQ/gcp-network-segmentation-terraform. Clone the repo to get started quickly.

VPC Architecture Overview

A well-designed GCP network architecture includes:

  • Separate VPCs - Production vs. non-production environments
  • Tiered subnets - Web, application, and database tiers
  • Firewall rules - Explicit allow rules between tiers
  • VPC Service Controls - Data exfiltration prevention
  • Private Google Access - Access Google APIs without public IPs

Step 1: Create VPC Networks

Create separate VPCs for environment isolation:

Via Google Cloud Console

  1. Navigate to VPC Network

  2. Click Create VPC Network

  3. Configure:

  4. Name: prod-vpc

  5. Subnet creation mode: Custom

  6. MTU: 1460 (default) or 1500 for jumbo frames

  7. Add subnets for each tier (see Step 2)

  8. Click Create

Via gcloud CLI

# Create production VPC
gcloud compute networks create prod-vpc \
  --subnet-mode=custom \
  --bgp-routing-mode=regional \
  --project=PROJECT_ID

# Create staging VPC
gcloud compute networks create staging-vpc \
  --subnet-mode=custom \
  --bgp-routing-mode=regional \
  --project=PROJECT_ID

# Create development VPC
gcloud compute networks create dev-vpc \
  --subnet-mode=custom \
  --bgp-routing-mode=regional \
  --project=PROJECT_ID

Via Terraform

resource "google_compute_network" "prod_vpc" {
  name                    = "prod-vpc"
  auto_create_subnetworks = false
  routing_mode            = "REGIONAL"
  project                 = var.project_id
}

resource "google_compute_network" "staging_vpc" {
  name                    = "staging-vpc"
  auto_create_subnetworks = false
  routing_mode            = "REGIONAL"
  project                 = var.project_id
}

resource "google_compute_network" "dev_vpc" {
  name                    = "dev-vpc"
  auto_create_subnetworks = false
  routing_mode            = "REGIONAL"
  project                 = var.project_id
}

Step 2: Create Subnets for Network Tiers

Create subnets to segment by application tier:

Via gcloud CLI

# Web tier subnet (public-facing load balancers)
gcloud compute networks subnets create prod-web-subnet \
  --network=prod-vpc \
  --region=us-central1 \
  --range=10.0.1.0/24 \
  --enable-private-ip-google-access \
  --project=PROJECT_ID

# Application tier subnet
gcloud compute networks subnets create prod-app-subnet \
  --network=prod-vpc \
  --region=us-central1 \
  --range=10.0.2.0/24 \
  --enable-private-ip-google-access \
  --project=PROJECT_ID

# Database tier subnet
gcloud compute networks subnets create prod-db-subnet \
  --network=prod-vpc \
  --region=us-central1 \
  --range=10.0.3.0/24 \
  --enable-private-ip-google-access \
  --project=PROJECT_ID

# Management/bastion subnet
gcloud compute networks subnets create prod-mgmt-subnet \
  --network=prod-vpc \
  --region=us-central1 \
  --range=10.0.10.0/24 \
  --enable-private-ip-google-access \
  --project=PROJECT_ID

Via Terraform

resource "google_compute_subnetwork" "prod_web" {
  name          = "prod-web-subnet"
  ip_cidr_range = "10.0.1.0/24"
  region        = "us-central1"
  network       = google_compute_network.prod_vpc.id

  private_ip_google_access = true

  log_config {
    aggregation_interval = "INTERVAL_5_SEC"
    flow_sampling        = 0.5
    metadata             = "INCLUDE_ALL_METADATA"
  }
}

resource "google_compute_subnetwork" "prod_app" {
  name          = "prod-app-subnet"
  ip_cidr_range = "10.0.2.0/24"
  region        = "us-central1"
  network       = google_compute_network.prod_vpc.id

  private_ip_google_access = true

  log_config {
    aggregation_interval = "INTERVAL_5_SEC"
    flow_sampling        = 0.5
    metadata             = "INCLUDE_ALL_METADATA"
  }
}

resource "google_compute_subnetwork" "prod_db" {
  name          = "prod-db-subnet"
  ip_cidr_range = "10.0.3.0/24"
  region        = "us-central1"
  network       = google_compute_network.prod_vpc.id

  private_ip_google_access = true

  log_config {
    aggregation_interval = "INTERVAL_5_SEC"
    flow_sampling        = 0.5
    metadata             = "INCLUDE_ALL_METADATA"
  }
}

Step 3: Configure Firewall Rules

Create explicit allow rules between tiers:

Delete Default Rules

Remove overly permissive default rules:

# List default rules
gcloud compute firewall-rules list --filter="network=prod-vpc" --project=PROJECT_ID

# Delete default-allow-internal if it exists
gcloud compute firewall-rules delete default-allow-internal --project=PROJECT_ID

Create Tier-Based Rules

# Allow HTTPS from anywhere to web tier (through load balancer)
gcloud compute firewall-rules create prod-allow-lb-to-web \
  --network=prod-vpc \
  --direction=INGRESS \
  --priority=1000 \
  --action=ALLOW \
  --rules=tcp:80,tcp:443 \
  --source-ranges=130.211.0.0/22,35.191.0.0/16 \
  --target-tags=web-tier \
  --project=PROJECT_ID

# Allow web tier to app tier
gcloud compute firewall-rules create prod-allow-web-to-app \
  --network=prod-vpc \
  --direction=INGRESS \
  --priority=1000 \
  --action=ALLOW \
  --rules=tcp:8080 \
  --source-tags=web-tier \
  --target-tags=app-tier \
  --project=PROJECT_ID

# Allow app tier to database tier
gcloud compute firewall-rules create prod-allow-app-to-db \
  --network=prod-vpc \
  --direction=INGRESS \
  --priority=1000 \
  --action=ALLOW \
  --rules=tcp:5432,tcp:3306 \
  --source-tags=app-tier \
  --target-tags=db-tier \
  --project=PROJECT_ID

# Allow SSH from bastion only
gcloud compute firewall-rules create prod-allow-bastion-ssh \
  --network=prod-vpc \
  --direction=INGRESS \
  --priority=1000 \
  --action=ALLOW \
  --rules=tcp:22 \
  --source-tags=bastion \
  --target-tags=web-tier,app-tier,db-tier \
  --project=PROJECT_ID

# Deny all other internal traffic (explicit deny for logging)
gcloud compute firewall-rules create prod-deny-internal-all \
  --network=prod-vpc \
  --direction=INGRESS \
  --priority=65534 \
  --action=DENY \
  --rules=all \
  --source-ranges=10.0.0.0/8 \
  --enable-logging \
  --project=PROJECT_ID

Terraform Firewall Rules

resource "google_compute_firewall" "allow_lb_to_web" {
  name    = "prod-allow-lb-to-web"
  network = google_compute_network.prod_vpc.name

  allow {
    protocol = "tcp"
    ports    = ["80", "443"]
  }

  source_ranges = ["130.211.0.0/22", "35.191.0.0/16"]
  target_tags   = ["web-tier"]
  priority      = 1000
}

resource "google_compute_firewall" "allow_web_to_app" {
  name    = "prod-allow-web-to-app"
  network = google_compute_network.prod_vpc.name

  allow {
    protocol = "tcp"
    ports    = ["8080"]
  }

  source_tags = ["web-tier"]
  target_tags = ["app-tier"]
  priority    = 1000
}

resource "google_compute_firewall" "allow_app_to_db" {
  name    = "prod-allow-app-to-db"
  network = google_compute_network.prod_vpc.name

  allow {
    protocol = "tcp"
    ports    = ["5432", "3306"]
  }

  source_tags = ["app-tier"]
  target_tags = ["db-tier"]
  priority    = 1000
}

resource "google_compute_firewall" "deny_all_internal" {
  name    = "prod-deny-internal-all"
  network = google_compute_network.prod_vpc.name

  deny {
    protocol = "all"
  }

  source_ranges = ["10.0.0.0/8"]
  priority      = 65534

  log_config {
    metadata = "INCLUDE_ALL_METADATA"
  }
}

Step 4: Implement Shared VPC (Enterprise)

For large organizations, use Shared VPC to centralize network management:

Enable Shared VPC

# Enable host project
gcloud compute shared-vpc enable HOST_PROJECT_ID

# Attach service project
gcloud compute shared-vpc associated-projects add SERVICE_PROJECT_ID \
  --host-project=HOST_PROJECT_ID

Grant Subnet Access

# Grant service project access to specific subnet
gcloud compute networks subnets add-iam-policy-binding prod-app-subnet \
  --region=us-central1 \
  --member="serviceAccount:[email protected]" \
  --role="roles/compute.networkUser" \
  --project=HOST_PROJECT_ID

Terraform Shared VPC

resource "google_compute_shared_vpc_host_project" "host" {
  project = var.host_project_id
}

resource "google_compute_shared_vpc_service_project" "service" {
  host_project    = google_compute_shared_vpc_host_project.host.project
  service_project = var.service_project_id
}

resource "google_compute_subnetwork_iam_member" "network_user" {
  project    = var.host_project_id
  region     = "us-central1"
  subnetwork = google_compute_subnetwork.prod_app.name
  role       = "roles/compute.networkUser"
  member     = "serviceAccount:${var.service_project_number}@cloudservices.gserviceaccount.com"
}

Step 5: Configure VPC Service Controls

Create security perimeters to prevent data exfiltration:

Create Access Policy

# Create access policy (organization level)
gcloud access-context-manager policies create \
  --organization=ORGANIZATION_ID \
  --title="Production Security Policy"

Create Service Perimeter

# Create a perimeter protecting Cloud Storage and BigQuery
gcloud access-context-manager perimeters create prod-perimeter \
  --title="Production Perimeter" \
  --resources="projects/PROJECT_NUMBER" \
  --restricted-services="storage.googleapis.com,bigquery.googleapis.com" \
  --policy=POLICY_NUMBER

Create Access Level for Trusted Networks

# Create access level for corporate IP ranges
gcloud access-context-manager levels create trusted-network \
  --title="Trusted Network" \
  --basic-level-spec="ipSubnetworks=203.0.113.0/24,198.51.100.0/24" \
  --combine-function=AND \
  --policy=POLICY_NUMBER

# Update perimeter to allow access level
gcloud access-context-manager perimeters update prod-perimeter \
  --add-access-levels=trusted-network \
  --policy=POLICY_NUMBER

Terraform VPC Service Controls

resource "google_access_context_manager_access_policy" "policy" {
  parent = "organizations/${var.organization_id}"
  title  = "Production Security Policy"
}

resource "google_access_context_manager_access_level" "trusted_network" {
  parent = "accessPolicies/${google_access_context_manager_access_policy.policy.name}"
  name   = "accessPolicies/${google_access_context_manager_access_policy.policy.name}/accessLevels/trusted_network"
  title  = "Trusted Network"

  basic {
    conditions {
      ip_subnetworks = ["203.0.113.0/24", "198.51.100.0/24"]
    }
  }
}

resource "google_access_context_manager_service_perimeter" "prod_perimeter" {
  parent = "accessPolicies/${google_access_context_manager_access_policy.policy.name}"
  name   = "accessPolicies/${google_access_context_manager_access_policy.policy.name}/servicePerimeters/prod_perimeter"
  title  = "Production Perimeter"

  status {
    resources = ["projects/${var.project_number}"]

    restricted_services = [
      "storage.googleapis.com",
      "bigquery.googleapis.com"
    ]

    access_levels = [
      google_access_context_manager_access_level.trusted_network.name
    ]
  }
}

Step 6: Enable VPC Flow Logs

Monitor network traffic for security analysis:

# Enable flow logs on existing subnet
gcloud compute networks subnets update prod-app-subnet \
  --region=us-central1 \
  --enable-flow-logs \
  --logging-aggregation-interval=interval-5-sec \
  --logging-flow-sampling=0.5 \
  --logging-metadata=include-all \
  --project=PROJECT_ID

Best Practices Summary

  • Separate VPCs per environment - Production, staging, development isolation
  • Use subnet tiers - Web, app, database with explicit firewall rules
  • Default deny - Only allow explicitly required traffic
  • Use network tags or service accounts - More flexible than IP-based rules
  • Enable VPC Flow Logs - For traffic analysis and forensics
  • Implement VPC Service Controls - Prevent data exfiltration
  • Use Private Google Access - Access APIs without public IPs
  • Deploy Cloud NAT - Outbound internet without public IPs

Need help designing a secure network architecture for your Google Cloud environment? Contact InventiveHQ for expert guidance on VPC design and security controls.

Frequently Asked Questions

Find answers to common questions

A standard VPC Network exists within a single project and resources in that VPC are managed by that project. Shared VPC allows a VPC to be shared across multiple projects in an organization - the VPC is owned by a host project while service projects can create resources that use subnets from the host project. Shared VPC enables centralized network management while maintaining project-level resource isolation, and is recommended for enterprise deployments.

GCP firewall rules are applied at the VPC level and can target instances by network tags or service accounts, while AWS Security Groups are attached directly to instances. GCP rules have explicit priority ordering (0-65535), while AWS evaluates all rules together. GCP supports both ingress and egress rules by default with an implicit deny, similar to AWS. GCP also offers hierarchical firewall policies at the organization and folder level that AWS doesn't have.

VPC Service Controls creates security perimeters around GCP services to prevent data exfiltration. It blocks API calls to services from outside the perimeter, even by authenticated users. Use VPC Service Controls when you need to prevent data copying to unauthorized projects, meet compliance requirements for data residency, or protect against insider threats. It's essential for regulated industries handling sensitive data like healthcare, finance, or government.

The recommended approach depends on your isolation requirements. For most organizations, use separate VPCs for production vs. non-production to provide strong isolation. Within each VPC, use subnets to segment by tier (web, app, database) or function. If you need shared services across environments (like a bastion host or DNS), use VPC Peering or Shared VPC. Never put production and development workloads in the same VPC unless you have very strict firewall rules.

GCP offers several connectivity options: Cloud VPN for encrypted tunnels over the internet (up to 3 Gbps per tunnel), Cloud Interconnect Dedicated for private physical connections (10-200 Gbps), Partner Interconnect for connections through a service provider, and Cloud Router for dynamic BGP routing. For most hybrid deployments, start with Cloud VPN and migrate to Interconnect as bandwidth needs grow. Use Network Connectivity Center for hub-and-spoke architectures.

Expert GCP Management

From architecture design to managed operations, we handle your Google Cloud infrastructure.