Using IAP for TCP forwarding

This page explains how you can use IAP TCP forwarding to enable administrative access to VM instances that do not have public IP addresses or do not permit direct access over the internet.

IAP TCP forwarding allows you to establish an encrypted tunnel over which you can forward SSH, RDP, and other traffic to VM instances. IAP TCP forwarding also provides you fine-grained control over which users are allowed to establish tunnels and which VM instances users are allowed to connect to.

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

Preparing your project for IAP TCP forwarding

This section walks you through the necessary steps to enable IAP TCP forwarding in your Google Cloud project.

Create a firewall rule

To allow IAP to connect to your VM instances, create a firewall rule that:

  • applies to all VM instances that you want to be accessible by using IAP.
  • allows ingress traffic from the IP range 35.235.240.0/20. This range contains all IP addresses that IAP uses for TCP forwarding.
  • allows connections to all ports that you want to be accessible by using IAP TCP forwarding, for example, port 22 for SSH and port 3389 for RDP.

Console

To allow RDP and SSH access to all VM instances in your network, do the following:

  • Open the Firewall Rules page and click Create firewall rule

    Open the Firewall Rules page

  • Configure the following settings:

    • Name: allow-ingress-from-iap
    • Direction of traffic: Ingress
    • Target: All instances in the network
    • Source filter: IP ranges
    • Source IP ranges: 35.235.240.0/20
    • Protocols and ports: Select TCP and enter 22,3389 to allow both RDP and SSH.
  • Click Create.

gcloud

To allow RDP access to all VM instances in your network, run:

gcloud compute firewall-rules create allow-rdp-ingress-from-iap \
  --direction=INGRESS \
  --action=allow \
  --rules=tcp:3389 \
  --source-ranges=35.235.240.0/20

For SSH access, run:

gcloud compute firewall-rules create allow-ssh-ingress-from-iap \
  --direction=INGRESS \
  --action=allow \
  --rules=tcp:22 \
  --source-ranges=35.235.240.0/20

For other protocols, run

gcloud compute firewall-rules create allow-ingress-from-iap \
  --direction=INGRESS \
  --action=allow \
  --rules=tcp:PORT \
  --source-ranges=35.235.240.0/20

where PORT is the port used by the protocol.

Grant permissions to use IAP TCP Forwarding

To control which users and groups are allowed to use IAP TCP forwarding and which VM instances they're allowed to connect to, configure Identity and Access Management (IAM) permissions.

We recommend granting all of the following roles for trusted administrators:

You can grant a user or group access to all VM instances in a project by configuring IAM permissions on the project level:

Console

  1. Open the IAM & Admin page in the Cloud Console.

    Open the IAM & Admin page

  2. Click Add and configure the following:

    • New members: Specify the user or group you want to grant access.
    • Select a role Select Cloud IAP > IAP-Secured Tunnel User.
  3. Optionally, click Add condition and configure a member restriction:

    • Title: Enter a name for the restriction.
    • Expression: Enter a condition that a user must meet before being allowed to use IAP for TCP forwarding.

    For example, the following CEL expression restricts access to port 22:

    destination.port == 22
    

    You can also restrict access by access level:

    destination.port == 22 && "FULL_ACCESS_LEVEL_NAME" in request.auth.access_levels
    

    Where FULL_ACCESS_LEVEL_NAME is an existing access level and uses the format accessPolicies/POLICY_NAME/accessLevels/ACCESS_LEVEL_NAME.

  4. Click Add another role and configure the following:

    • Select a role Select Compute Engine > Compute Instance Admin (v1).
  5. Click Add another role and configure the following:

    • Select a role Select Service Accounts > Service Account User.
  6. Click Save.

gcloud

Grant the three roles to the user:

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member=user:EMAIL \
    --role=roles/iap.tunnelResourceAccessor
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member=user:EMAIL \
    --role=roles/compute.instanceAdmin.v1
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member=user:EMAIL \
    --role=roles/iam.serviceAccountUser

Replace the following:

  • PROJECT_ID: ID of the project
  • EMAIL: email address of the user you want to grant access, for example user@example.com.

If desired, you can instead configure the iap.tunnelResourceAccessor role by VM (the other roles must be on the project):

