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:

  • 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, 35.235.240.0/20, on all ports of your machine. 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

When setting up Cloud IAP for TCP forwarding, access control is enforced by a resource's Cloud Identity and Access Management (Cloud IAM) policy. To set Cloud IAM permissions, follow the steps below:

Console

  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. Note that if a member has the Owner role, they have permission to use Cloud IAP for TCP forwarding.
  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 10.0.0.1:

    destination.ip == "10.0.0.1" || 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.

gcloud

  1. Open the Cloud IAM policy for the app using the following gcloud command:

    gcloud projects get-iam-policy PROJECT_ID > policy.yaml

  2. Grant the iap.tunnelResourceAccessorrole to your members by modifying the Cloud IAM policy YAML file. Note that if a member has the Owner role, they have permission to use Cloud IAP for TCP forwarding.

    The following is an example of an edited policy.yaml file that binds the iap.tunnelResourceAccessor role to a group of VM instance admins, granting them access to Cloud IAP-secured tunnel resources.


    Example policy.yaml file

    ...
    - members:
      - group:instance-admins@example.com
      role: roles/iap.tunnelResourceAccessor
    ...

    Optionally, set access level conditions at the project level with Cloud IAM conditions. To use Cloud IAM conditions, join the Private Beta.

  3. Bind the policy to the app using the set-iam-policy command.

    gcloud projects set-iam-policy PROJECT_ID policy.yaml

To grant a member the iap.tunnelResouceAccessor role without editing the policy.yaml file, call the following command.

gcloud projects add-iam-policy-binding PROJECT_ID \
   --member=user:EXAMPLE_USER@EXAMPLE.COM \
   --role=roles/iap.tunnelResourceAccessor

API

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.

    1. Go to the Service accounts page.
      Go to the service accounts page

    2. Click the email address of your service account.

    3. Click Edit.

    4. Click Create key.

    5. Select JSON as your key type.

    6. Create a new key by clicking Create and closing the confirmation window that appears.

    Your JSON credentials file has now been downloaded.

  2. Export the following variables.

    export IAP_BASE_URL=https://iap.googleapis.com/v1/projects/PROJECT_NUMBER/iap_tunnel
    # Replace with the path to your local service account's downloaded JSON file
    export JSON_CREDS=EXAMPLE.IAM.GSERVICEACCOUNT.COM.JSON
    # Replace POLICY_FILE.JSON with the name of JSON file to use for setIamPolicy
    export JSON_NEW_POLICY=POLICY_FILE.JSON
    

  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.
      export CLOUD_OAUTH_TOKEN=AUTHORIZATION_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 10.0.0.1 on port 22 using the destination.ip and destination.port Cloud IAM Conditions. They must also meet the requirements of the ACCESS_LEVEL_NAME access level.

    Note that if a member has the Owner role, they have permission to use Cloud IAP for TCP forwarding.


    Example policy.json file

    {
      "policy": {
        "bindings": [
          {
            "role": "roles/iap.tunnelResourceAccessor",
            "members": ["group:instance-admins@example.com"],
            "condition": {
              "expression": "\"accessPolicies/POLICY_NAME/accessLevels/ACCESS_LEVEL_NAME\" in request.auth.access_levels && destination.ip == \"10.0.0.1\" && destination.port == 22",
              "title": "CONDITION_NAME"
            }
          }
        ]
      }
    }

    To find a policy name , call accessPolicies.list:

    GET https://accesscontextmanager.googleapis.com/v1/accessPolicies
    
  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

Note that 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.

For RDP connections, you can install a plugin for Microsoft's Remote Desktop Connection Manager, streamlining the process of connecting to Windows VMs in GCP. For more information, on how to use and install the plugin, see the GitHub repository.

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 compute start-iap-tunnel INSTANCE_NAME INSTANCE_PORT \
  --local-host-port=localhost:LOCAL_PORT

Where:

  • 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.

Starting SSH

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.

Console

Use the SSH button in the GCP Console to connect to an instance with only an internal IP address that's configured to allow TCP tunneling though Cloud IAP.

gcloud

Use the gcloud compute ssh command to connect to an instance that's configured to allow TCP tunneling though Cloud IAP.

gcloud compute ssh INSTANCE_NAME

Where:

  • INSTANCE_NAME is the name of the instance to SSH into.

If the instance doesn't have a public IP address, the connection automatically uses Cloud IAP TCP tunneling. If the instance does have a public IP address, the connection uses the public IP address instead of Cloud IAP TCP tunneling.

If you specify the --tunnel-through-iap flag, gcloud compute ssh will always use Cloud IAP TCP tunneling.

Cloud Audit Logs and access levels

Enabling Cloud Audit Logs for your Cloud IAP-secured project allows you to see authorized and unauthorized access requests. View requests and all the access levels a requestor has met by following the process below:

  1. Go to the GCP Console Logs page for your project.
    Go to the logs page
  2. On the resource selector drop-down list, select a resource. Cloud IAP-secured SSH and TCP resources are under GCE VM instance.
  3. On the logs type drop-down list, select data_access.
    • The data_access log type only appears if there was traffic to your resource after you enabled Cloud Audit Logs for Cloud IAP.
  4. Click to expand the date and time of the access you want to review.
    • Authorized access has a blue i icon.
    • Unauthorized access has an orange !! icon.
  5. View the access levels the requester has met by clicking to expand sections until you reach protoPayload > requestMetadata > requestAttributes > auth > accessLevels.

Note that all access levels that a user has met are visible when viewing a request, including access levels that weren't required to access it. Viewing an unauthorized request doesn't indicate what access levels weren't met. This is determined by comparing the conditions on the resource to the access levels visible on the request.

See the Cloud Audit Logs guide for more information about logs.

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