[Yandex Cloud documentation](../../index.md) > [Yandex Virtual Private Cloud](../index.md) > [Tutorials](index.md) > Configuring network resources and interaction between them > Architecture and protection of a basic web service

# Architecture and protection of a basic web service


In this tutorial, you will deploy and set up a basic web service infrastructure consisting of multiple VMs and accessible from a remote site. You will use [security groups](../concepts/security-groups.md) to restrict access to the VMs and a [network load balancer](../../network-load-balancer/concepts/index.md) to distribute traffic across web servers. 

The diagram below shows how a remote site communicates with your web service:

![image](../../_assets/tutorials/web-service.svg)

Remote site:

* `remote-net` network with `subnet-1` (`10.129.0.0/24`).
* `vm-1` Ubuntu VM residing in `subnet-1` and used to test your cloud site infrastructure.

{% note info %}

You can also use your PC as the remote site. To do this, you need to know your public IP address and your subnet CIDR.

{% endnote %}

Cloud site:

* `network` with the following subnets: `subnet-a` (`192.168.5.0/24`), `subnet-b` (`192.168.15.0/24`), and `subnet-d` (`192.168.25.0/24`).
* `vpn` IPsec gateway residing in `subnet-a` to provide an IPsec connection to a remote site and network connectivity between cloud VMs.
* Route table containing static `vpn-route` directing `subnet-1` traffic through the IPsec gateway to the cloud VMs.
* `web-node-a`, `web-node-b`, and `web-node-d` Drupal internet service VMs residing in `subnet-a`, `subnet-b`, and `subnet-d`, respectively.
* `vpn-sg` security group managing IPSec tunnel traffic for `vpn` and `web-service-sg` security group managing traffic between `web-node-a`, `web-node-b`, and `web-node-d`. 
* `web-service-lb` load balancer distributing incoming traffic across `web-node-a`, `web-node-b`, and `web-node-d`.

To create the web service infrastructure:

1. [Get your cloud ready](#before-begin).
1. [Set up your remote site](#remote-setup).
1. [Set up your cloud site](#cloud-setup).
1. [Test the solution](#test).

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

## Get your cloud ready {#before-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).

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

The cost of support for the new infrastructure includes:

* Fee for continuously running VMs (see [Yandex Compute Cloud pricing](../../compute/pricing.md)).
* Fee for public static IP addresses (see [Yandex Virtual Private Cloud pricing](../pricing.md)).
* Fee for using a network load balancer (see [Yandex Network Load Balancer pricing](../../network-load-balancer/pricing.md)).

## Set up your remote site {#remote-setup}

In this step, you will set up your remote site infrastructure, including a network, a subnet, and a VM you will use to access the web service.

{% note info %}

You can use your PC as the remote site. To do this, you need to know your public IP address and your subnet CIDR.

If you are going to use your PC as the remote site, you can skip this section and go to [Set up your cloud site](#cloud-setup).

{% endnote %}

### Create a network and a subnet {#remote-net}

1. Create the `remote-net` [network](../operations/network-create.md) with the **Create subnets** option disabled.
1. [Create a subnet](../operations/subnet-create.md) for your remote site test VM, configuring it as follows:

    * **Name**: `subnet-1`.
    * **Availability zone**: `ru-central1-b`.
    * **Network**: `remote-net`.
    * **CIDR**: `10.129.0.0/24`.

### Create a test VM {#remote-test-vm}

Create a VM you to test whether your web service is accessible from the internet.

{% list tabs group=instructions %}

- Management console {#console}

    1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you want to create your VM.
    1. Navigate to **Compute Cloud**.
    1. In the left-hand panel, select ![image](../../_assets/console-icons/server.svg) **Virtual machines**.
    1. Click **Create virtual machine**.
    1. Under **Boot disk image**, select [Ubuntu 22.04 LTS OS Login](https://yandex.cloud/en/marketplace/products/yc/ubuntu-2204-lts-oslogin).
    1. Under **Location**, select the `ru-central1-b` [availability zone](../../overview/concepts/geo-scope.md).
    1. Under **Network settings**:

        * In the **Subnet** field, select `subnet-1`. 
        * In the **Public IP address** field, select `Auto`.
    1. Under **Access**, select **Access by OS Login** to [connect](../../compute/operations/vm-connect/os-login.md) to your VM and manage its access using [OS Login](../../organization/concepts/os-login.md) in Yandex Identity Hub.

        With OS Login, you can connect to VMs using SSH keys and SSH certificates via a standard SSH client or the [CLI](../../cli/quickstart.md). OS Login enables rotating the SSH keys used to access VMs, providing the most [secure](../../security/domains/iaas-checklist.md#vm-security) access option.

    1. Under **General information**, specify the VM name: `vm-1`.
    1. Click **Create VM**.
    1. Get the new VM public IP address:

        1. Once the `vm-1` status changes to `Running`, click its name.
        1. On the VM overview page that opens, copy **Public IPv4 address** under **Network interface**.

            Save the copied IP address as you will need it later when [creating a security group](#create-vpn-sg).

{% endlist %}

## Set up your cloud site {#cloud-setup}

### Set up a cloud network {#setup-cloud-net}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), navigate to the folder where you want to deploy your infrastructure.
  1. Navigate to **Virtual Private Cloud**.
  1. [Create a cloud network](../operations/network-create.md) named `network` with the **Create subnets** option disabled.
  1. In `network`, [create subnets](../operations/subnet-create.md) with the following settings:
  
      1. Subnet hosting the `web-node-a` VM and the `vpn` IPSec instance:
          * **Name**: `subnet-a`.
          * **Availability zone**: `ru-central1-a`.
          * **Network**: `network`.
          * **CIDR**: `192.168.5.0/24`.
  
      1. Subnet hosting the `web-node-b` VM:
          * **Name**: `subnet-b`.
          * **Availability zone**: `ru-central1-b`.
          * **Network**: `network`.
          * **CIDR**: `192.168.15.0/24`.
  
      1. Subnet hosting the `web-node-d` VM:
          * **Name**: `subnet-d`.
          * **Availability zone**: `ru-central1-d`.
          * **Network**: `network`.
          * **CIDR**: `192.168.25.0/24`.

{% endlist %}

### Reserve two static public IP addresses {#reserve-ips}

You will need two static public IP addresses: one for your VPN gateway and another for the network load balancer.

{% list tabs group=instructions %}

- Management console {#console}

    1. In the [management console](https://console.yandex.cloud), navigate to the folder where you will reserve your IP addresses.
    1. Navigate to **Virtual Private Cloud**.
    1. In the left-hand panel, select ![image](../../_assets/console-icons/map-pin.svg) **Public IP addresses**.
    1. Click **Reserve public IP address**.
    1. In the window that opens, select the `ru-central1-a` availability zone and click ** Reserve**.
    1. Repeat steps 4 and 5 and reserve the second IP address in the `ru-central1-b` availability zone.

{% endlist %}

### Create and configure security groups {#create-security-group}

To split traffic between network segments, create security groups with rules for inbound and outbound traffic.

#### Create a security group for the VPN gateway {#create-vpn-sg}

You need to allow inbound and outbound internet traffic on UDP ports `500` and `4500` used by the IPsec VPN. You also need to allow traffic between the subnets of your virtual network and the remote site network.

{% list tabs group=instructions %}

- Management console {#console}

    1. In the [management console](https://console.yandex.cloud), navigate to the folder where you want to create a security group. 
    1. Navigate to **Virtual Private Cloud**.
    1. In the left-hand panel, select ![image](../../_assets/console-icons/shield.svg) **Security groups**.
    1. Click **Create security group**.
    1. Specify the security group name: `vpn-sg`.
    1. In the **Network** field, select `network`.
    1. Under **Rules**, [create](../operations/security-group-add-rule.md) rules from the table below:

       #|
       || **Traffic<br/>direction** | **Description** | **Port range** | **Protocol** | **Source /<br/>Destination name** | **CIDR blocks** ||
       || Inbound | `udp500` | `500` | `UDP` | `CIDR` | `<remote_VM_public_IP_address>/32` ||
       || Inbound | `udp4500` | `4500` | `UDP` | `CIDR` | `<remote_VM_public_IP_address>/32` ||
       || Inbound | `internal` | `0-65535` | `Any` | `CIDR` | 
         * `192.168.5.0/24`
         * `192.168.15.0/24`
         * `192.168.25.0/24`
         * `10.129.0.0/24` ^1^ ||
       || Outbound | `udp500` | `500` | `UDP` | `CIDR` | `<remote_VM_public_IP_address>/32` ||
       || Outbound | `udp4500` | `4500` | `UDP` | `CIDR` | `<remote_VM_public_IP_address>/32` ||
       || Outbound | `intersubnet` | `0-65535` | `Any` | `CIDR` | 
         * `192.168.5.0/24`
         * `192.168.15.0/24`
         * `192.168.25.0/24`
         * `10.129.0.0/24` ^1^ ||
       |#

       ^1^ If you are using your local PC as the test VM, specify your subnet CIDR here.

    1. Click **Create**.

{% endlist %}

#### Create a security group for your web service VMs {#create-service-sg}

{% list tabs group=instructions %}

- Management console {#console}
  
    1. In the [management console](https://console.yandex.cloud), navigate to the folder where you want to create a security group. 
    1. Navigate to **Virtual Private Cloud**.
    1. In the left-hand panel, select ![image](../../_assets/console-icons/shield.svg) **Security groups**.
    1. Click **Create security group**.
    1. Specify the security group name: `web-service-sg`.
    1. In the **Network** field, select `network`.
    1. Under **Rules**, [create](../operations/security-group-add-rule.md) rules from the table below:
   
       #|
       || **Traffic<br/>direction** | **Description** | **Port range** | **Protocol** | **Source /<br/>Destination name** | **CIDR blocks** /<br/>**Security group** ||
       || Ingress | `ssh` | `22` | `TCP` | `CIDR` | `0.0.0.0/0` ||
       || Inbound | `anyself` | `0-65535` | `Any` | `Security group` | `Current` ||
       || Inbound | `healthchecks` | `80` | `TCP` | `Load balancer healthchecks` | — ||
       || Outbound | `self` | `0-65535` | `Any` | `Security group` | `Current` ||
       |#

    1. Click **Create**.

{% endlist %}

### Create and configure your cloud VMs {#setup-cloud-vms}

#### Create web service VMs in all availability zones {#create-vms}

{% list tabs group=instructions %}

- Management console {#console}

    1. In the [management console](https://console.yandex.cloud), select the folder where you want to create your VMs.
    1. Navigate to **Compute Cloud**.
    1. In the left-hand panel, select ![image](../../_assets/console-icons/server.svg) **Virtual machines**.
    1. Click **Create virtual machine**.
    1. Under **Boot disk image**, navigate to the **Marketplace** tab and select [Drupal 10](https://yandex.cloud/en/marketplace/products/yc/drupal-8).
    1. Under **Location**, select the `ru-central1-a` availability zone.
    1. Under **Network settings**:

       * Select `subnet-a`. 
       * In the **Public IP address** field, select `No address`.
       * Select the `web-service-sg` security group.
    1. Under **Access**:

        * Select the **SSH key** connection option.
        * In the **Login** field, set a username.

            {% note alert %}

            Do not use `root` or other reserved usernames. For operations requiring root privileges, use the `sudo` command.

            {% endnote %}

        * In the **SSH key** field, select the SSH key saved in your [organization user](../../organization/concepts/membership.md) profile.
          
          If there are no SSH keys in your profile or you want to add a new key:
          
          1. Click **Add key**.
          1. Enter a name for the SSH key.
          1. Select one of the following:
          
              * `Enter manually`: Paste the contents of the public SSH key. You need to [create](../../compute/operations/vm-connect/ssh.md#creating-ssh-keys) an SSH key pair on your own.
              * `Load from file`: Upload the public part of the SSH key. You need to create an SSH key pair on your own.
              * `Generate key`: Automatically create an SSH key pair.
              
                When adding a new SSH key, an archive containing the key pair will be created and downloaded. In Linux or macOS-based operating systems, unpack the archive to the `/home/<user_name>/.ssh` directory. In Windows, unpack the archive to the `C:\Users\<user_name>/.ssh` directory. You do not need additionally enter the public key in the management console.
          
          1. Click **Add**.
          
          The system will add the SSH key to your organization user profile. If the organization has [disabled](../../organization/operations/os-login-access.md) the ability for users to add SSH keys to their profiles, the added public SSH key will only be saved in the user profile inside the newly created resource.
       
    1. Under **General information**, specify the VM name: `web-node-a`.
    1. Click **Create VM**.
    1. Repeat steps 4 through 10 to create the `web-node-b` and `web-node-d` VMs in the `ru-central1-b` and `ru-central1-d` availability zones and `subnet-b` and `subnet-d` subnets, respectively.

{% endlist %}

#### Create an IPSec instance for remote access {#create-ipsec-instance}

To provide secure access to your resources, create an IPSec instance.

{% list tabs group=instructions %}

- Management console {#console}

    1. In the [management console](https://console.yandex.cloud), navigate to the folder where you want to create your VM.
    1. Navigate to **Compute Cloud**.
    1. In the left-hand panel, select ![image](../../_assets/console-icons/server.svg) **Virtual machines**.
    1. Click **Create virtual machine**.
    1. Under **Boot disk image**, navigate to the **Marketplace** tab and select the [IPSec instance](https://yandex.cloud/en/marketplace/products/yc/ipsec-instance-ubuntu) image.
    1. Under **Location**, select the `ru-central1-a` availability zone.
    1. Under **Network settings**:

        * Select `subnet-a`.
        * In the **Public IP address** field, select `List` and then select the previously reserved IP address from the list that opens.
        * Select the `vpn-sg` security group.

    1. Under **Access**, select **SSH key** and specify the VM access credentials:

        * In the **Login** field, enter a username. Do not use `root` or other reserved usernames. To perform operations requiring root privileges, use the `sudo` command.
        * In the **SSH key** field, select the SSH key saved in your [organization user](../../organization/concepts/membership.md) profile.
          
          If there are no SSH keys in your profile or you want to add a new key:
          
          1. Click **Add key**.
          1. Enter a name for the SSH key.
          1. Select one of the following:
          
              * `Enter manually`: Paste the contents of the public SSH key. You need to [create](../../compute/operations/vm-connect/ssh.md#creating-ssh-keys) an SSH key pair on your own.
              * `Load from file`: Upload the public part of the SSH key. You need to create an SSH key pair on your own.
              * `Generate key`: Automatically create an SSH key pair.
              
                When adding a new SSH key, an archive containing the key pair will be created and downloaded. In Linux or macOS-based operating systems, unpack the archive to the `/home/<user_name>/.ssh` directory. In Windows, unpack the archive to the `C:\Users\<user_name>/.ssh` directory. You do not need additionally enter the public key in the management console.
          
          1. Click **Add**.
          
          The system will add the SSH key to your organization user profile. If the organization has [disabled](../../organization/operations/os-login-access.md) the ability for users to add SSH keys to their profiles, the added public SSH key will only be saved in the user profile inside the newly created resource.

    1. Under **General information**, specify the VM name: `vpn`.
    1. Click **Create VM**.
    1. Once the `vpn` VM status changes to `Running`, copy its **Internal IPv4**.
    
        You will need the internal gateway address to configure a static route.

{% endlist %}

### Configure VPN routing {#vpn-routing}

Configure routing between your remote site subnet and IPSec instance.

#### Create a route table {#create-route-table}

Create a [route table](../concepts/routing.md#rt-vpc) and add [static routes](../concepts/routing.md#static):

{% list tabs group=instructions %}

- Management console {#console}

    1. In the [management console](https://console.yandex.cloud), navigate to the folder where you want to configure routing.
    1. Navigate to **Virtual Private Cloud**.
    1. Select `network`.
    1. In the left-hand panel, select ![image](../../_assets/console-icons/route.svg) **Routing tables**.
    1. Click **Create routing table**.
    1. Specify the route table name: `vpn-route`.
    1. Under **Static routes**, click **Add**.
    1. In the window that opens:
       * In the **Destination prefix** field, enter `10.129.0.0/24`.

           If you are using your local PC as the test VM, specify your subnet CIDR.
       * In the **Next hop** field, specify the IPSec gateway internal IP address.
       * Click **Add**.
    1. Click **Create routing table**.

{% endlist %}

#### Associate the route table with all subnets {#associate-route-table}

To use static routes, associate the route table with all subnets in your cloud `network`.

{% list tabs group=instructions %}

- Management console {#console}

    1. In the [management console](https://console.yandex.cloud), navigate to your cloud network folder.
    1. Navigate to **Virtual Private Cloud**.
    1. In the left-hand panel, select ![image](../../_assets/console-icons/nodes-right.svg) **Subnets**.
    1. Click ![image](../../_assets/console-icons/ellipsis.svg) next to `subnet-a` and select **Link routing table**.
    1. In the window that opens, select the `vpn-route` table in the **Route table** field.
    1. Click **Link**.
    1. Repeat steps 4 through 6 to associate the `vpn-route` table with `subnet-b` and `subnet-d`.

{% endlist %}

### Create a network load balancer {#create-load-balancer}

The network load balancer will distribute incoming traffic across your web service VMs in the target group. 

To create a network load balancer:

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), navigate to the folder where you want to create a load balancer.
  1. Navigate to **Network Load Balancer**.
  1. Click **Create a network load balancer**.
  1. Specify the load balancer name: `web-service-lb`.
  1. In the **Public address** field, select `List` and specify the public static IP address.
  1. Under **Listeners**, click **Add listener**. In the window that opens:

      1. Specify the listener name: `web-service-lb-listener`.
      1. In the **Port** field, specify `80`.
      1. In the **Target port** field, specify `80`.
      1. Click **Add**.
  1. Under **Target groups**, click **Add target group**.

      1. In the **Target group** field, select ![plus](../../_assets/console-icons/plus.svg) **Create target group**. In the window that opens:

          1. Specify the target group name: `web-tg`.
          1. Select the `web-node-a`, `web-node-b`, and `web-node-d` VMs.
          1. Click **Create**.
      1. Select the `web-tg` target group.
  1. In the selected target group section:

      1. Click **Configure**.
      1. In the window that opens, select `TCP` in the **Type** field and click **Apply**.
  1. Click **Create**.

{% endlist %}

## Test the solution {#test}

Check that your infrastructure works properly and your web service VMs do not receive any external traffic:

1. Run the following command on your remote computer:

    ```bash
    curl <public_IP_address_of_network_load_balancer>
    ```
    
    You should get no response because the system will block traffic to your Drupal servers.
1. [Add](../operations/security-group-add-rule.md) two new inbound traffic rules to the `web-service-sg` security group:

   #|
   || **Description** | **Port range** | **Protocol** | **Source /<br/>Destination name** | **CIDR blocks** ||
   || http-external-vm | 80 | TCP | CIDR | `<remote_VM_public_IP_address>/32` ||
   || https-external-vm | 443 | TCP | CIDR | `<remote_VM_public_IP_address>/32` ||
   |#

   These rules allow access to the network load balancer’s target group VMs from your remote VM public IP address.

1. Run this command on your remote computer again:

    ```bash
    curl <public_IP_address_of_network_load_balancer>
    ```

    You should get the Drupal home page HTML code, which means the rules you added to the security group allowed network access to the Drupal VMs from your remote computer IP address.

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

To stop paying for the resources you created:
1. [Delete](../../compute/operations/vm-control/vm-delete.md) the VMs.
1. [Delete](../../network-load-balancer/operations/load-balancer-delete.md) the network load balancer.
1. [Delete](../operations/address-delete.md) the static public IP addresses you reserved.
1. You can also delete the [route table](../operations/delete-route-table.md), [security groups](../operations/security-group-delete.md), [subnets](../operations/subnet-delete.md), and [networks](../operations/network-delete.md).