Console

  1. Open the IAP admin page and select the SSH and TCP Resources tab.

    Open the IAP admin page

  2. Select the VM instances that you want to configure.
  3. Click Show info panel if the info panel is not visible.
  4. Click Add member and configure the following:

    • New members: Specify the user or group you want to grant access.
    • Select a role Select Cloud IAP > IAP-Secured Tunnel User.
  5. Optionally, click Add condition and configure a member restriction:

    • Title: Enter a name for the restriction.
    • Expression: Enter a condition that a user must meet before being allowed to use IAP for TCP forwarding.

    For example, the following CEL expression restricts access to port 22:

    destination.port == 22
    

    You can also restrict access by access level:

    destination.port == 22 && "FULL_ACCESS_LEVEL_NAME" in request.auth.access_levels
    

    Where FULL_ACCESS_LEVEL_NAME is an existing access level and uses the format accessPolicies/POLICY_NAME/accessLevels/ACCESS_LEVEL_NAME.

  6. Click Save.

API

To edit your application's policy.json file, follow the process below. See Managing access to IAP-secured resources for more information about using the 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 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 IAM policy JSON file.

  8. Optionally, add member restrictions based on 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 IAP-secured tunnel resources. An 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 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 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}
    

Permissions details

The required permissions vary depending on how a user will use IAP TCP forwarding:

Scenarios Permissions required
All
  • iap.tunnelInstances.accessViaIAP
Using gcloud compute [start-iap-tunnel, ssh, scp]
  • compute.instances.get
  • compute.instances.list
Using gcloud compute [ssh, scp]
  • compute.projects.get
VM using OS Login Please see these instructions
Not using OS Login
  • compute.instances.setMetadata
  • compute.projects.setCommonInstanceMetadata
  • compute.globalOperations.get
SSH to VM using a service account
  • iam.serviceAccounts.actAs
SSH from the browser Please see these instructions

For example, if a user wants to connect using gcloud compute ssh to a VM not using OS Login, but that uses a service account, the user would need the following permissions:

  • iap.tunnelInstances.accessViaIAP
  • compute.instances.get
  • compute.instances.list
  • compute.projects.get
  • compute.instances.setMetadata
  • compute.projects.setCommonInstanceMetadata
  • compute.globalOperations.get
  • iam.serviceAccounts.actAs

Tunneling SSH connections

You can connect to Linux instances that don't have a public IP address by tunneling SSH traffic through IAP:

Console

To connect to your instance, use the SSH button in the Cloud Console. Your instance's access configuration (defined through IAM permissions) must allow TCP tunneling through IAP.

gcloud

To connect to your instance, use the gcloud compute ssh command. Your instance's access configuration (defined through IAM permissions) must allow TCP tunneling through IAP.

gcloud compute ssh INSTANCE_NAME

Replace INSTANCE_NAME with the name of the instance to SSH into.

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

You can use the --tunnel-through-iap flag so that gcloud compute ssh always uses IAP TCP tunneling.

Use the --internal-ip flag so that gcloud compute ssh never uses IAP TCP tunneling and instead directly connects to the internal IP of the VM. Doing so is useful for clients that are connected to the same VPC network as the target VM.

IAP Desktop

You can use IAP Desktop to connect to a VM instance by using SSH and IAP TCP forwarding.

  1. In the application, select File > Add Google Cloud project.

  2. Enter the ID or name of your project and click OK.

  3. In the Project Explorer window, right-click the VM instance you want to connect to and select Connect.

IAP Desktop

For more information on IAP Desktop, see the GitHub project page.

PuTTY

You can set up PuTTY so that it uses IAP TCP forwarding to connect to a VM instance. Your instance's access configuration (defined through IAM permissions) must allow TCP tunneling through IAP.

