# Implementing a secure high-availability network infrastructure with a dedicated DMZ based on the Check Point NGFW


In this tutorial, we will deploy a high-availability fail-safe network infrastructure with a dedicated [DMZ](https://en.wikipedia.org/wiki/DMZ_(computing)) segment and comprehensive protection based on the [Check Point next-generation firewall](https://www.checkpoint.com/ru/cloudguard/cloud-network-security/iaas-public-cloud-security/).

The infrastructure elements reside in two [availability zones](../../overview/concepts/geo-scope.md); we will also group them by purpose, placing the groups into different [folders](../../resource-manager/concepts/resources-hierarchy.md#folder). This solution enables you to publish web resources, e.g., front-end applications, in a DMZ, restricting access to the internal network and thus ensuring its extra security.

![image](../../_assets/tutorials/high-accessible-dmz.svg)

Our solution uses the following folders:

* **public** that contains [Application Load Balancer](../index.md) enabling public access to DMZ applications from the internet.
* **mgmt** that contains NGFWs and cloud infrastructure management resources, including `fw-a` and `fw-b` firewall VMs, `mgmt-server`, which is a firewall management server VM, and `jump-vm`, a VM for accessing the VPN protected segment.
* **dmz** that enables you to publish open-access applications.
* **app** and **database** that contain application business logic; we will not use them in this tutorial.

For more information, see the [project repository](https://github.com/yandex-cloud-examples/yc-dmz-with-high-available-ngfw/blob/main/README.md).

To deploy a secure high-availability network infrastructure with a dedicated DMZ based on the Check Point next-generation firewall:

1. [Get your cloud ready](#prepare-cloud).
1. [Set up your environment](#prepare-environment).
1. [Deploy your resources](#create-resources).
1. [Set up firewall gateways](#configure-gateways).
1. [Enable the route switcher](#enable-route-switcher).
1. [Test the solution for performance and fault tolerance](#test-accessibility).

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

## Next-Generation Firewall {#ngfw}

We will use a next-generation firewall for cloud network protection and segmentation, creating a dedicated DMZ for publicly accessible applications. [Yandex Cloud Marketplace](https://yandex.cloud/en/marketplace?categories=security) offers multiple NGFW solutions.

In this tutorial, we will use the [Check Point CloudGuard IaaS](https://yandex.cloud/en/marketplace/products/checkpoint/cloudguard-iaas-firewall-tp-payg-m) solution. Its features include:

* Firewalling
* NAT
* Intrusion prevention
* Antivirus
* Bot protection
* Application-layer granular traffic control
* Session logging
* Centralized management with Check Point Security Management

In this tutorial, we will configure Check Point CloudGuard IaaS with basic access control and NAT policies.

## Get your cloud ready {#prepare-cloud}

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 infrastructure support cost includes:

* Fee for continuously running VMs (see [Yandex Compute Cloud pricing](../../compute/pricing.md)).
* Fee for using Application Load Balancer (see [Yandex Application Load Balancer pricing](../pricing.md)).
* Fee for using Network Load Balancer (see [Yandex Network Load Balancer pricing](../../network-load-balancer/pricing.md)).
* Fee for using public IP addresses and outgoing traffic (see [Yandex Virtual Private Cloud pricing](../../vpc/pricing.md)).
* Fee for using functions (see [Yandex Cloud Functions pricing](../../functions/pricing.md)).
* Fee for using the [CheckPoint NGFW](https://yandex.cloud/en/marketplace/products/checkpoint/cloudguard-iaas-firewall-tp-payg-m).

### Required quotas {#required-quotes}

{% note warning %}

In this tutorial, you will deploy a resource-intensive infrastructure.

{% endnote %}

Make sure you have sufficient cloud [quotas](../../overview/concepts/quotas-limits.md) not used by other projects.

{% cut "Resources used by this tutorial" %}

   | Resource | Quantity |
   | ----------- | ----------- |
   | Folders | 7 |
   | Instance groups | 1 |
   | Virtual machines | 6 |
   | VM vCPUs | 18 |
   | VM RAM | 30 GB |
   | Disks | 6 |
   | SSD size | 360 GB |
   | HDD size | 30 GB |
   | Cloud networks | 7 |
   | Subnets | 14 |
   | Route tables | 4 |
   | Security groups | 10 |
   | Static public IP addresses | 2 |
   | Public IP addresses | 2 |
   | Static routes | 17 |
   | Buckets | 1 |
   | Cloud functions | 1 |
   | Cloud function triggers | 1 |
   | Total RAM for all running functions | 128 MB |
   | Network load balancers (NLB) | 2 |
   | NLB target groups | 2 |
   | Application load balancers (ALB) | 1 |
   | ALB backend groups | 1 |
   | ALB target groups | 1 |

{% endcut %}

## Set up your environment {#prepare-environment}

This tutorial uses Windows software and [Windows Subsystem for Linux](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux) (WSL).
To deploy the infrastructure, we will use [Terraform](https://www.terraform.io/).

### Configure WSL {#setup-wsl}

1. Check whether WSL is installed on your PC. Do it by running this command in the CLI terminal:

   ```bash
   wsl -l
   ```

   If WSL is installed, the terminal will return a list of available distributions, such as the following:

   ```bash
   Windows Subsystem for Linux Distributions:
   docker-desktop (Default)
   docker-desktop-data
   Ubuntu
   ```

1. If WSL is not installed, [install](https://learn.microsoft.com/en-us/windows/wsl/install) it and repeat the previous step.
1. Additionally, you can install your preferred Linux distribution, e.g., [Ubuntu](https://ubuntu.com/tutorials/install-ubuntu-on-wsl2-on-windows-11-with-gui-support#1-overview), on top of WSL.
1. To set the installed distribution as default, run this command:

   ```bash
   wsl --setdefault ubuntu
   ```

1. To switch your terminal to Linux, run this command:

   ```bash
   wsl ~
   ```

{% note info %}

We use the Linux terminal to perform the following steps.

{% endnote %}

### Create a cloud administrator service account {#create-account}

{% list tabs %}

- Management 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 service account.
   1. Navigate to **Identity and Access Management**.
   1. Click **Create service account**.
   1. Name your service account, e.g., `sa-terraform`.

       The naming requirements are as follows:

       * Length: between 3 and 63 characters.
       * It can only contain lowercase Latin letters, numbers, and hyphens.
       * It must start with a letter and cannot end with a hyphen.

       Make sure the service account name is unique within your cloud.

   1. Click **Create**.

   1. Assign the admin [role](../../iam/concepts/access-control/roles.md) to the service account:

       1. On the management console [home page](https://console.yandex.cloud), select your cloud.
       1. Navigate to the ![image](../../_assets/console-icons/persons-lock.svg) **Access bindings** tab.
       1. Click ![image](../../_assets/console-icons/person-plus.svg) **Configure access**.
       1. In the window that opens, click **Service accounts** and select the `sa-terraform` service account.
       1. Click ![image](../../_assets/console-icons/plus.svg) **Add role** and select the `admin` role.
       1. Click **Save**.

- CLI

   If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

   The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

   1. Create a service account:

         ```bash
         yc iam service-account create --name sa-terraform
         ```

         Where `name` is the service account name. The naming requirements are as follows:

         * Length: between 3 and 63 characters.
         * It can only contain lowercase Latin letters, numbers, and hyphens.
         * It must start with a letter and cannot end with a hyphen.

         Result:

         ```text
         id: ajehr0to1g8bh0la8c8r
         folder_id: b1gv87ssvu497lpgjh5o
         created_at: "2023-03-04T09:03:11.665153755Z"
         name: sa-terraform
         ```

   1. Assign the admin [role](../../iam/concepts/access-control/roles.md) to the account:

         ```bash
         yc resource-manager cloud add-access-binding <cloud_ID> \
           --role admin \
           --subject serviceAccount:<service_account_ID>
         ```

         Result:

         ```text
         done (1s)
         ```

- API

   To create a service account, use the [create](../../iam/api-ref/ServiceAccount/create.md) REST API method for the [ServiceAccount](../../iam/api-ref/ServiceAccount/index.md) resource or the [ServiceAccountService/Create](../../iam/api-ref/grpc/ServiceAccount/create.md) gRPC API call.

   To assign the service account a role for a cloud or folder, use the `updateAccessBindings` REST API method for the [Cloud](../../resource-manager/api-ref/Cloud/index.md) or [Folder](../../resource-manager/api-ref/Folder/index.md) resource:
   
   1. Select the role to assign to the service account. You can find the description of the roles in the Yandex Identity and Access Management documentation in the [Yandex Cloud role reference](../../iam/roles-reference.md).
   1. [Get](../../resource-manager/operations/folder/get-id.md) the ID of the service accounts folder.
   1. [Get](../../iam/operations/iam-token/create.md) an IAM token for authentication in the Yandex Cloud API.
   1. Get a list of folder service accounts to find out their IDs:
   
       ```bash
       export FOLDER_ID=b1gvmob95yys********
       export IAM_TOKEN=CggaATEVAgA...
       curl \
         --header "Authorization: Bearer ${IAM_TOKEN}" \
         "https://iam.api.cloud.yandex.net/iam/v1/serviceAccounts?folderId=${FOLDER_ID}"
       ```
   
       Result:
   
   
       ```json
       {
        "serviceAccounts": [
         {
          "id": "ajebqtreob2d********",
          "folderId": "b1gvmob95yys********",
          "createdAt": "2018-10-18T13:42:40Z",
          "name": "my-robot",
          "description": "my description"
         }
        ]
       }
       ```
   
   1. Create the request body, e.g., in the `body.json` file. Set the `action` property to `ADD` and `roleId` to the appropriate role, such as `editor`, and specify the `serviceAccount` type and service account ID in the `subject` property:
   
       **body.json:**
       ```json
       {
         "accessBindingDeltas": [{
           "action": "ADD",
           "accessBinding": {
             "roleId": "editor",
             "subject": {
               "id": "ajebqtreob2d********",
               "type": "serviceAccount"
             }
           }
         }]
       }
       ```
   1. Assign a role to a service account. For example, for a folder with the `b1gvmob95yys********` ID:
      
      ```bash
      export FOLDER_ID=b1gvmob95yys********
      export IAM_TOKEN=CggaAT********
      curl \
        --request POST \
        --header "Content-Type: application/json" \
        --header "Authorization: Bearer ${IAM_TOKEN}" \
        --data '@body.json' \
        "https://resource-manager.api.cloud.yandex.net/resource-manager/v1/folders/${FOLDER_ID}:updateAccessBindings"
      ```

{% endlist %}

### Install the required tools {#install-utilities}

1. Install [Git](https://en.wikipedia.org/wiki/Git) using the following command:

   ```bash
   sudo apt install git
   ```

1. Install Terraform:

   1. Navigate to the root directory:

      ```bash
      cd ~
      ```

   1. Create the `terraform` directory and open it:

      ```bash
      mkdir terraform
      cd terraform
      ```

   1. Download the `terraform_1.3.9_linux_amd64.zip` file:

      ```bash
      curl \
        --location \
        --remote-name \
        https://hashicorp-releases.yandexcloud.net/terraform/1.3.9/terraform_1.3.9_linux_amd64.zip
      ```

   1. Install `zip` and unpack the ZIP archive:

      ```bash
      apt install zip
      unzip terraform_1.3.9_linux_amd64.zip
      ```

   1. Add the path to the directory with the executable to the `PATH` variable:

      ```bash
      export PATH=$PATH:~/terraform
      ```

   1. Make sure Terraform is installed by running this command:

      ```bash
      terraform -help
      ```

1. Create a configuration file specifying the Terraform provider source:

   1. Create the `.terraformrc` file in `nano`:

      ```bash
      cd ~
      nano .terraformrc
      ```

   1. Add the following section to the file:

      ```text
      provider_installation {
        network_mirror {
          url = "https://terraform-mirror.yandexcloud.net/"
          include = ["registry.terraform.io/*/*"]
        }
        direct {
          exclude = ["registry.terraform.io/*/*"]
        }
      }
      ```

      For more information about mirror settings, see the relevant [Terraform guides](https://www.terraform.io/cli/config/config-file#explicit-installation-method-configuration).

## Deploy your resources {#create-resources}

1. Clone the `yandex-cloud-examples/yc-dmz-with-high-available-ngfw` GitHub repository and navigate to the `yc-dmz-with-high-available-ngfw` directory:

    ```bash
    git clone https://github.com/yandex-cloud-examples/yc-dmz-with-high-available-ngfw.git
    cd yc-dmz-with-high-available-ngfw
    ```

1. Set up a CLI profile to run operations under the service account:

   {% list tabs %}

   - CLI

      If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

      The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

      1. Create an [authorized key](../../iam/concepts/authorization/key.md) for your service account and save it to the file:

         ```bash
         yc iam key create \
           --service-account-id <service_account_ID> \
           --folder-id <ID_of_folder_with_service_account> \
           --output key.json
         ```

         Where:

         * `service-account-id`: Service account ID.
         * `folder-id`: Service account folder ID.
         * `output`: Authorized key file name.

         Result:

         ```text
         id: aje8nn871qo4********
         service_account_id: ajehr0to1g8b********
         created_at: "2023-03-04T09:16:43.479156798Z"
         key_algorithm: RSA_2048
         ```

      1. Create a CLI profile to run operations under the service account:

         ```bash
         yc config profile create sa-terraform
         ```

         Result:

         ```text
         Profile 'sa-terraform' created and activated
         ```

      1. Configure the profile:

         ```bash
         yc config set service-account-key key.json
         yc config set cloud-id <cloud_ID>
         yc config set folder-id <folder_ID>
         ```

         Where:

         * `service-account-key`: Service account authorized key file.
         * `cloud-id`: [Cloud ID](../../resource-manager/operations/cloud/get-id.md).
         * `folder-id`: [Folder ID](../../resource-manager/operations/folder/get-id.md).

      1. Add the credentials to the environment variables:

         ```bash
         export YC_TOKEN=$(yc iam create-token)
         export YC_CLOUD_ID=$(yc config get cloud-id)
         export YC_FOLDER_ID=$(yc config get folder-id)
         ```

    {% endlist %}

1. Get your PC IP address:

      ```bash
      curl 2ip.ru
      ```

      Result:

      ```text
      192.2**.**.**
      ```

1. Open the `terraform.tfvars` file in `nano` and edit the following:

   1. Cloud ID line:

      ```text
      cloud_id = "<cloud_ID>"
      ```

   1. Line with a list of public IP addresses allowed to access `jump-vm`:

      ```text
      trusted_ip_for_access_jump-vm = ["<PC_external_IP_address>/32"]
      ```

1. Deploy your cloud resources with Terraform:

   1. Initialize Terraform:

       ```bash
       terraform init
       ```

   1. Check the Terraform file configuration:

       ```bash
       terraform validate
       ```

   1. Check the list of new cloud resources:

       ```bash
       terraform plan
       ```

   1. Create the resources:

       ```bash
       terraform apply
       ```

## Set up firewall gateways {#configure-gateways}

In this tutorial, we will configure the `FW-A` and `FW-B` firewalls with basic access control and NAT policies required to test performance and fault tolerance, but insufficient for the production environment.

### Connect to the management segment via a VPN {#connect-via-vpn}

After deploying the infrastructure, the `mgmt` folder will contain the `jump-vm` Ubuntu instance with the configured [WireGuard VPN](https://www.wireguard.com/) allowing secure connections. Set up a VPN tunnel between your PC and the `mgmt`, `dmz`, `app`, and `database` segment subnets through `jump-vm`.

To set up the VPN tunnel:

1. Get your Linux username:

   ```bash
   whoami
   ```

1. [Install](https://download.wireguard.com/windows-client/wireguard-installer.exe) WireGuard on your PC.
1. Open WireGuard and click **Add Tunnel**.
1. In the dialog that opens, select the `jump-vm-wg.conf` file in the `yc-dmz-with-high-available-ngfw` directory.

   To find a Linux, e.g., Ubuntu, directory, type the file path in the dialog address bar:

   ```bash
   \\wsl$\Ubuntu\home\<Ubuntu_user_name>\yc-dmz-with-high-available-ngfw
   ```

   Where `<Ubuntu_user_name>` is your Linux username you got in the previous step.

1. Click **Activate** to activate the tunnel.
1. Check whether you can connect to the management server through the WireGuard VPN tunnel by running this command in the terminal:

   ```bash
   ping 192.168.1.100
   ```

   {% note warning %}

   If `ping` fails, make sure the `mgmt-jump-vm-sg` [security group](../../vpc/concepts/security-groups.md) inbound rules include your PC external IP address.

   {% endnote %}


### Run SmartConsole {#setup-smartconsole}

To set up and manage [Check Point](https://en.wikipedia.org/wiki/Check_Point), install and run the SmartConsole GUI client: 

1. Connect to the NGFW management server by opening `https://192.168.1.100` in your browser.
1. Sign in using `admin` as both the username and the password.
1. You will enter Gaia Portal where you can download the SmartConsole GUI client by clicking **Manage Software Blades using SmartConsole. Download Now!**.
1. Install SmartConsole on your PC.
1. Get a password to access SmartConsole by running this command in the terminal:

    ```bash
    terraform output fw_smartconsole_mgmt-server_password
    ```

1. Open SmartConsole and sign in as `admin` with the password you got in the previous step, specifying `192.168.1.100` as your management server IP address.

### Add firewall gateways {#add-gateways}

Use the wizard to add the `FW-A` firewall gateway to the management server:

1. In the **Objects** drop-down list at the top left, select **More object types → Network Object → Gateways and Servers → New Gateway...**.
1. Click **Wizard Mode**.
1. In the dialog that opens, specify the following:

   * **Gateway name**: `FW-A`
   * **Gateway platform**: `CloudGuard IaaS`
   * **IPv4**: `192.168.1.10`

1. Click **Next**.
1. Get the firewall password by running this command in the terminal:

    ```bash
    terraform output fw_sic-password
    ```

1. Enter this password in the **One-time password** field.
1. Click **Next**, and then **Finish**.

Similarly, add the `FW-B` firewall gateway with the values below:

   * **Gateway name**: `FW-B`
   * **IPv4**: `192.168.2.10`

### Configure the `FW-A` gateway network interfaces {#setup-gateways-fw-a}

Configure the `eth0` network interface:

1. In the **Gateways & Servers** tab, open the `FW-A` gateway setup dialog.
1. In the **Topology** table within the **Network Management** tab, select the `eth0` interface and click **Modify...**.
1. Under **Leads To**, select **Override**.
1. Next to **Specific**, hover over the `FW-A-eth0` interface name and click the edit icon in the window that opens.
1. In the dialog that opens, rename `FW-A-eth0` to `mgmt`.
1. Under **Security Zone**, enable **Specify Security Zone** and select **InternalZone**.

Similarly, configure the `eth1`, `eth2`, `eth3`, and `eth4` network interfaces:

1. For `eth1`, specify **ExternalZone** under **Security Zone**. Do not rename this interface.
1. Rename the `eth2` interface to `dmz`, enable **Interface leads to DMZ**, and specify **DMZZone**.

   Set up **Automatic Hide NAT** to hide the addresses of internet-facing VMs hosted in the DMZ segment. Proceed as follows:

      1. In the `dmz` interface edit dialog, click `Net_10.160.1.0` and navigate to the **NAT** tab.
      1. Enable **Add automatic address translation rules**, select **Hide** from the drop-down list, and then enable **Hide behind gateway**.
      1. Repeat these steps for `Net_10.160.2.0`.

1. Rename the `eth3` interface to `app` and specify **InternalZone**.
1. Rename the `eth4` interface to `database` and specify **InternalZone**.

### Configure the `FW-B` gateway network interfaces {#setup-gateways-fw-b}

Configure the `FW-B` gateway network interfaces the same way as you did for `FW-A`. Give the interfaces existing names from the list.

To select an already specified interface name:

1. Under **Leads To**, select **Override**.
1. Find the relevant name in the drop-down list next to **Specific**.

{% note warning %}

Renaming the interfaces again will cause the network object name replication error when setting security policies.

{% endnote %}


### Create network objects {#create-network-objects}

1. In the **Objects** drop-down list at the top left, select **New Network...** and create the `public - a` and `public - b` networks with the following settings:

    | Name | Network address | Net mask |
    | ----------- | ----------- | ----------- |
    | public - a | 172.16.1.0 | 255.255.255.0 |
    | public - b | 172.16.2.0 | 255.255.255.0 |

1. Select **New Network Group...**, create the `public` group, and add the `public - a` and `public - b` networks to it.
1. Select **New Host...** and create hosts with the following parameters:

    | Name | IPv4 address |
    | ----------- | ----------- |
    | dmz-web-server | 10.160.1.100 |
    | FW-a-dmz-IP | 10.160.1.10 |
    | FW-a-public-IP | 172.16.1.10 |
    | FW-b-dmz-IP | 10.160.2.10 |
    | FW-b-public-IP | 172.16.2.10 |

1. Select **More object types → Network Object → Service → New TCP...** and create a TCP service for the DMZ application, specifying `TCP_8080` as its name and `8080` as the port.

### Set security policy rules {#define-policies}

To add a security rule:

1. In the **Security policies** tab, select **Policy** under **Access Control**.
1. Right-click the rule table area and, in the context menu that opens, select **Above** or **Below** next to **New Rule**.
1. In the new line that appears:
   * In the **Name** column, specify `Web-server port forwarding on FW-a`.
   * In the **Source** column, click `+` and select `public`.
   * In the **Destination** column, select `FW-a-public-IP`.
   * In the **Services & Applications** column, select `TCP_8080`.
   * In the **Action** column, select `Accept`.
   * In the **Track** column, select `Log`.
   * In the **Install On** column, select `FW-a`.


In the same way, add other rules from the table below; these rules will allow you to test the firewall policies, pass NLB health checks, publish a test application from the DMZ segment, and run a fault tolerance test.

   | No | Name | Source | Destination | VPN | Services & Applications | Action | Track | Install On |
   | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- |
   | 1 | Web-server port forwarding on FW-a | public | FW-a-public-IP | Any | TCP_8080 | Accept | Log | FW-a |
   | 2 | Web-server port forwarding on FW-b | public | FW-b-public-IP | Any | TCP_8080 | Accept | Log | FW-b |
   | 3 | FW management & NLB healthcheck | mgmt | FW-a, FW-b, mgmt-server | Any | https, ssh | Accept | Log | Policy Targets (All gateways)  |
   | 4 | Stealth | Any | FW-a, FW-b, mgmt-server | Any | Any | Drop | Log | Policy Targets (All gateways) |
   | 5 | mgmt to DMZ | mgmt | dmz | Any | Any | Accept | Log | Policy Targets (All gateways) |
   | 6 | mgmt to app | mgmt | app | Any | Any | Accept | Log | Policy Targets (All gateways) |
   | 7 | mgmt to database | mgmt | database | Any | Any | Accept | Log | Policy Targets (All gateways) |
   | 8 | ping from dmz to internet | dmz | ExternalZone | Any | icmp-requests (Group) | Accept | Log | Policy Targets (All gateways) |
   | 9 | Cleanup rule | Any | Any | Any | Any | Drop | Log | Policy Targets (All gateways) |

### Set up a static NAT table {#setup-static-nat}

`Source NAT` ensures that the return traffic of the user’s connection goes back through the same firewall as the user's request. `Destination NAT` routes user requests to the network load balancer upstream of the group of application web servers.

The headers of packets arriving from Application Load Balancer with user requests to the DMZ application will be translated to `Source IP` of the firewall DMZ interface and `Destination IP` of the web server traffic load balancer.

To set up the `FW-A` gateway NAT table:

1. Navigate to the **NAT** section under **Access Control**.
1. Right-click the rule table area and, in the context menu that opens, select **Above** or **Below** next to **New Rule**.
1. In the new line that appears:
   * In the **Original Source** column, click `+` and select `public`.
   * In the **Original Destination** column, select `FW-a-public-IP `.
   * In the **Original Services** column, select `TCP_8080`.
   * In the **Translated Source** column, select `FW-a-dmz-IP`.
   * In the **Translated Destination** column, select `dmz-web-server`.
   * In the **Install On** column, select `FW-a`.
1. Make sure to change the NAT method for `FW-a-dmz-IP` by right-clicking `FW-a-dmz-IP` in the table and selecting **NAT Method > Hide** in the context menu.

In the same way, set up the `FW-B` gateway static NAT table based on the table below:

   | No | Original Source | Original Destination | Original Services | Translated Source | Translated Destination | Translated Services | Install On |
   | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- |
   | 1 | public | FW-a-public-IP | TCP_8080 | FW-a-dmz-IP (Hide) | dmz-web-server | Original | FW-a |
   | 2 | public | FW-b-public-IP | TCP_8080 | FW-b-dmz-IP (Hide) | dmz-web-server | Original | FW-b |

### Apply the security policy rules {#apply-policies}

1. Click **Install Policy** at the top left of the screen.
1. In the dialog that opens, click **Push & Install**.
1. In the next dialog, click **Install** and wait for the process to complete.

## Enable the route switcher {#enable-route-switcher}

After you complete the NGFW setup, make sure `FW-A` and `FW-B` health checks return `Healthy`. In the Yandex Cloud [management console](https://console.yandex.cloud), navigate to **Network Load Balancer** in the `mgmt` folder and then go to the `route-switcher-lb-...` page. Expand the target group and make sure the targets are `Healthy`. If they are `Unhealthy`, make sure `FW-A` and `FW-B` are [configured](#configure-gateways) correctly and running.

Once the `FW-A` and `FW-B` status changes to `Healthy`, open the `route-switcher.tf` file and change the `route-switcher` `start_module` value to `true`. To enable the module, run these commands:

```bash
terraform plan
terraform apply
```

Within five minutes, the `route-switcher` module will start working, providing outbound traffic fault tolerance.

## Test the solution for performance and fault tolerance {#test-accessibility}

### Test the system {#test-accessibility}

1. To get the load balancer public IP address, run this command in the terminal:

    ```bash
    terraform output fw-alb_public_ip_address
    ```

1. Make sure your network infrastructure is accessible from outside by opening the following address in your browser:

    ```bash
    http://<ALB_load_balancer_public_IP_address>
    ```
    If your system is accessible from outside, you will see the `Welcome to nginx!` page.

1. Make sure the firewall rules allowing traffic are active. To do this, navigate to the `yc-dmz-with-high-available-ngfw` folder on your PC and connect to a DMZ VM over SSH:

    ```bash
    cd ~/yc-dmz-with-high-available-ngfw
    ssh -i pt_key.pem admin@<VM_internal_IP_address_in_DMZ_segment>
    ```

1. To check whether the DMZ-hosted VM has internet access, run this command:

    ```bash
    ping ya.ru
    ```

    The `ping from dmz to internet` rule should allow the command to run.

1. Make sure the firewall traffic-blocking rules are active.

   To check that `Jump VM` in the `mgmt` segment cannot be accessed from the `dmz` segment, run this command:

   ```bash
   ping 192.168.1.101
   ```

   The `Cleanup rule` should block the command.

### Testing fault tolerance {#fault-tolerance-check}

1. Install `httping` for making HTTP requests on your PC:

    ```bash
    sudo apt-get install httping
    ```

1. To get the load balancer public IP address, run this command in the terminal:

    ```bash
    terraform output fw-alb_public_ip_address
    ```

1. Initiate DMZ application inbound traffic by making a request to the ALB public IP address:

    ```bash
    httping http://<ALB_load_balancer_public_IP_address>
    ```

1. Open another terminal window and connect to a DMZ VM over SSH:

    ```bash
    ssh -i pt_key.pem admin@<VM_internal_IP_address_in_DMZ_segment>
    ```

1. Set a password for the `admin` user:

    ```bash
    sudo passwd admin
    ```

1. In the Yandex Cloud [management console](https://console.yandex.cloud), change the settings of this VM:

    1. Navigate to **Compute Cloud**.
    1. In the left-hand panel, select ![image](../../_assets/console-icons/server.svg) **Virtual machines**.
    1. Click ![ellipsis](../../_assets/console-icons/ellipsis.svg) next to the VM you need and select ![pencil](../../_assets/console-icons/pencil.svg) **Edit**.
    1. In the window that opens, under **Additional**, enable **Serial console access**.
    1. Click **Save changes**.

1. Connect to the VM serial console, enter the `admin` username and password you set earlier.

1. Initiate outbound traffic from the DMZ VM to an internet resource by running `ping`:

    ```bash
    ping ya.ru
    ```

1. Emulate the main firewall failure by [stopping](../../compute/operations/vm-control/vm-stop-and-start.md#stop) the `FW-A` VM in the `mgmt` folder of the Yandex Cloud [management console](https://console.yandex.cloud).
1. Monitor the loss of `httping` and `ping` packets. After FW-A fails, you may experience traffic loss for about one minute, then traffic should resume.
1. Make sure the `dmz-rt` route table in the `dmz` folder uses the `FW-B` address as `next hop`.
1. Emulate the main firewall recovery by [running](../../compute/operations/vm-control/vm-stop-and-start.md#start) the `FW-A` VM in the Yandex Cloud [management console](https://console.yandex.cloud).
1. Monitor the loss of `httping` and `ping` packets. After FW-A recovers, you may experience traffic loss for about one minute, then traffic should resume.
1. Make sure the `dmz-rt` route table in the `dmz` folder uses the `FW-A` address as `next hop`.

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

To stop paying for the resources you created, run this command:

  ```bash
  terraform destroy
  ```
  Terraform will **permanently** delete all resources, such as networks, subnets, VMs, load balancers, folders, etc.

You can delete the resources faster by deleting all folders in the Yandex Cloud console and then deleting the `terraform.tfstate` file from the `yc-dmz-with-high-available-ngfw` directory on your PC.