Stay organized with collections
Save and categorize content based on your preferences.
This page describes how to add a VPN tunnel from one VPN gateway to another.
A VPN tunnel is an encrypted IPsec tunnel between an organization network and a remote network. It connects a VPNGateway interface to a PeerGateway interface, and uses VPNBGPPeer resource to exchange routing information over the tunnel.
Before you begin
To create a VPN tunnel, you must have the following:
MANAGEMENT_API_SERVER: the zonal API
server's kubeconfig path. If you have not yet generated a kubeconfig file
for the API server in your targeted zone, see
Sign in for details.
VPN_TUNNEL_NAME: the name of the VPN tunnel being used.
VPN_GW_NAME: the name of the VPN gateway.
VPN_INTERFACE_NAME: the name of the VPN interface.
PEER_GW_NAME: the name of the peer VPN gateway.
PEER_INTERFACE_NAME: the name of the peer VPN gateway interface.
VPN_BGP_PEER_NAME: the name of the VPN BGP peer. For more
information, see
Create a VPN BGP session.
The VPNGateway, PeerGateway, and VPNBGPPeer objects must have updated statuses after being referenced by a VPNTunnel. For example, if you verify that the VPNBGPPeer was correctly reconciled, you see updated status values. Get the details of the VPNBGPPeer object:
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-29 UTC."],[[["\u003cp\u003eThis guide details the process of establishing an encrypted IPsec VPN tunnel between two VPN gateways, connecting a \u003ccode\u003eVPNGateway\u003c/code\u003e to a \u003ccode\u003ePeerGateway\u003c/code\u003e and using \u003ccode\u003eVPNBGPPeer\u003c/code\u003e for routing.\u003c/p\u003e\n"],["\u003cp\u003eBefore creating a VPN tunnel, you must have an existing VPN gateway, VPN peer gateway, VPN BGP peer, and a secret, along with the required VPN Admin or VPN Viewer IAM roles.\u003c/p\u003e\n"],["\u003cp\u003eCreating the VPN tunnel involves creating a \u003ccode\u003eVPNTunnel\u003c/code\u003e object in the platform namespace, referencing the previously created \u003ccode\u003eVPNGateway\u003c/code\u003e, \u003ccode\u003ePeerGateway\u003c/code\u003e, \u003ccode\u003eVPNBGPPeer\u003c/code\u003e, and \u003ccode\u003eSecret\u003c/code\u003e resources.\u003c/p\u003e\n"],["\u003cp\u003eAfter creating the \u003ccode\u003eVPNTunnel\u003c/code\u003e object, verify its status and ensure that the \u003ccode\u003eVPNGateway\u003c/code\u003e, \u003ccode\u003ePeerGateway\u003c/code\u003e, and \u003ccode\u003eVPNBGPPeer\u003c/code\u003e objects have updated statuses, indicating successful tunnel establishment and reconciliation.\u003c/p\u003e\n"]]],[],null,["# Create a VPN tunnel\n\nThis page describes how to add a VPN tunnel from one VPN gateway to another.\n\nA VPN tunnel is an encrypted IPsec tunnel between an organization network and a remote network. It connects a `VPNGateway` interface to a `PeerGateway` interface, and uses `VPNBGPPeer` resource to exchange routing information over the tunnel.\n\nBefore you begin\n----------------\n\nTo create a VPN tunnel, you must have the following:\n\n- An existing VPN gateway and VPN peer gateway resource. For more information, see [Create a VPN gateway and peer gateway](/distributed-cloud/hosted/docs/latest/gdch/platform/pa-user/vpn/configure-the-gateways).\n- An existing VPN BGP peer object. For more information, see [Create a VPN BGP session](/distributed-cloud/hosted/docs/latest/gdch/platform/pa-user/vpn/configure-routing).\n- An existing secret. For more information, see [Create the secret with a PSK](/distributed-cloud/hosted/docs/latest/gdch/platform/pa-user/vpn/create-secret).\n- The necessary identity and access roles:\n\n - VPN Admin: has read and write permissions on all VPN-related resources. Ask your Organization IAM Admin to grant you the VPN Admin (`vpn-admin`) role.\n - VPN Viewer: has read permissions on all VPN-related resources. Ask your Organization IAM Admin to grant you the VPN Viewer (`vpn-viewer`) role.\n - For more information, see [Role definitions](/distributed-cloud/hosted/docs/latest/gdch/platform/pa-user/iam/role-definitions).\n\nCreate a VPN tunnel\n-------------------\n\nReference the `VPNGateway`, `PeerGateway`, `VPNBGPPeer`, and `Secret` resources\ncreated in the previous steps to create the tunnel.\n\nTo create a VPN tunnel, follow these steps:\n\n1. Create the `VPNTunnel` object:\n\n **Note:** The `VPNTunnel` object must be created in the platform namespace. \n\n kubectl --kubeconfig \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER\u003c/var\u003e create -n platform -f - \u003c\u003cEOF\n apiVersion: networking.gdc.goog/v1\n kind: VPNTunnel\n metadata:\n name: \u003cvar translate=\"no\"\u003eVPN_TUNNEL_NAME\u003c/var\u003e\n spec:\n vpnInterface:\n name: \u003cvar translate=\"no\"\u003eVPN_GW_NAME\u003c/var\u003e\n namespace: platform\n interface: \u003cvar translate=\"no\"\u003eVPN_INTERFACE_NAME\u003c/var\u003e\n peerInterface:\n name: \u003cvar translate=\"no\"\u003ePEER_GW_NAME\u003c/var\u003e\n namespace: platform\n interface: \u003cvar translate=\"no\"\u003ePEER_INTERFACE_NAME\u003c/var\u003e\n vpnBGPPeer:\n name: \u003cvar translate=\"no\"\u003eVPN_BGP_PEER_NAME\u003c/var\u003e\n namespace: platform\n ikeKey:\n name: \u003cvar translate=\"no\"\u003ePSK_NAME\u003c/var\u003e\n namespace: platform\n EOF\n\n Replace the following:\n - \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER\u003c/var\u003e: the zonal API server's kubeconfig path. If you have not yet generated a kubeconfig file for the API server in your targeted zone, see [Sign in](/distributed-cloud/hosted/docs/latest/gdch/platform/pa-user/iam/sign-in#cli) for details.\n - \u003cvar translate=\"no\"\u003eVPN_TUNNEL_NAME\u003c/var\u003e: the name of the VPN tunnel being used.\n - \u003cvar translate=\"no\"\u003eVPN_GW_NAME\u003c/var\u003e: the name of the VPN gateway.\n - \u003cvar translate=\"no\"\u003eVPN_INTERFACE_NAME\u003c/var\u003e: the name of the VPN interface.\n - \u003cvar translate=\"no\"\u003ePEER_GW_NAME\u003c/var\u003e: the name of the peer VPN gateway.\n - \u003cvar translate=\"no\"\u003ePEER_INTERFACE_NAME\u003c/var\u003e: the name of the peer VPN gateway interface.\n - \u003cvar translate=\"no\"\u003eVPN_BGP_PEER_NAME\u003c/var\u003e: the name of the VPN BGP peer. For more information, see [Create a VPN BGP session](/distributed-cloud/hosted/docs/latest/gdch/platform/pa-user/vpn/configure-routing#create-vpn-bgp-session).\n - \u003cvar translate=\"no\"\u003ePSK_NAME\u003c/var\u003e: the name of the PSK you created in [Create the secret with a PSK](/distributed-cloud/hosted/docs/latest/gdch/platform/pa-user/vpn/create-secret).\n2. Verify that the \u003cvar translate=\"no\"\u003eVPN_TUNNEL_NAME\u003c/var\u003e object was correctly reconciled by examining the `Status` field. Get the details of the VPN tunnel:\n\n kubectl --kubeconfig \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER\u003c/var\u003e describe -n platform vpntunnel \u003cvar translate=\"no\"\u003eVPN_TUNNEL_NAME\u003c/var\u003e\n\n Examine the output, it must look similar to the following example: \n\n Status:\n Conditions:\n Last Transition Time: 2024-05-10T00:33:31Z\n Message: Ready\n Observed Generation: 1\n Reason: Ready\n Status: True\n Type: Reconciled\n Last Transition Time: 2024-05-10T00:33:31Z\n Message: Ready\n Observed Generation: 1\n Reason: Ready\n Status: True\n Type: Ready\n Last Transition Time: 2024-05-10T00:33:31Z\n Message: Tunnel is established.\n Observed Generation: 1\n Reason: Ready\n Status: True\n Type: TunnelEstablished\n State: Established\n\n3. The `VPNGateway`, `PeerGateway`, and `VPNBGPPeer` objects must have updated statuses after being referenced by a `VPNTunnel`. For example, if you verify that the `VPNBGPPeer` was correctly reconciled, you see updated status values. Get the details of the `VPNBGPPeer` object:\n\n kubectl --kubeconfig \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER\u003c/var\u003e describe -n platform vpnbgppeer \u003cvar translate=\"no\"\u003eVPN_BGP_PEER_NAME\u003c/var\u003e\n\n Examine the output, the status values are now updated: \n\n Status:\n Advertised:\n Prefix: 10.0.0.16/28\n Prefix: 10.0.1.32/27\n Prefix: 172.16.0.0/14\n Prefix: 172.20.0.0/17\n Prefix: 172.20.128.0/17\n Prefix: 2002:4860:100e:fa00::/58\n Conditions:\n Last Transition Time: 2024-05-10T00:36:38Z\n Message: Ready\n Observed Generation: 1\n Reason: Ready\n Status: True\n Type: ValidIPs\n Last Transition Time: 2024-05-10T00:36:38Z\n Message: Ready\n Observed Generation: 1\n Reason: Ready\n Status: True\n Type: TunnelsAttached\n Last Transition Time: 2024-05-10T00:36:38Z\n Message: Ready\n Observed Generation: 1\n Reason: Ready\n Status: True\n Type: Reconciled\n Last Transition Time: 2024-05-10T00:36:38Z\n Message: Ready\n Observed Generation: 1\n Reason: Ready\n Status: True\n Type: AdvertisedRoutesReady\n Last Transition Time: 2024-05-10T00:36:38Z\n Message: Ready\n Observed Generation: 1\n Reason: Ready\n Status: True\n Type: ReceivedRoutesValid\n Last Transition Time: 2024-05-10T00:36:38Z\n Message: Ready\n Observed Generation: 1\n Reason: Ready\n Status: True\n Type: ReceivedRoutesReady\n Last Transition Time: 2024-05-10T00:36:38Z\n Message: Ready\n Observed Generation: 1\n Reason: Ready\n Status: True\n Type: Ready\n Received:\n Prefix: 192.168.100.0/24\n Prefix: 193.188.200.0/24\n State: Established\n\nWhat's next\n-----------\n\n- [Control egress and ingress traffic](/distributed-cloud/hosted/docs/latest/gdch/platform/pa-user/vpn/egress-and-ingress)"]]