Using Cloud IAP for TCP forwarding

This page explains how to control who can access administrative services like SSH and RDP on your backends by setting tunnel resource permissions and creating tunnels that route TCP traffic through Cloud Identity-Aware Proxy (Cloud IAP) to Compute Engine instances.

To learn more about how Cloud IAP handles TCP forwarding, see the TCP forwarding overview.

Before you begin

Before you begin, you'll need the following:

  • A Cloud IAP-secured application that has the Cloud IAP API enabled.

    Open the Cloud IAP API page

  • User or group names that you want to grant access to.
  • Firewall rules that are configured to allow access from Cloud IAP's TCP forwarding netblock,, on the desired ports. This ensures that connections are allowed from Cloud IAP's TCP forwarding IP addresses to the TCP port of the admin service on your resource. Note that you might not need to adjust your firewall rules if the default-allow-ssh and default-allow-rdp default rules are applied to ports used for SSH and RDP.

    Open the Firewall Rules page

Configuring access and permissions

To set Cloud Identity and Access Management (Cloud IAM) permissions, follow the steps below:


  1. View your SSH and TCP resources by going to the Identity-Aware Proxy page and selecting SSH and TCP Resources tab.

    Open the Cloud IAP admin page

  2. Update member permissions on resources by selecting the checkbox next to resources. This can be set per zone name or per whole project by selecting the region or All Tunnel Resources checkboxes.
  3. On the right side Info panel, click Add member.
  4. Specify which users and groups you want to grant access by adding them to the New members field.
  5. Grant the members access to the tunneled resources by opening the Select a role drop-down list and selecting Cloud IAP > IAP-Secured Tunnel User.
  6. Optionally, add member restrictions by clicking Add condition and entering the condition Title and Expression.

    For example, by setting Expression to a CEL expression that uses destination.ip and destination.port Cloud IAM conditions, you can limit access to only members on port 22 or to members who have a private IP of

    destination.ip == "" || destination.port == 22

    Access levels can also be used to restrict access with the following CEL expression:

    "FULL_ACCESS_LEVEL_NAME" in request.auth.access_levels

    Where FULL_ACCESS_LEVEL_NAME is accessPolicies/POLICY_NAME/accessLevels/ACCESS_LEVEL_NAME.

    To find the full name of an access level:

    1. Open the Access Context Manager page.

      Open the Access Context Manager page

    2. Click on the name of the access level.

    The full Access level name is now displayed on the right side panel in the following format:

  7. Click Save.


To edit your application's policy.json file, follow the process below. See Managing access to Cloud IAP-secured resources for more information about using the Cloud IAM API to manage access policies.

  1. Download the credentials file for your service account.
  2. Export the following variables.

    export IAP_BASE_URL=${PROJECT_NUMBER}/iap_tunnel
    # Replace with the path to your local service account's downloaded JSON file
    # Replace POLICY_FILE.JSON with the name of JSON file to use for setIamPolicy

  3. Convert your service account credentials JSON file into an OAuth access token using Oauth2l by running the following command:

    oauth2l header --json ${JSON_CREDS} cloud-platform

  4. If this is your first time running the above command, when prompted:

    1. Get the verification code by clicking the displayed link and copying the code.
    2. Paste the verification code into your app prompt.
    3. Copy the returned bearer token.
    4. Export a new variable that's assigned to the value of your returned bearer token.
  5. If you've run this command before, export the following variable.

    export CLOUD_OAUTH_TOKEN ="$(oauth2l header --json ${JSON_CREDS} cloud-platform)"

  6. Get the Cloud IAM policy for the Compute Engine instance using the getIamPolicy method. The empty data bit at the end turns the curl request into POST instead of GET.

    curl -i -H "${CLOUD_OAUTH_TOKEN}" \
         ${IAP_BASE_URL}/zones/ZONE_NAME/instances/INSTANCE_ID or INSTANCE_NAME:getIamPolicy \
         -d ''

  7. Grant the iap.tunnelResourceAccessor role to your members by modifying the Cloud IAM policy JSON file.

  8. Optionally, add member restrictions based on Cloud IAM Conditions and access levels.

    The following is an example of an edited policy.json file that binds the iap.tunnelResourceAccessor role to a group of VM instance admins, granting them access to Cloud IAP-secured tunnel resources. A Cloud IAM condition has been added to make the resources accessible only to members in the VM instance admins group with a private IP address of on port 22 using the destination.ip and destination.port Cloud IAM Conditions.

    Example policy.json file

      "policy": {
        "bindings": [
            "role": "roles/iap.tunnelResourceAccessor",
            "member": ""
            "condition": {
               "expression": "destination.ip == \"\" && destination.port == 22"

    Access levels can be used to restrict access with the following expression:

    "\"accessPolicies/POLICY_NAME/accessLevels/ACCESS_LEVEL_NAME\" in request.auth.access_levels"

    To find a policy name , call accessPolicies.list:

  9. Set your new policy.json file using the setIamPolicy method.

    curl -i -H "Content-Type:application/json" \
         -H "$(oauth2l header --json ${JSON_CREDS} cloud-platform)" \
         ${IAP_BASE_URL}/zones/ZONE_NAME/instances/INSTANCE_ID or INSTANCE_NAME:setIamPolicy \
         -d @${JSON_NEW_POLICY}

Tunneling with gcloud

gcloud requires you to specify the instance you want to connect to. To tunnel using gcloud, you'll need to provide the name of the instance.

General TCP tunneling

Cloud IAP's TCP forwarding feature handles TCP traffic by allocating a local port. The local port tunnels data traffic from the local machine to the remote machine in an HTTPS stream. Cloud IAP then receives the data, applies access controls, and forwards the unwrapped data to the remote port. Conversely, any data from the remote port is also wrapped before it's sent to the local port where it's then unwrapped.

The command below creates an encrypted tunnel between the local machine and the remote resource, specified by its instance name. Cloud IAP's TCP forwarding feature will then start listening for connections on localhost:LOCAL_PORT. Remove the local-host-port flag from the command if you want a random local port selected.

gcloud beta compute start-iap-tunnel INSTANCE_NAME INSTANCE_PORT \
  --local-host-port=localhost:LOCAL_PORT \


  • INSTANCE_NAME is the name of the instance to operate on.
  • INSTANCE_PORT is the name or number of the instance's port to connect to.
  • LOCAL_PORT is the port to which the proxy is bound.
  • NETWORK_INTERFACE is the name of the instance network interface to connect to. "nic0" is used by default.

SSH tunneling

Using SSH with Cloud IAP's TCP forwarding feature doesn't require the mapping of a local port. The SSH connection is instead directly wrapped inside HTTPS and sent by Cloud IAP's TCP forwarding to the remote instance.

Use the command below to create an SSH session to a specified instance by securely tunneling all traffic through Cloud IAP.

gcloud beta compute ssh INSTANCE_NAME \
   --command=COMMAND \


  • INSTANCE_NAME is the name of the instance to SSH into.
  • COMMAND is a command to run on the instance. For example, "ps -ejH".

You now have an SSH session that is tunneled through Cloud IAP.

Known limitations

Bandwidth: Cloud IAP's TCP forwarding feature isn't intended for bulk transfer of data. Cloud IAP reserves the right to rate-limit users abusing this service.

Connection length: Cloud IAP won't disconnect active sessions unless required for maintenance. We recommend having logic in your applications to handle reestablishing a tunnel if it becomes disconnected.

Was this page helpful? Let us know how we did:

Send feedback about...

Identity-Aware Proxy Documentation