A free IPv6 network and one locked door

Subhankar Denria
Software Architect · Product Engineer
What this part does
Give the server a private network with a free public IPv6 address instead of a paid IPv4 one, and a firewall that lets exactly one thing in — you, through Google's own login relay.
- Time
- About 5 minutes of clicking — the ideas take longer
- Saves
- ~$3.65 a month, by skipping IPv4
- If you skip a step
- A firewall rule that looks right and protects nothing
First, why no IPv4?
Every device on the internet needs an address. There are two formats:
- IPv4 — the old one, like
34.121.8.15. There are only about 4 billion of them, and they ran out years ago, so they cost money. - IPv6 — the new one, like
2600:1900:4001:…. There are so many that they're handed out freely.
Google charges for every public IPv4 address attached to a running server — about $0.005 an hour, roughly $3.65 a month, even on the free e2-micro. External IPv6 addresses cost nothing.
So the plan is: the server gets a public IPv6 address and no public IPv4 at all. It still has a private IPv4 address for talking to Google's own services inside the data centre — that one is free and invisible from the internet.
IPv4
34.121.8.15How many exist
4,294,967,296
about 4 billion — they ran out years ago
On a running server
$0.005 an hour · ~$3.65 a month
Since this card appeared, one would have cost
$0.00000000
…and ~$43.80 a year, forever.
IPv6
2600:1900:4001:…How many exist
340,282,366,920,938,463,463,374,607,431,768,211,456
about 340 undecillion — handed out freely
On a running server
Free
This server uses
IPv6 only
It only ever calls out, so nobody on IPv4 needs to reach it.
What does "IPv6 only" break?
Less than you'd fear. Ubuntu's package servers, Cloudflare, healthchecks.io and Cloudflare R2 all speak IPv6. The notable exception is GitHub, which has no IPv6 address — so the server can't download code or PHP libraries from it. Post 5 shows the simple workaround: build the app on your laptop and upload the finished package.
And because the server will only ever call out (to Cloudflare, to the alarm service, to the backup store), nobody on the IPv4 internet needs to reach it anyway.
Step 1 — Switch on Compute Engine
In the search bar at the top, type Compute Engine API → Enable. It takes one to three minutes.
Why: new projects start with servers and networks switched off. Without this, the network page just says "Data could not be loaded" and offers no buttons — which looks like something is broken.
Then ☰ → VPC network → VPC networks → Refresh. A network called default has appeared. Leave it alone; nothing goes on it.
Why not use default? It's an "auto mode" network that Google fills with IPv4 subnets in 40-odd regions — and it can't do IPv6. We need our own.
Step 2 — Create the network
VPC stands for "virtual private cloud": a private network that you own, inside Google's data centres. Create VPC network:
| Field | Value | Why |
|---|---|---|
| Name | lampsill-net | Any name; this one's easy to recognise |
| Subnet creation mode | Custom | You choose the one region, instead of Google creating subnets everywhere. Custom mode is also required for IPv6 |
| Subnet → Name | lampsill-us | |
| Subnet → Region | us-central1 | One of the three free regions — and it must match the server's |
| IP stack type | IPv4 and IPv6 (dual-stack) | Private IPv4 inside Google, public IPv6 for the internet |
| IPv4 range | 10.10.0.0/24 | A private range (256 addresses), never reachable from the internet |
| IPv6 access type | External | The part that gives the server free internet access |
| Firewall rules | Tick nothing — on the IPv4 tab and the IPv6 tab | The suggested rules open SSH and remote desktop to the whole internet |
| DNS Armor | Disabled | A paid threat-detection service — see below |
| Dynamic routing | Leave the default | Only matters for VPNs |
Name
- Value
lampsill-net- Why
- Any name; this one's easy to recognise
Subnet creation mode
- Value
- Custom
- Why
- You choose the one region, instead of Google creating subnets everywhere. Custom mode is also required for IPv6
Subnet → Name
- Value
lampsill-us
Subnet → Region
- Value
- us-central1
- Why
- One of the three free regions — and it must match the server's
IP stack type
- Value
- IPv4 and IPv6 (dual-stack)
- Why
- Private IPv4 inside Google, public IPv6 for the internet
IPv4 range
- Value
10.10.0.0/24- Why
- A private range (256 addresses), never reachable from the internet
IPv6 access type
- Value
- External
- Why
- The part that gives the server free internet access
Firewall rules
- Value
- Tick nothing — on the IPv4 tab and the IPv6 tab
- Why
- The suggested rules open SSH and remote desktop to the whole internet
DNS Armor
- Value
- Disabled
- Why
- A paid threat-detection service — see below
Dynamic routing
- Value
- Leave the default
- Why
- Only matters for VPNs
→ Create.
The IPv6 firewall tab matters most
With External IPv6, the server gets an address the whole internet can reach. The firewall is the only thing standing in front of it. The form offers ready-made rules like allow-ipv6-ssh — leave them unticked. What remains are two invisible built-in rules: deny everything coming in, allow everything going out. That's exactly what we want, plus one exception in the next step.
DNS Armor is a trap
Further down, under "Additional security configuration", there's DNS Armor. I clicked its Enable button to see what it did. That switched on an API — harmless and free on its own — and then quietly preselected "Enable for this network", with the small print "Additional costs apply." Set it back to Disabled before creating the network.
Step 3 — One firewall rule
Here's the problem this rule solves. You'll manage the server through the SSH button in Google's console, which opens a terminal in your browser. Normally that connects to the server's public IPv4 address — which our server doesn't have. Instead, Google routes it through its own relay, called IAP ("Identity-Aware Proxy"). The relay only lets through people signed in to your Google account.
Our "deny everything" firewall blocks the relay too. So we open exactly one door: port 22 (SSH), and only from Google's relay addresses.
- Denied
Anyone on the internet → port 443 · HTTPS
No web port is open. Visitors come through the tunnel instead.
- Denied
Anyone on the internet → port 80 · HTTP
Same: nothing listens to the outside.
- Denied
Anyone on the internet → port 22 · SSH
The ready-made rule that would open this was left unticked.
- Denied
Anyone on the internet → port 3389 · remote desktop
Also offered on the form. Also unticked.
- Allowed
Google's SSH relay · 35.235.240.0/20 → port 22 · SSH
The one door. Only people signed in to your Google account get through the relay.
VPC network → Firewall (it may open a page called Firewall policies) → Create firewall rule. Not "Create firewall policy" — that's a heavier feature for organizations.
| Field | Value | Why |
|---|---|---|
| Name | allow-google-ssh | |
| Network | lampsill-net | ⚠️ The form preselects default. A rule only guards the network it's on; left on default, it does nothing for your server and the SSH button fails later |
| Priority | 1000 | Lower numbers win. The built-in "deny all" is 65535, so this is checked first |
| Direction · Action | Ingress · Allow | Something coming in, allowed |
| Targets | All instances in the network | There's only one server; network tags are one more thing to get wrong |
| Source filter | IPv4 ranges → 35.235.240.0/20 | Google's IAP relay, and nothing else. Never 0.0.0.0/0, which means "the whole internet" |
| Protocols and ports | Specified → TCP → 22 | SSH only |
| Logs | Off | Firewall logs are billed |
Name
- Value
allow-google-ssh
Network
- Value
lampsill-net- Why
- ⚠️ The form preselects
default. A rule only guards the network it's on; left ondefault, it does nothing for your server and the SSH button fails later
Priority
- Value
1000- Why
- Lower numbers win. The built-in "deny all" is 65535, so this is checked first
Direction · Action
- Value
- Ingress · Allow
- Why
- Something coming in, allowed
Targets
- Value
- All instances in the network
- Why
- There's only one server; network tags are one more thing to get wrong
Source filter
- Value
- IPv4 ranges →
35.235.240.0/20 - Why
- Google's IAP relay, and nothing else. Never
0.0.0.0/0, which means "the whole internet"
Protocols and ports
- Value
- Specified → TCP →
22 - Why
- SSH only
Logs
- Value
- Off
- Why
- Firewall logs are billed
→ Create.
Why is the source IPv4 when the server has no public IPv4? The relay talks to the server's private IPv4 address inside Google's network. 35.235.240.0/20 is where those relay connections come from.
Don't add HTTP or HTTPS rules
This feels wrong the first time: a web API with no web ports open. But the API will reach the internet through a Cloudflare Tunnel (post 6), which the server dials out to. Nothing ever needs to come in. No open port means nothing to scan, attack or misconfigure.
What went wrong (or nearly did)
- The firewall form defaulted to the
defaultnetwork. The rule would have looked perfect and protected nothing of mine. - DNS Armor switched itself to "Enable for this network" after I clicked around it — a paid feature, enabled by curiosity.
- "Data could not be loaded" on the VPC page looked like an outage. It was just the Compute Engine API not switched on yet.
What you should see
The firewall list shows five rules: four default-allow-… rules on the network default (they don't touch our network), and yours:
Next up · Part 4 of 9 · 11 min read
Creating the free server without paying for it
Create the one always-on computer using only the settings the free tier covers, put it on the IPv6 network from post 3, log in to it from the browser — and fix the one thing Ubuntu 26.04 gets wrong on Google Cloud.
Keep going Part 2: A Google Cloud account that stays freeWritten by
Subhankar Denria
Software Architect · 25+ products shipped