[Yandex Cloud documentation](../../index.md) > [Yandex Compute Cloud](../index.md) > [Tutorials](index.md) > Configuring a secure GRE tunnel over IPsec

# Configuring a secure GRE tunnel over IPsec


For secure communication between remote resources and data transmission over public communication channels, e.g., the internet, you can use secure connection technologies, such as the [IPsec](https://www.ietf.org/rfc/rfc2401.txt) protocol. However, IPsec has significant limitations: it is only designed for IP packet transmission, does not support [multicast delivery](https://en.wikipedia.org/wiki/IP_multicast), and cannot be combined with other protocols within a single request.

IPsec can be boosted using the [GRE](https://en.wikipedia.org/wiki/Generic_Routing_Encapsulation) protocol configured as GRE over IPsec. GRE encapsulates network packets in IP packets, enabling you to transmit any traffic over IPsec.

In this example, you will create a secure GRE-over-IPsec tunnel between two [Cisco CSR 1000v](https://yandex.cloud/en/marketplace/products/yc/cisco-csr) virtual routers hosted in different [virtual networks](../../vpc/concepts/network.md) and [availability zones](../../overview/concepts/geo-scope.md) in Yandex Cloud. 

You will configure IPsec in NAT-T ([NAT Traversal](https://en.wikipedia.org/wiki/Network_address_translation)) mode, since Yandex Cloud employs [NAT](https://en.wikipedia.org/wiki/Network_address_translation), while GRE does not support using ports. This mode enables the translation of router IP addresses over NAT when using a GRE-over-IPsec tunnel. This makes the tunnel configuration in our example suitable for both the Yandex Cloud infrastructure and remote resources placed behind the device that provides NAT. 

To set up a secure tunnel between two virtual routers:

1. [Get your cloud ready](#before-you-begin).
1. [Create an SSH key pair](#create-ssh-keys).
1. [Create folders](#create-folders).
1. [Create two VMs with a Cisco Cloud Services Router](#create-routers).
1. [Configure IPSec protocols](#ipsec-setup).
1. [Create tunnel interfaces](#create-interfaces).
1. [Configure routing](#setup-routers).
1. [Test the tunnel](#check-tunnel).

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

## Getting started {#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).

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

{% note alert %}

When using a Cisco CSR 1000v image without a license, the router throughput is limited to 100 Kbps. To remove this limitation, [install a license](https://www.cisco.com/c/en/us/td/docs/routers/csr1000/software/configuration/b_CSR1000v_Configuration_Guide/b_CSR1000v_Configuration_Guide_chapter_01000.html).

{% endnote %}

The infrastructure support costs include:

* Fee for disks and continuously running VMs (see [Yandex Compute Cloud pricing](../pricing.md)).
* Fee for using an external IP address (see [Yandex Virtual Private Cloud pricing](../../vpc/pricing.md#prices-public-ip)).

## Create an SSH key pair {#create-ssh-keys}

To connect to a [VM](../concepts/vm.md) over SSH, you need a key pair: the public key resides on the VM, and the private one is kept by the user. This method is more secure than connecting with login and password.

{% note info %}

SSH connections using a login and password are disabled by default on public Linux images that are provided by Yandex Cloud.

{% endnote %}

Cisco Cloud Services Router (CSR) 1000v only supports keys generated using the RSA algorithm.

To create a key pair:

{% list tabs group=operating_system %}

- Linux/macOS {#linux-macos}

  1. Open the terminal.
  1. Use the `ssh-keygen` command to create a new key:

     ```bash
     ssh-keygen -t rsa -b 2048
     ```

     After you run the command, you will be asked to specify the names of files where the keys will be saved and enter the password for the private key. The default name is `id_rsa`. Keys are created in the `~/.ssh` directory.

     The public part of the key will be saved in the `<key_name>.pub` file.

- Windows 10/11 {#windows}

  1. Run `cmd.exe` or `powershell.exe`.
  1. Use the `ssh-keygen` command to create a new key:

     ```shell
     ssh-keygen -t rsa -b 2048
     ```

     After you run the command, you will be asked to specify the names of files where the keys will be saved and enter the password for the private key. The default name is `id_rsa`. The keys are created in `C:\Users\<username>\.ssh\` or `C:\Users\<username>\` depending on the command-line interface.

     The public part of the key will be saved to a file named `<key name>.pub`.

- Windows 7/8 {#windows7-8}

  Create keys using the PuTTY app:
  1. [Download](https://www.putty.org) and install PuTTY.
  1. Add the folder with PuTTY to the `PATH` variable:

      1. Click **Start** and type **Change system environment variables** in the Windows search bar.
      1. Click **Environment Variables...** at the bottom right.
      1. In the window that opens, find the `PATH` parameter and click **Edit**.
      1. Add your folder path to the list.
      1. Click **OK**.

  1. Launch the PuTTYgen app.
  1. Select **RSA** for the type of pair to generate and set the length to 2048. Click **Generate** and move the cursor in the field above it until key creation is complete.

     ![ssh_generate_key](../../_assets/compute/ssh-putty/ssh-generate-key-rsa.png)

  1. In **Key passphrase**, enter a strong password. Enter it again in the field below.
  1. Click **Save private key** and save the private key. Do not share its key phrase with anyone.
  1. Save the key to a text file. To do this, copy the public key from the text field to a text file named `id_rsa.pub`. Please note that the key must be written as a **single line** (no returns or line breaks).

{% endlist %}

{% note warning %}

Save the private key in a secure location, as you will not be able to connect to the VM without it.

{% endnote %}

## Create folders {#create-folders}

To test tunneling between two different virtual networks, place Yandex Cloud resources in different folders. To create a new folder:

{% list tabs group=instructions %}

- Management console {#console}

   1. In the [management console](https://console.yandex.cloud), select a [cloud](../../resource-manager/concepts/resources-hierarchy.md#cloud) and click ![image](../../_assets/console-icons/ellipsis.svg) → ![image](../../_assets/console-icons/plus.svg) **Create folder** at the top right.
   1. Enter the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) name: `site-d`.
   1. Add a folder description if required.
   1. Select **Create a default network**. 
   1. Click **Create**.

- CLI {#cli}

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

   Create a folder:
   ```bash
   yc resource-manager folder create \
   --name site-d \
   --description "Folder for site-d"
   ```

- API {#api}

   To create a folder, use the [create](../../resource-manager/api-ref/Folder/create.md) REST API method for the [Folder](../../resource-manager/api-ref/Folder/index.md) resource or the [FolderService/Create](../../resource-manager/api-ref/grpc/Folder/create.md) gRPC API call.

- Terraform {#tf}

   If you do not have Terraform yet, [install it and configure the Yandex Cloud provider](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).
   
   
   To manage infrastructure using Terraform under a service account or user accounts (a Yandex account, a federated account, or a local user), [authenticate](../../terraform/authentication.md) using the appropriate method.

   1. In the configuration file, describe the resources you want to create:

      ```hcl
      resource "yandex_resourcemanager_folder" "folder1" {
         cloud_id    = "<cloud_ID>"
         name        = "site-d"
         description = "Folder for site-d"
      }
      ```

      For more information about `yandex_resourcemanager_folder` properties in Terraform, see [this provider guide](../../terraform/resources/resourcemanager_folder.md).

   1. Make sure the configuration files are correct.

      1. In the command line, navigate to the directory where you created the configuration file.

      1. Check the configuration using this command:

         ```
         terraform validate
         ```
     
         If the configuration is valid, you will get this message:
     
         ```
         Success! The configuration is valid.
         ```

      1. Run this command:

         ```
         terraform plan
         ```

         If the configuration is correct, the terminal will display a list of the resources and their settings. Otherwise, Terraform will show any detected errors. 

   1. Deploy the cloud resources.

      1. If the configuration is correct, run this command:

         ```
         terraform apply
         ```

      1. Confirm creating the resources: type `yes` and press **Enter**.

      This will create the folder in the specified cloud. You can check the new folder and its settings using the [management console](https://console.yandex.cloud) or this [CLI](../../cli/quickstart.md) command:

      ```
      yc resource-manager cloud list
      ```

{% endlist %}

Repeat these steps to create a second folder named `site-b`.

## Create two VMs with Cisco Cloud Services Router {#create-routers}

### Create your first VM with Cisco Cloud Services Router {#create-first-vm}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select `site-d`.
  1. Click ![image](../../_assets/console-icons/plus.svg) **Create resource** and select ![image](../../_assets/console-icons/cpu.svg) **Virtual machine instance**.
  1. Under **Boot disk image**, in the **Product search** field, enter `Cisco CSR` and select a [Cisco CSR](https://yandex.cloud/en/marketplace/products/yc/cisco-csr) public image.
  1. Under **Location**, select the `ru-central1-d` [availability zone](../../overview/concepts/geo-scope.md).
  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**:

      * In the **Subnet** field, select the network and subnet to connect your VM to.
      * In the **Public IP address** field, keep `Auto` to assign the VM a random external IP address from the Yandex Cloud pool or select a static address from the list if you reserved one.

  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](../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: `cisco-router-d`.
  1. Under **Additional**, enable `Serial console access`.
  1. Click **Create VM**.

  It may take a few minutes to create your VM. When the VM status changes to `RUNNING`, you can use the serial console.

{% endlist %}

### Set the host name for the router {#hostname}

{% list tabs group=instructions %}

- Management console {#console}
  
   1. In the [management console](https://console.yandex.cloud), select the folder containing your VM.
   1. Navigate to **Compute Cloud**.
   1. In the VM list, select `cisco-router-d`.
   1. Go to the ![image](../../_assets/console-icons/terminal.svg) **Serial console** tab and click **Connect**.
   1. Wait for the operating system to boot.
   1. To switch to privileged mode, run this command in the serial console:

      ```bash
      enable
      ```

   1. Enter configuration mode and set the host name for the router:

      ```bash
      conf t
      hostname cisco-router
      ```

      The router name at the beginning of the command line should change to `cisco-router`.

{% endlist %}

### Create a user with administrator privileges {#create-user}

Create a user with administrator privileges and password authentication disabled:

{% list tabs group=instructions %}

- Management console {#console}

   In the serial console, run this command:

   ```bash
   username test-user privilege 15
   ```

{% endlist %}

### Prepare the key {#split-ssh}

If your public SSH key is longer than 72 characters, split it into chunks of 72 characters each:

1. In your computer terminal, run this command:

   ```bash
   fold -bw 72 <public_key_file_path>
   ```

   This will output your public SSH key split into chunks of 72 characters each.

1. Save the key hash:

   ```bash
   ssh-keygen -E md5 -lf <public_key_file_path>
   ```


### Configure authentication using SSH keys {#enable-ssh}


{% list tabs group=instructions %}

- Management console {#console}

   1. In the serial console, enable VM access over SSH:

      ```bash
      conf t
      aaa new-model
         ip ssh server algorithm authentication publickey 
         ip ssh pubkey-chain
      ```

   1. Create a user named `test-user` and provide your public SSH key in the chunks into which you split it at the previous step:

      ```bash
         username test-user
            key-string
               <public_key_row>
               ...
               <public_key_row>
               exit
            exit
         exit
      exit
      ```

   1. Make sure the key has been added:

      ```bash
      show run | beg ip ssh
      ```
      Result:

      ```bash
      ip ssh pubkey-chain
        username test-user
         key-hash ssh-rsa <key_hash> <username_associated_with_this_key>
      !
      !
      ...
      ```

      Compare the SSH key hash on the router with the key hash on your computer.

   1. In the serial console, enter the password that enables privileged mode:

      ```bash
      cisco-router#configure terminal
      cisco-router(config)#enable secret <password>
      ```

{% endlist %}


### Check the SSH connection to the router {#test-ssh}

1. Log in to the router via SSH by running this command in your computer terminal:

   ```bash
   ssh -i <private_key_file_path> test-user@<router_public_IP_address> 
   ```

   If the configuration is correct, you will log in to the router as `test-user`. If these actions produce no connection, make sure the router configuration is correct in the serial console, i.e., check whether you ran the `aaa new-model` command, the key hashes are identical on your computer and the router, and password authorization is disabled for the test user. If still unable to locate the issue, repeat the previous steps. 
1. Switch to privileged mode. To do this, enter the `enable` command and your password. If the configuration is correct, you can proceed to configuring the router.

### Set up and configure a second VM with a Cisco Cloud Services Router {#create-second-vm}

1. In the `site-b` folder, create a VM named `cisco-router-b` by following the above steps. Select **ru-central1-b** as its availability zone.
1. Set up the VM in the same way as the `cisco-router-d` VM.

## Configure the IPSec protocols {#ipsec-setup}

{% note warning %}

* The settings are the same on both VMs, except as specifically mentioned.
* You will configure the protocols in the terminal connected to the VM over SSH, in privileged mode. 

{% endnote %}

1. Configure the global parameters for [IKEv2](https://ru.wikipedia.org/wiki/IKE):

   ```bash
   conf t
   crypto logging ikev2
   crypto ikev2 nat keepalive 900
   crypto ikev2 dpd 10 2 periodic
   ```

1. Configure an IKEv2 `proposal`:

   ```bash
   crypto ikev2 proposal MY_IKEV2_PROPOSAL
      encryption aes-cbc-256
      integrity sha256
      group 2
      exit
   ```

1. Configure an IKEv2 `policy`:

   ```bash
   crypto ikev2 policy MY_IKEV2_POLICY
      proposal MY_IKEV2_PROPOSAL
      exit
   ```

1. Set a secret key:

   {% list tabs %}

   - Cisco-router-d VM

     ```bash
     crypto ikev2 keyring MY_IKEV2_KEYRING
        peer SiteB
        address cisco-router-b
        pre-shared-key <secret_key>
        exit
     ```

   - Cisco-router-b VM

     ```bash
     crypto ikev2 keyring MY_IKEV2_KEYRING
        peer SiteA
        address cisco-router-d
        pre-shared-key <secret_key>
        exit
     ```

   {% endlist %}

   Where:
   * `<secret_key>`: Encryption key that is at least 16 characters long, e.g., `MySecretKey12345`. Use the same key on both VMs.

1. Create an IKEv2 profile:

   {% list tabs %}

   - Cisco-router-d VM

     ```bash
     crypto ikev2 profile MY_IKEV2_PROFILE
        match address local interface GigabitEthernet1
        match identity remote address cisco-router-b
        authentication remote pre-share
        authentication local pre-share
        keyring local MY_IKEV2_KEYRING
        lifetime 28800
        dpd 20 2 periodic
        exit
     ```

   - Cisco-router-b VM

     ```bash
     crypto ikev2 profile MY_IKEV2_PROFILE
        match address local interface GigabitEthernet1
        match identity remote address cisco-router-d
        authentication remote pre-share
        authentication local pre-share
        keyring local MY_IKEV2_KEYRING
        lifetime 28800
        dpd 20 2 periodic
        exit
     ```

   {% endlist %}

   {% note info %}

   For testing purposes, you can use the `0.0.0.0` template rather than IP addresses to provide access to any IP.
   You can also set up separate profiles for different peers.

   {% endnote %}

1. Add the IKEv2 profile to the IPsec profile:

   ```bash
   crypto ipsec transform-set ESP_AES128_SHA256 esp-aes esp-sha-hmac
      mode tunnel
      exit
   crypto ipsec profile MY_IPSEC_PROFILE
      set transform-set ESP_AES128_SHA256
      set ikev2-profile MY_IKEV2_PROFILE
      exit
   exit
   ```

## Create tunnel interfaces {#create-interfaces}

{% note warning %}

* The settings are the same on both VMs, except as specifically mentioned.
* You will configure the protocols in the terminal connected to the VM over SSH, in privileged mode. 

{% endnote %}

1. Configure the GRE tunnel:

   {% list tabs %}

   - Cisco-router-d VM

     ```bash
     conf t
     int tu192
        ip address 192.168.0.1 255.255.255.0
        no ip redirects
        no ip proxy-arp
        ip mtu 1400
        ip tcp adjust-mss 1360
        tunnel source GigabitEthernet1
        tunnel destination cisco-router-b
        tunnel mode ipsec ipv4
        tunnel protection ipsec profile MY_IPSEC_PROFILE
     ```

   - Cisco-router-b VM

     ```bash
     conf t
     int tu192
        ip address 192.168.0.2 255.255.255.0
        no ip redirects
        no ip proxy-arp
        ip mtu 1400
        ip tcp adjust-mss 1360
        tunnel source GigabitEthernet1
        tunnel destination cisco-router-d
        tunnel mode ipsec ipv4
        tunnel protection ipsec profile MY_IPSEC_PROFILE
     ```

   {% endlist %}

1. Check whether the tunnel is there:

   {% list tabs %}

   - Cisco-router-d VM

     ```bash
     show crypto ikev2 sa remote cisco-router-b
     ```

   - Cisco-router-b VM

     ```bash
     show crypto ikev2 sa remote cisco-router-d
     ```

   {% endlist %}

   Result:

   ```bash
   Tunnel-id Local                 Remote                fvrf/ivrf            Status
   4         10.128.0.32/4500      51.250.***.***/4500   none/none            READY
         Encr: AES-CBC, keysize: 256, PRF: SHA256, Hash: SHA256, DH Grp:2, Auth sign: PSK, Auth verify: PSK
         Life/Active Time: 28800/23528 sec
   ```

   You can also view tunnel logs by running these commands:

   ```bash
   debug crypto ikev2
   conf t
   do sh log
   ```

## Configure routing {#setup-routers}

{% note warning %}

* The settings are the same on both VMs, except as specifically mentioned.
* You will configure the protocols in the terminal connected to the VM over SSH, in privileged mode. 

{% endnote %}

1. To make sure the requests get responses, configure a [Loopback](https://ru.wikipedia.org/wiki/Loopback) interface:

   {% list tabs %}

   - Cisco-router-d VM

     ```bash
     conf t
     int lo10
        ip address 10.1.1.1 255.255.255.255
        exit
     ```

   - Cisco-router-b VM

     ```bash
     conf t
     int lo10
        ip address 10.1.1.2 255.255.255.255
        exit
     ```

   {% endlist %}

1. To enable dynamic routing, configure the Border Gateway Protocol (BGP):

   {% list tabs %}

   - Cisco-router-d VM

     ```bash
     router bgp 65001
        bgp log-neighbor-changes
        neighbor 192.168.0.2 remote-as 65002
        address-family ipv4
           network 10.1.1.1 mask 255.255.255.255
           neighbor 192.168.0.2 activate
           exit
        exit
     exit
     ```

   - Cisco-router-b VM

     ```bash
     router bgp 65002
        bgp log-neighbor-changes
        neighbor 192.168.0.1 remote-as 65001
        address-family ipv4
           network 10.1.1.2 mask 255.255.255.255
           neighbor 192.168.0.1 activate
           exit
        exit
     exit
     ```

   {% endlist %}

## Test the GRE tunnel {#check-tunnel}

Make sure this resulted in sending and returning the packets. To do this, run this command on the `cisco-router-d` VM:

   ```bash
   ping 10.1.1.2 source lo10
   ```

   Result:

   ```bash
   Type escape sequence to abort.
   Sending 5, 100-byte ICMP Echos to 10.1.1.2, timeout is 2 seconds:
   Packet sent with a source address of 10.1.1.1
   !!!!!
   Success rate is 100 percent (5/5), round-trip min/avg/max = 10/10/11 ms
   ```

For GRE tunnel performance diagnostics, you can also run these commands:

   ```bash
   show ip int brief
   show ip bgp summary
   show ip bgp
   show ip route bgp
   ```

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

To stop paying for the resources you created:
* [Delete](../operations/vm-control/vm-delete.md) the VM.
* [Delete](../../vpc/operations/address-delete.md) the static public IP if you reserved one.