[Yandex Cloud documentation](../../index.md) > [Yandex Compute Cloud](../index.md) > [Tutorials](index.md) > Deploying Remote Desktop Gateway

# Deploying Remote Desktop Gateway


{% note warning %}

In Yandex Cloud, you can only use Microsoft products with your own licenses and on dedicated hosts. For more information, see [Using personal licenses for Microsoft products](../../microsoft/byol.md).

{% endnote %}



Remote Desktop Gateway (RDGW) is a Windows Server role which allows you to access internal network resources over HTTPS. 

In this scenario, users from the `Administrators` group will access a test VM with a self-signed certificate.

To deploy the Remote Desktop Gateway infrastructure:

1. [Get your cloud ready](#before-you-begin).
1. [Create a cloud network and subnets](#create-network).
1. [Create a security group](#sg).
1. [Create a gateway VM](#create-gw).
1. [Configure the RDGW role](#role).
1. [Test the RDGW](#test-rdgw).

If you no longer need the resources you created, [delete them](#clear-out).

## Get your cloud ready {#before-you-begin}

Sign up for Yandex Cloud and create a [billing account](../../billing/concepts/billing-account.md):
1. Navigate to the [management console](https://console.yandex.cloud) and log in to Yandex Cloud or create a new account.
1. On the **[Yandex Cloud Billing](https://center.yandex.cloud/billing/accounts)** page, make sure you have a billing account linked and it has the `ACTIVE` or `TRIAL_ACTIVE` [status](../../billing/concepts/billing-account-statuses.md). If you do not have a billing account, [create one](../../billing/quickstart/index.md) and [link](../../billing/operations/pin-cloud.md) a cloud to it.

If you have an active billing account, you can create or select a [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) for your infrastructure on the [cloud page](https://console.yandex.cloud/cloud).

[Learn more about clouds and folders here](../../resource-manager/concepts/resources-hierarchy.md).

{% note info %}

Make sure that the billing account contains user details [required to meet the Microsoft licensing policy requirements](../../microsoft/check-user-data.md). You can launch the product only if you have these details.

{% endnote %}


### Required paid resources {#paid-resources}

The cost of RDGW infrastructure includes:

* Fee for continuously running virtual machines (see [Yandex Compute Cloud pricing](../pricing.md)).
* Fee for dynamic or static public IP addresses (see [Yandex Virtual Private Cloud pricing](../../vpc/pricing.md)).
* Fee for Yandex Cloud outbound internet traffic (see [Yandex Compute Cloud pricing](../pricing.md)).


## Create a cloud network and subnets {#create-network}

Create the `rdgw-network` cloud network with a subnet in the availability zone where your VMs will reside.

1. Create a [cloud network](../../vpc/concepts/network.md).

   {% list tabs group=instructions %}

   - Management console {#console}
    
      1. In the [management console](https://console.yandex.cloud), select a folder where you want to create your cloud network.
      1. Navigate to **Virtual Private Cloud**.
      1. Click **Create network**.
      1. Specify the network name: `rdgw-network`.
      1. Click **Create network**.
   
    - CLI {#cli}
      
      ```
      yc vpc network create --name rdgw-network
      ```

      Where `rdgw-network` is the network name.

      Result:
      
      ```
      id: qqppl6fduhct76qkjh6s
      folder_id: big67u7m5flplkc6vvpc
      created_at: "2021-06-09T10:49:07Z"
      name: rdgw-network
      default_security_group_id: enpa139ji55jti00u5sg
      ```

    - API {#api}

      Use the [create](../../vpc/api-ref/Network/create.md) REST API method for the [Network](../../vpc/api-ref/Network/index.md) resource or the [NetworkService/Create](../../vpc/api-ref/grpc/Network/create.md) gRPC API call.

   {% endlist %}

1. Create a subnet in `rdgw-network`.

   {% list tabs group=instructions %}
   
    - Management console {#console}
    
      1. Navigate to **Virtual Private Cloud** in the folder where you need to create a subnet.
      1. Click the name of your cloud network.
      1. Under **Subnets**, click **Create**.
      1. Specify `rdgw-subnet` as the subnet name and select the availability zone from the drop-down list (e.g., `ru-central1-d`).
      1. Enter the subnet CIDR: IP address and subnet mask `10.1.0.0/16`. For more information about subnet IP address ranges, see [Cloud networks and subnets](../../vpc/concepts/network.md).
      1. Click **Create subnet**.
   
    - CLI {#cli}
   
      ```
      yc vpc subnet create `
        --name rdgw-subnet `
        --zone ru-central1-d `
        --network-name rdgw-network `
        --range 10.1.0.0/16
      ```

      Where `rdgw-subnet` is the subnet name.
      
      Result:
      
      ``` 
      id: e9b95m6al33r********
      folder_id: big67u7m5flp********
      created_at: "2021-06-09T10:49:21Z"
      name: rdgw-subnet
      network_id: qqppl6fduhct********
      zone_id: ru-central1-d
      v4_cidr_blocks:
      - 10.1.0.0/16
      ```

    - API {#api}

       Use the [create](../../vpc/api-ref/Subnet/create.md) REST API method for the [Subnet](../../vpc/api-ref/Subnet/index.md) resource or the [SubnetService/Create](../../vpc/api-ref/grpc/Subnet/create.md) gRPC API call.

   {% endlist %}

## Create a security group {#sg}

Create and configure a [security group](../../vpc/concepts/security-groups.md).

{% list tabs group=instructions %}

- Management console {#console}

   1. Navigate to **Virtual Private Cloud** in the folder where you need to create a security group.
   1. Open the **Security groups** tab.
   1. Click **Create security group**.
   1. Specify the security group name: `my-rdgw-sg`.
   1. In the **Network** field, select the network to assign the security group to: `rdgw-network`.
   1. Under **Rules**, create the following network traffic rules using the instructions below the table:
      
        | Traffic</br>direction | Description | Port</br>range | Protocol | Type</br>of source | Source/Destination | 
        |---|---|---|---|---|---|
        | Inbound | icmp | — | ICMP | CIDR | 0.0.0.0/0 |
        | Inbound | self-security | Any | Any | Security group | Current |
        | Inbound | tcp | 3389 | TCP | CIDR | 0.0.0.0/0 |
        | Inbound | rdgw | 443 | TCP | CIDR | 0.0.0.0/0 |
        | Outbound | default | Any | Any | CIDR | 0.0.0.0/0 |
        
        1. Select the **Egress** or **Ingress** tab.
        1. Click **Add**.
        1. In the **Port range** field of the window that opens, specify a single port or a range of ports for incoming and outgoing traffic.
        1. In the **Protocol** field, specify the required protocol or leave **Any** to allow traffic over any protocol.
        1. In the **Destination name** or **Source** field, select the purpose of the rule:
           * **CIDR**: Rule will apply to the range of IP addresses. In the **CIDR blocks** field, specify the CIDRs and masks of subnets traffic will move to/from. To add multiple CIDRs, click **Add**.
           * **Security group**: The rule will apply to the current or selected security group VMs.
        1. Click **Save**. Repeat these steps to create all rules from the table.
     
   1. Click **Save**.
   
- CLI {#cli}

   ```
   yc vpc security-group create --name=my-rdgw-sg `
     --network-name rdgw-network `
     --rule direction=ingress,protocol=icmp,v4-cidrs=[0.0.0.0/0],description=icmp `
     --rule direction=ingress,port=any,protocol=any,predefined=self_security_group,description=self `
     --rule direction=ingress,port=3389,protocol=tcp,v4-cidrs=[0.0.0.0/0],description=rdp `
     --rule direction=ingress,port=443,protocol=tcp,v4-cidrs=[0.0.0.0/0],description=rdgw `
     --rule direction=egress,port=any,protocol=any,v4-cidrs=[0.0.0.0/0],description=default 
   ```
  
   Result:

   ``` 
   id: enp136p8s2ae********
   folder_id: big67u7m5flp********
   created_at: "2021-06-09T10:50:29Z"
   name: my-rdgw-sg
   network_id: qqppl6fduhct********
   status: ACTIVE
   rules:
   - id: env98jerk9b3********
     description: icmp
     direction: INGRESS
     protocol_name: ICMP
     protocol_number: "1"
     cidr_blocks:
     v4_cidr_blocks:
      - 0.0.0.0/0
  ```

- API {#api}

  Use the [create](../../vpc/api-ref/SecurityGroup/create.md) REST API method for the [SecurityGroup](../../vpc/api-ref/SecurityGroup/index.md) resource or the [SecurityGroupService/Create](../../vpc/api-ref/grpc/SecurityGroup/create.md) gRPC API call.

{% endlist %}

## Create a gateway VM {#create-gw}

Create a VM and give it a public IP address:

{% list tabs group=instructions %}

- Management console {#console}

     1. On the folder dashboard in the [management console](https://console.yandex.cloud), click **Create resource** and select `Virtual machine instance`.
     1. Under **Boot disk image**:

         * Navigate to the **Custom** tab.
         * Click **Select** and select **Create** in the window that opens.
         * In the **Contents** field, select `Image` and then select the **Windows Server 2022 Datacenter** image from the list below. For more information on how to upload your own image for Microsoft products, see [Importing a custom image](../../microsoft/byol.md#how-to-import).
         * Optionally, enable **Additional** in the **Delete along with the virtual machine** field if you need this disk automatically deleted when deleting the VM.
         * Click **Add disk**.
     1. Under **Location**, select the `ru-central1-d` [availability zone](../../overview/concepts/geo-scope.md).
     1. Under **Disks and file storages**, specify your boot [disk](../concepts/disk.md) size: `60 GB`.
     1. Under **Computing resources**, switch to the `Custom` tab and specify the [platform](../concepts/vm-platforms.md), number of vCPUs, and amount of RAM:

         * **Platform**: `Intel Ice Lake`.
         * **vCPU**: `2`.
         * **Guaranteed vCPU performance**: `100%`.
         * **RAM**: `4 GB`.
     1. Under **Network settings**, specify:

         * **Subnet**: `rdgw-network` and `rdgw-subnet`.
         * **Public IP address**: `Auto`.
         * **Security groups**: `my-rdgw-sg`.
     1. Under **General information**, specify the VM name: `my-rds-gw`.
     1. Click **Create VM**.

     Wait for the VM status to change to `Running` and reset the password:
     
     1. Select the VM.
     1. Click **Reset password**.
     1. Specify the **Username** to reset the password for. If there is no user with that name on the VM, this user will be created with administrator access.
     1. Click **Generate password**.
     1. Save the **New password**. It will become unavailable once you close the window.

- CLI {#cli}
     
    1. In PowerShell, create the `setpass` script setting up the `Administrator` password using the [VM metadata](../concepts/vm-metadata.md) `user-data` field. The `cloudbase-init` tool will execute the script on the first run.

       {% note info %}
    
       The first line of the script must be `#ps1`; otherwise, the `cloudbase-init` tool will fail.
    
       {% endnote %}
    
        ```powershell
        #ps1
        Get-LocalUser | Where-Object SID -like *-500 | Set-LocalUser -Password (ConvertTo-SecureString "<your password>" -AsPlainText -Force) 
        ```
   
    1. Create a VM specifying the created script as the metadata source. Specify the `my-rdgw-group` ID as the `security-group-ids` value:

       ```
       yc compute instance create `
         --name my-rds-gw `
         --hostname my-rds-gw `
         --memory 4 `
         --cores 2 `
         --platform standard-v3 `
         --zone ru-central1-d `
         --network-interface subnet-name=rdgw-subnet,ipv4-address=10.1.0.3,nat-ip-version=ipv4,security-group-ids=<id_my-rdgw-group> `
         --create-boot-disk image-folder-id=standard-images,image-family=windows-2022-dc-gvlk `
         --metadata-from-file user-data=setpass
       ```

       Result:

       ```
       done (25s)
       id: frmogfp7mm1k********
       folder_id: big67u7m5flp********
       created_at: "2021-06-09T10:51:58Z"
       name: my-rds-gw
       zone_id: ru-central1-d
       platform_id: standard-v3
       resources:
       memory: "4294967296"
       cores: "2"
       core_fraction: "100"
       status: RUNNING
       boot_disk:
       mode: READ_WRITE
       device_name: fhmplfvr7g6p********
       auto_delete: true
       disk_id: fhmplfvr7g6p********
       network_interfaces:
       - index: "0"
         mac_address: d0:0d:18:83:c8:7b
         subnet_id: e9b95m6al33r********
         primary_v4_address:
         address: 10.1.0.3
         one_to_one_nat:
         address: 178.154.231.126
         ip_version: IPV4
         security_group_ids:
          - enp136p8s2a********
            fqdn: my-rds-gw.ru-central1.internal
            scheduling_policy: {}
            network_settings:
            type: STANDARD
            placement_policy: {}
       ```

       {% note info %}
       
       The commands [`yc compute instance create`](../../cli/cli-ref/compute/cli-ref/instance/create.md) | [`create-with-container`](../../cli/cli-ref/compute/cli-ref/instance/create-with-container.md) | [`update`](../../cli/cli-ref/compute/cli-ref/instance/update.md) | [`add-metadata`](../../cli/cli-ref/compute/cli-ref/instance/add-metadata.md) support substitution of environment variable values into VM metadata. When you execute a Yandex Cloud CLI command, these values, specified in the `user-data` key in `$<variable_name>` format, will be substituted into the VM metadata from the environment variables of the environment the command is executed in. 
       
       To change such behavior, i.e. to provide a variable name to the VM metadata in `$<variable_name>` format rather than take the variable value from the CLI command runtime environment, use the two-dollar syntax, e.g., `$$<variable_name>`.
       
       For more information, see [Specifics of providing environment variables in metadata via the CLI](../concepts/metadata/sending-metadata.md#environment-variables).
       
       {% endnote %}

{% endlist %}

## Configure the RDGW role {#role}

1. [Connect](../operations/vm-connect/rdp.md) to the created VM via RDP.
1. Install the required role and [management tools](https://docs.microsoft.com/en-us/troubleshoot/windows-server/system-management-components/what-is-microsoft-management-console#more-information):
   
    ```powershell
    Install-WindowsFeature RDS-Gateway -IncludeManagementTools
    ```
   
   Result:
   
   ``` 
   Success Restart Needed Exit Code      Feature Result
   ------- -------------- ---------      --------------
   True    No             Success        {Network Policy and Access Services, Remot...
   ```
   
1. Import the RDS module:
   
   ```powershell
   Import-Module -Name RemoteDesktopServices
   ```
   
   
1. Create a client access policy allowing members of the `Administrators` group to connect to the RDGW. You can do this using a [Windows PowerShell drive](https://docs.microsoft.com/en-us/powershell/scripting/samples/managing-windows-powershell-drives?view=powershell-7.1) that is automatically installed with the role:

   ```powershell
   New-Item -Path 'RDS:\GatewayServer\CAP' -Name 'Default-CAP' -UserGroups Administrators@Builtin -AuthMethod '1'
   ```

   Result:

   ``` 
       Directory: RDS:\GatewayServer\CAP
   
   Name                   Type      CurrentValue         GP   PermissibleValues PermissibleOperations
   ----                   ----      ------------         --   ----------------- ---------------------
   Default-CAP                                           -                      Get-Item, Get-ChildItem, Remove-Item,...
   ```

1. Create a resource access policy allowing members of the `Administrators` groups to connect to internal resources through the RDGW. 

   ```powershell
   New-Item -Path 'RDS:\GatewayServer\RAP' -Name 'Default-RAP' -UserGroups Administrators@Builtin -ComputerGroupType '2'
   ```

   Result:

   ``` 
       Directory: RDS:\GatewayServer\RAP
   
   Name                   Type      CurrentValue         GP   PermissibleValues PermissibleOperations
   ----                   ----      ------------         --   ----------------- ---------------------
   Default-RAP                                           -                      Get-Item, Get-ChildItem, Remove-Item,...
   ```
   
1. Create your RDGW server certificate that will be used for traffic encryption:

   ```powershell
   $Certificate = New-SelfSignedCertificate -CertStoreLocation 'Cert:\LocalMachine\My' -DnsName $ENV:COMPUTERNAME
   ```
   
1. Export the created certificate so the gateway clients can upload it to their `Trusted Roots Certificate Authorities` certificate stores. This is required to trust your self-signed certificate:

   ```powershell
   $Certificate | Export-Certificate -FilePath "C:\REGW.cer"
   ```
   
   Result:

   ``` 
       Directory: RDS:\GatewayServer\RAP
   
   Name                   Type      CurrentValue         GP   PermissibleValues PermissibleOperations
   ----                   ----      ------------         --   ----------------- ---------------------
   Default-RAP                                           -                      Get-Item, Get-ChildItem, Remove-Item,...
   ```

1. Configure RDGW to use your certificate and restart the RDG service to apply the settings:

   ```powershell
   Set-Item -Path 'RDS:\GatewayServer\SSLCertificate\Thumbprint' -Value $Certificate.Thumbprint
   Get-Service TSGateway | Restart-Service
   ```

   Result:

   ``` 
       Directory: C:\
   
   Mode                LastWriteTime         Length Name
   ----                -------------         ------ ----
   -a----         6/9/2021  11:51 AM            796 REGW.cer
   ```

The RDGW VM allows members of the `BUILTIN\Administrators` group to connect to internal network VMs.

## Test the RDGW {#test-rdgw}

1. Create an internal network VM to which you will connect during the test. 

    {% list tabs group=instructions %}

    - Management console {#console}

        1. On the folder dashboard in the [management console](https://console.yandex.cloud), click **Create resource** and select `Virtual machine instance`.
        1. Under **Boot disk image**:

            * Navigate to the **Custom** tab.
            * Click **Select** and select **Create** in the window that opens.
            * In the **Contents** field, select `Image` and then select the **Windows Server 2022 Datacenter** image from the list below. For more information on how to upload your own image for Microsoft products, see [Importing a custom image](../../microsoft/byol.md#how-to-import).
            * Optionally, enable **Additional** in the **Delete along with the virtual machine** field if you need this disk automatically deleted when deleting the VM.
            * Click **Add disk**.
        1. Under **Location**, select the `ru-central1-d` [availability zone](../../overview/concepts/geo-scope.md).
        1. Under **Disks and file storages**, set `60 GB` as your boot disk size.
        1. Under **Computing resources**, switch to the `Custom` tab and specify the [platform](../concepts/vm-platforms.md), number of vCPUs, and amount of RAM:

            * **Platform**: `Intel Ice Lake`.
            * **vCPU**: `2`.
            * **Guaranteed vCPU performance**: `100%`.
            * **RAM**: `4 GB`.
        1. Under **Network settings**, specify:

            * **Subnet**: `rdgw-network` and `rdgw-subnet`.
            * **Public IP address**: `No address`.
        1. Under **General information**, specify the VM name: `test-vm`.
        1. Click **Create VM**.

        Wait for the VM status to change to `Running` and reset the password:
        
        1. Select the VM.
        1. Click **Reset password**.
        1. Specify the **Username** to reset the password for. If there is no user with that name on the VM, this user will be created with administrator access.
        1. Click **Generate password**.
        1. Save the **New password**. It will become unavailable once you close the window.

    - CLI {#cli}
        
      Create a VM:
    
      ```
      yc compute instance create `
        --name test-vm `
        --hostname test-vm `
        --memory 4 `
        --cores 2 `
        --platform standard-v3 `
        --zone ru-central1-d `
        --network-interface subnet-name=rdgw-subnet,ipv4-address=10.1.0.4 `
        --create-boot-disk image-folder-id=standard-images,image-family=windows-2022-dc-gvlk `
        --metadata-from-file user-data=setpass
      ```

      Result:
   
      ``` 
      done (19s)
      id: fhm5pflreh2j********
      folder_id: big67u7m5flp********
      created_at: "2021-06-09T11:53:03Z"
      name: test-vm
      zone_id: ru-central1-d
      platform_id: standard-v3
      resources:
      memory: "4294967296"
      cores: "2"
      core_fraction: "100"
      status: RUNNING
      boot_disk:
      mode: READ_WRITE
      device_name: fhmmf65nlbt1********
      auto_delete: true
      disk_id: fhmmf65nlbt1********
      network_interfaces:
      - index: "0"
        mac_address: d0:0d:5d:ef:bb:74
        subnet_id: e9b95m6al33r********
        primary_v4_address:
        address: 10.1.0.4
        fqdn: test-vm.ru-central1.internal
        scheduling_policy: {}
        network_settings:
        type: STANDARD
        placement_policy: {}
      ```

    - API {#api}

      Use the [create](../api-ref/Instance/create.md) REST API method for the [Instance](../api-ref/Instance/index.md) resource or the [InstanceService/Create](../api-ref/grpc/Instance/create.md) gRPC API call.

    {% endlist %} 

1. Import your RDGW certificate file to the `Trusted Roots Certificate Authorities` directory of the computer you will connect to the test VM.
    
   To connect to the gateway by the VM name, specify its name and external IP address in the `C:\Windows\system32\drivers\etc\hosts` file. Here is an example:
   
    ```powershell
    87.250.250.242 my-rds-gw
    ```
   
1. Run the [`mstsc`](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/mstsc) remote desktop client. On the **Advanced** tab of the connection settings, specify the gateway: `my-rds-gw`, destination node: `test-vm`, and username: `Administrator`. 

## How to delete the resources you created {#clear-out}

If you no longer need the resources you created, i.e., [VMs](../operations/vm-control/vm-delete.md) and [networks](../../vpc/operations/network-delete.md), delete them.