Configuring SNAT with GCP CloudNAT
Sometimes, our servers need to access the Internet using a specific public IP address. This is particularly useful when working with databases, third-party services, or API providers that allow IP whitelisting. SNAT (Source Network Address Translation) is the protocol responsible for translating private IP addresses to public ones when communicating with external networks (e.g., the Internet).
In this post, I'll show you how to configure SNAT using Google Cloud Platform service CloudNAT.
This guide assumes you already have a Terraform project set up with the Google provider.
IP address
First, let's reserve our static public IP:
resource "google_compute_address" "this" {
name = "my-public-ip"
}
Network
Now, we'll create a network and subnetwork where the CloudNAT router will be attached:
resource "google_compute_network" "this" {
name = "my-network"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "this" {
name = "my-subnetwork"
ip_cidr_range = "10.0.1.0/24"
network = google_compute_network.this.self_link
}
CloudNAT
With the subnetwork and reserved IP address in place, we can create the CloudNAT router:
resource "google_compute_router" "this" {
name = "my-router"
network = google_compute_network.this.name
}
resource "google_compute_router_nat" "this" {
name = "my-nat-router"
router = google_compute_router.this.name
nat_ip_allocate_option = "MANUAL_ONLY"
nat_ips = [google_compute_address.this.self_link]
source_subnetwork_ip_ranges_to_nat = "LIST_OF_SUBNETWORKS"
subnetwork {
name = google_compute_subnetwork.this.name
source_ip_ranges_to_nat = ["ALL_IP_RANGES"]
}
}
We use nat_ip_allocate_option = "MANUAL_ONLY"
because we're specifying the public IP, preventing Google Cloud Platform from assigning one automatically.
The nat_ips = [google_compute_address.this.self_link]
line indicates our public IP. Note that this is an array, so we could use multiple IP addresses if needed.
By using source_subnetwork_ip_ranges_to_nat = "LIST_OF_SUBNETWORKS"
and the subnetwork
block, we specify that all IPs in the subnetwork ("ALL_IP_RANGES"
) should use the static IP when connecting to the Internet.
Other configurations are available. Check the Terraform documentation for more options.
With this setup, every VM instance running inside the subnetwork where the NAT router is attached (including Kubernetes nodes) will use our reserved static IP address when accessing the Internet.