Before you configure PuTTY, use the gcloud compute ssh command once to ensure that you have a private SSH key on your local computer and that your public SSH key is published to Compute Engine:

  1. Open a command prompt and run the following command to connect to the VM instance:

    gcloud compute ssh INSTANCE_NAME `
      --tunnel-through-iap `
      --project PROJECT_ID `
      --zone ZONE
    

    Replace the following:

    • INSTANCE_NAME: name of the instance to connect to
    • PROJECT_ID: project ID of the project the VM instance is located in
    • ZONE: zone where the VM instance is located

    If necessary, confirm that you want to generate SSH keys by pressing Y.

  2. On the VM, determine your username by running the following command:

    whoami
    

    You need this username later.

You can now configure PuTTY to use IAP TCP forwarding:

  1. Open PuTTY and select the category Connection > Proxy.
  2. Configure the following proxy settings:

    • For Proxy type, select Local.
    • In the Telnet command, or local proxy command field, enter the following:

      gcloud.cmd compute start-iap-tunnel %host %port --listen-on-stdin --project PROJECT_ID --zone ZONE
      

      Replace the following:

      • PROJECT_ID: Project ID of the project the VM instance is located in
      • ZONE: Zone where the VM instance is located
    • For Print proxy diagnostics in the terminal window, select Only until session starts.

  3. Select the category Connection > SSH > Auth.

  4. Click Browse and paste the following file name, then click Open:

    %USERPROFILE%\.ssh\google_compute_engine.ppk
    
  5. Select the category Session.

  6. Configure the following proxy settings:

    • In the Host name (or IP address) field, enter the following:

      USERNAME@INSTANCE_NAME
      

      Replace the following:

      • USERNAME: the Linux username you determined earlier
      • INSTANCE_NAME: the name of the VM instance that you want to connect to
    • Saved sessions: Enter a name for the session.

  7. Click Save.

  8. Click Open to start the SSH session.

Tunneling RDP connections

You can connect to Windows instances that don't have a public IP address by tunneling RDP traffic through IAP:

IAP Desktop

You can use IAP Desktop to connect to the Remote Desktop of one or more VM instances by using IAP TCP forwarding.

  1. In the application, select File > Add Google Cloud project.

  2. Enter the ID or name of your project and click OK.

  3. In the Project Explorer window, right-click the VM instance you want to connect to and select Connect.

IAP Desktop

For more information on IAP Desktop, see the GitHub project page.

gcloud

To connect to the Remote Desktop of a VM instance, you first create a tunnel.

  1. Use the gcloud compute start-iap-tunnel command to create an encrypted tunnel to the RDP port of the VM instance.

    gcloud compute start-iap-tunnel INSTANCE_NAME 3389 \
        --local-host-port=localhost:LOCAL_PORT \
        --zone=ZONE
    

    Replace INSTANCE_NAME with the name of the VM instance you want to connect to. Replace LOCAL_PORT with the localhost port where you want the proxy to be bound or use 0 to have an unused one selected automatically. Replace ZONE with the zone where the VM instance is located.

  2. gcloud performs a connectivity test with the VM instance, then opens a tunnel and shows a port number.

    Listening on port [LOCAL_PORT].
    

    All traffic sent to localhost:LOCAL_PORT is forwarded to the VM instance. The port is only accessible by applications running on your local computer.

  3. Leave gcloud running and open the Microsoft Windows Remote Desktop Connection app.

  4. Enter the tunnel endpoint as computer name:

    localhost:LOCAL_PORT
    

    Replace LOCAL_PORT with the port number shown when the tunnel was opened by gcloud.

  5. Click Connect.

Tunneling other TCP connections

You can use IAP TCP forwarding for other TCP-based protocols by using the gcloud compute start-iap-tunnel command to allocate a local port. The local port tunnels data traffic from the local machine to the remote machine in an HTTPS stream. 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.

gcloud

Create an encrypted tunnel to a port of the VM instance:

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

Replace INSTANCE_NAME and INSTANCE_PORT with the name and port of the VM instance you want to connect to. Replace LOCAL_PORT with the localhost port where you want the proxy to be bound. Replace ZONE with the zone where the VM instance is located.

gcloud performs a connectivity test with the VM instance, then opens a tunnel and shows a port number.

Listening on port [LOCAL_PORT].

All traffic sent to localhost:LOCAL_PORT is forwarded to the VM instance. The port is only accessible by applications running on your local computer.

Known limitations

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

Connection length: IAP automatically disconnects sessions after 1 hour of inactivity. We recommend having logic in your applications to handle reestablishing a tunnel when it becomes disconnected.

Next steps