VPN Site-to-Site between Azure and Google Cloud Platform. Part 1
Published: 2021-10-19 21:18:34

> You can find this story, with more information, on my website [https://blog.truyol.dev/vpn-site-to-site-between-gcp-and-azure/](https://blog.truyol.dev/vpn-site-to-site-between-gcp-and-azure/)

I never had the chance to deploy a VPN Server or configure a Site-to-Site connection. So this was a huge "must" on my professional bucket list.

Luckily I was tasked to perform some tests between Azure and GCP using IPsec IKEv2, and set the ground on how the company will create and protect this kind of connection. The task list was:

- Choose the service with the best cost/feature ratio.
- Create the resources on both ends and establish a connection.
- Test the network
- Limit the connection to specific IP/resources
- Validate that we can deploy multiple VPN connections with different customers.

Without further ado, let's get into it.

## Choosing the service

These secure connections will be needed only for the development and stage of our products. This way we can extract data securely from our client's data sources. That's why we don't need High Availability services on either end.

### Azure

Azure offers 3 types of connections:

- VNet-to-VNet: Simple way to connect VNets in azure. Similar to a Site-to-Site IPsec connection to an on-premises location.
- Site-to-Site (IPsec): Composed by a `VPN Gateway`, a `Local Gateway` and a `Connection`, allows to send encrypted traffic between an Azure's VNet and an on-premises location through the public internet.
- ExpressRoute: Lets us create private connections between Azure datacenters and on-premises infrastructure through the Microsoft private network. Also, have higher bandwidth over a Site-to-Site connection (up to 10Gbps vs <100Mbps)

We will use the Site-to-Site VPN this time.

### Google Cloud Platform

GCP offers 3 types of connections:

- Cloud VPN: This service has 2 subtypes:
  - HA VPN: This is a High Availability Cloud VPN that lets us securely connect on-premises networks to our private networks on GCP through an IPsec VPN connection.
  - Classic VPN: In contrast to HA VPN, Classic VPN have a single interface and a single external IP address.
- Cloud Interconnect: Provides low latency and high availability connections to reliably transfer data between on-premises and GCP through a supported service provider or Google's network with no public internet dependency.
- Cloud Router: Fully distributed and managed GCP Service that uses Border Gateway Protocol (BGP). Support custom dynamic routes based on the BGP advertisements that it receives from a peer.

In this opportunity, we will use Classic VPN

## Create the resources

Requirements:

- Azure:
  - VNet with address space `10.128.0.0/9`. In this case, it will be on `useast-2`
- GCP:
  - VNet with a subnet with address space `10.125.0.0/20`. In this case it will be `default` VPC with the `vpn-subnet` on `us-east1`

It could be any address space, the most important is that they don't overlap.

### Azure

Let's create a `Virtual Network Gateway` on Azure. This resource will be the public face of our VNet

![Virtual Network Gateway](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6l0ihwigvz5mj921cey0.png)


| Field           | Description                                                                           | Value       |
| --------------- | ------------------------------------------------------------------------------------- | ----------- |
| Name            | Name of the Virtual Network Gateway                                                   | `vpn-test`  |
| Region          | The same as our VNet                                                                  | `East US 2` |
| Gateway Type    | Type of connection to use                                                             | `VPN`       |
| VPN Type        | Type of VPN to use. Route based will allow us to define the address space of this VPN | `VPN`       |
| SKU             | Tier of service to use. `VpnGwX` allows us to use IPsec                               | `VpnGw1`    |
| Virtual Network | The VNet to associate to this VPN                                                     | `test-vnet` |

When everything is created, we can see the public IP `20.97.253.157` on the Overview page of the resource.

Now, let's jump to GCP

### GCP

Now that we have the public IP and the address space on the Azure side, we will create the Classic Cloud VPN resource
![Cloud VPN](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hgtxqy2fd8wl0dhaa3mt.png)
![Cloud VPN Basic Data](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uvu3inkz9nv3uki7xr57.png)
![Cloud VPN Tunnel Data](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uekq5jduaia6tmo302jp.png)

**Cloud VPN**  

| Field | Description | Value |
| ------------------------ | ---------------------------------------------- | ------------------- |
| Name | Name of the Cloud VPN resource | `vpn-test` |
| Network | GCP Network to link with this VPN | `default` |
| Region | GCP Region where our subnet is located | `us-east1` |
| IP address | New IP address request for this VPN | `vpn-test-ip` |

**Tunnel**  

| Field                    | Description                                    | Value             |
| ------------------------ | ---------------------------------------------- | ----------------- |
| Name                     | Name of the VPN Tunnel                         | vpn-test-tunnel-1 |
| Remote peer IP Address   | Azure's VPN Gateway public IP                  | 20.97.253.157     |
| IKE version              | Versión de IKE a usar                          | IKEv2             |
| IKE pre-shared key       | Key to encrypt the traffic                     | secret            |
| Routing options          | For simplicity we will use Route-Based routing | Route-Based       |
| Remote network IP ranges | Correspond to the address space on Azure       | 10.128.0.0/9      |


After this resource is created we will copy and save the public IP address `34.138.192.84`

Let's jump back to Azure to finish the VPN configuration

### Azure

Now that we have the Virtual Network Gateway, we will create a Local Network Gateway with the GPC information.

![Local Network Gateway](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g4q6uyv1t3akwsl1o4nh.png)

| Field | Description | Value |
| - | - | - |
| IP address    | Public IP of the GCP gateway         | `34.138.192.84` |
| Address space | Address space on GCP to connect with | `10.125.0.0/20` |

We are almost there! Now we need to create the Connection using the Virtual Network Gateway and the Local Network Gateway previously created.

![Local Network Gateway](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qggoktofk410ncd6q4xm.png)

![Local Network Gateway](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u6lnap3bvzrq0vizcvg1.png)

| Field                   | Description                                                  | Value                |
| ----------------------- | ------------------------------------------------------------ | -------------------- |
| Connection Type         | VPN Connection type                                          | `Site-to-Site IPsec` |
| Virtual network gateway | Virtual network previously created. The image is out-of-date | `vpn-test `          |
| Local network gateway   | Local Network Gateway previously created                     | `vpn-test-lng`       |
| Shared key (PSK)        | Secret key used in the GCP VPN                               | `secret`             |
| IKE Protocol            | The same as the GCP VPN                                      | `IKEv2`              |

## Verification

Finally, we have our VPN Site-to-Site completely created. We can verify this by checking the connection status on each side. In Azure, it should show `Status: Connected` on the Connection resource. In GCP it should show `Status: Tunnel is up and running` with a green check on the VPN Tunnel.

In the next part, we will verify that any virtual machine can reach the other side of the VPN using the private IPs.