Secure Admin Access to Private Compute Engine VMs with IAP TCP Forwarding
Learn when to use Google Cloud IAP TCP forwarding, how it works, and a step‑by‑step example to give administrators SSH or RDP access to VMs that have no public IPs. Includes IAM, firewall, audit‑log checks and trade‑offs.
17 Aug 2026, 19:43 UTC

Why IAP TCP Forwarding Matters for Private VMs
Many production environments keep Compute Engine VMs without public IP addresses to reduce attack surface. However, when an administrator needs to SSH or RDP into such a VM, the usual bastion‑host pattern can become cumbersome: you must maintain a separate host, rotate credentials, and open firewall rules. Identity‑Aware Proxy (IAP) TCP forwarding solves this by letting you tunnel traffic through Google’s identity layer and a single proxy endpoint.
How IAP TCP Forwarding Works
When you run gcloud compute start-iap-tunnel, the client establishes a secure HTTPS connection to the IAP endpoint. The request is authenticated with your Google identity (OAuth or a service account). IAP verifies that you have the roles/iap.tunnelResourceAccessor IAM binding on the target VM or project, then opens a TCP tunnel to the requested port on the VM. The tunnel is a bi‑directional stream; once established, you can use any SSH or RDP client to connect to localhost:PORT on your machine, and the traffic will be forwarded to the VM.
| Component | Role |
|---|---|
| Client | Runs gcloud or SSH client, authenticates with Google identity |
| IAP Proxy | Validates IAM, opens TCP tunnel to VM |
| Private VM | Receives traffic on the requested port, requires OS‑level authentication |
When to Use IAP TCP Forwarding
- Administrators need SSH or RDP access to VMs that lack public IPs.
- You want to avoid maintaining a bastion host and rotating its credentials.
- Auditability is required: IAP logs every tunnel request in Cloud Audit Logs.
- Firewall rules can be tightened to allow traffic only from the IAP proxy IP ranges.
Do Not Use IAP for End‑User Application Traffic
IAP TCP forwarding is intended for administrative access only. Exposing application ports over IAP can bypass your existing security controls and is not supported for production traffic.
Step‑by‑Step Example
Below is a practical example that shows how to set up IAP TCP forwarding for SSH access to a private VM. The same approach works for RDP by changing the port and client.
Prerequisites
- Google Cloud project with Compute Engine enabled.
- VM instance
my-private-vmin zoneus-central1-awith no public IP. - IAM role
roles/iap.tunnelResourceAccessorgranted to your user or a service account. - Firewall rule allowing inbound TCP on port 22 from
0.0.0.0/0(or better, from IAP proxy IP ranges). - gcloud SDK installed and authenticated with a Google identity that has the required role.
1. Enable the IAP API
# Run once per project
gcloud services enable iap.googleapis.com
2. Verify IAM Binding
# Check that your user has the accessor role on the VM
gcloud projects get-iam-policy YOUR_PROJECT_ID \
--flatten='bindings[].members' \
--filter='bindings.role:roles/iap.tunnelResourceAccessor' \
--format='table(bindings.members)'
3. Start the IAP Tunnel
# Open a TCP tunnel to port 22 on the VM
# The tunnel listens on localhost:12345
# Replace YOUR_VM_NAME and ZONE accordingly
gcloud compute start-iap-tunnel my-private-vm 22 \
--zone=us-central1-a \
--local-host-port=localhost:12345
After the command completes, you should see a message similar to:
Tunnel started. Connect using ssh -p 12345 localhost
4. Connect via SSH
# Use the local port to SSH into the VM
ssh -p 12345 -i ~/.ssh/id_rsa myuser@localhost
At this point you have an SSH session to the VM. The OS‑level authentication (public key, password, or GCE OS Login) still applies.
5. Verify Audit Logging
In the Cloud Console, navigate to IAM & Admin → Audit Logs and filter for the VM’s name. You should see an event with methodName=iap.tunnel.start and the user who initiated the tunnel.
Trade‑offs and Limitations
- Firewall Configuration: The VM’s firewall must allow inbound traffic from the IAP proxy IP ranges on the target port. A blanket
0.0.0.0/0rule works but is less secure than restricting to IAP ranges. - Quota and Availability: IAP TCP forwarding is subject to per‑region quotas. In high‑traffic scenarios, you may hit limits or experience latency if the region’s proxy capacity is saturated.
- Not a Replacement for Application Security: IAP only protects the transport layer. If your SSH keys are weak or your OS is unpatched, the tunnel offers no additional defense.
- Operational Complexity: While IAP removes the bastion host, you still need to manage IAM roles and ensure the IAP API is enabled.
- Client Support: The standard
gcloud compute start-iap-tunnelcommand is required to establish the tunnel. Some legacy SSH clients may not support theProxyCommandstyle configuration needed for direct tunneling.
Practical Checklist Before Going Live
- Confirm IAP API is enabled in the target project.
- Verify the
roles/iap.tunnelResourceAccessorbinding exists on the VM or project for the intended user. - Ensure the firewall allows the target port from IAP proxy IP ranges.
- Test the tunnel and audit log entry in a staging environment.
- Document the procedure and IAM policy in your security handbook.
Actionable Takeaway
IAP TCP forwarding gives you a lightweight, audit‑ready way to administer private Compute Engine VMs without exposing them to the public internet. By combining IAM role checks, firewall restrictions, and Cloud Audit Logs, you can maintain strong security posture while simplifying admin workflows. Set up the example above in a test project, verify the logs, and then roll out to production with the same IAM and firewall patterns. Keep in mind the limitations—especially that IAP does not replace OS‑level hardening—and adjust your security controls accordingly.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.