<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gergo Vadasz</title>
    <description>The latest articles on DEV Community by Gergo Vadasz (@gergovadasz).</description>
    <link>https://dev.to/gergovadasz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3821728%2Fd5a8abe6-b1bf-406d-870c-9439752e608b.jpg</url>
      <title>DEV Community: Gergo Vadasz</title>
      <link>https://dev.to/gergovadasz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gergovadasz"/>
    <language>en</language>
    <item>
      <title>Connecting Your Hybrid Cloud with GCP Connectivity Center and Router Appliance - with Terraform</title>
      <dc:creator>Gergo Vadasz</dc:creator>
      <pubDate>Mon, 06 Apr 2026 20:28:01 +0000</pubDate>
      <link>https://dev.to/gergovadasz/connecting-your-hybrid-cloud-with-gcp-connectivity-center-and-router-appliance-with-terraform-iop</link>
      <guid>https://dev.to/gergovadasz/connecting-your-hybrid-cloud-with-gcp-connectivity-center-and-router-appliance-with-terraform-iop</guid>
      <description>&lt;p&gt;In hybrid cloud environments, connecting on-premises networks to Google Cloud in a scalable and manageable way is a common challenge. Google Cloud's Network Connectivity Center (NCC) implements a hub-and-spoke model for streamlined network management.&lt;/p&gt;

&lt;p&gt;In this post, I'll walk through deploying two VPCs — one serving as a network hub with a Router Appliance VM, another for testing connectivity with a standard VM instance.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  What is GCP Network Connectivity Center?
&lt;/h2&gt;

&lt;p&gt;Network Connectivity Center (NCC) is Google Cloud's centralized network connectivity management solution. It enables a hub-and-spoke topology, simplifying connections across VPCs, VPNs, interconnects, and SD-WAN gateways in hybrid and multi-cloud settings.&lt;/p&gt;

&lt;p&gt;Key benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduced complexity in peering and route configuration&lt;/li&gt;
&lt;li&gt;Enhanced visibility into hybrid network topology&lt;/li&gt;
&lt;li&gt;Scalable network expansion through spoke attachment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gslfcivlxzqgq21f2zj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gslfcivlxzqgq21f2zj.png" alt="GCP NCC Architecture" width="800" height="617"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The environment consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Connectivity Center hub&lt;/li&gt;
&lt;li&gt;Internal VPC spoke with test VM&lt;/li&gt;
&lt;li&gt;Router appliance VPC&lt;/li&gt;
&lt;li&gt;Router appliance VM attached as spoke&lt;/li&gt;
&lt;li&gt;Cloud Router for BGP route exchange&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Create the Internal VPC
&lt;/h3&gt;

&lt;p&gt;Create an internal VPC with a &lt;code&gt;10.0.0.0/24&lt;/code&gt; subnet and deploy a Linux VM in it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblc7weux6oe572kcxdvl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblc7weux6oe572kcxdvl.png" alt="Internal VPC" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw5v4t0h5fdz1gbageq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw5v4t0h5fdz1gbageq1.png" alt="Internal VM" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Create the Router Appliance VPC
&lt;/h3&gt;

&lt;p&gt;Create a router appliance VPC with a &lt;code&gt;10.1.0.0/24&lt;/code&gt; subnet and deploy a Linux VM that will serve as the router appliance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwyh3f08y0b745tsr5l5v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwyh3f08y0b745tsr5l5v.png" alt="Router Appliance VPC" width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frm05gputrwjw0hfpy8o0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frm05gputrwjw0hfpy8o0.png" alt="Router Appliance VM" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  3. Create the Cloud Router
&lt;/h3&gt;

&lt;p&gt;Create a GCP Cloud Router in the router appliance subnet with AS number 64512.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14wmj40ynssz7x9qzl5q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14wmj40ynssz7x9qzl5q.png" alt="Cloud Router" width="800" height="731"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  4. Create the NCC Hub and Spokes
&lt;/h3&gt;

&lt;p&gt;Create an NCC Hub, then attach two spokes: one VPC spoke (internal VPC) and one Router Appliance spoke.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnxttbwej4pq4phiew7df.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnxttbwej4pq4phiew7df.png" alt="NCC Hub" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffe50mt0cyzriasuvuins.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffe50mt0cyzriasuvuins.png" alt="NCC Spokes" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configure the Router Appliance spoke with BGP using AS number 65001.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj5wv1whbsnc2q96nbl1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj5wv1whbsnc2q96nbl1.png" alt="BGP Configuration" width="800" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  5. Configure the Router Appliance VM
&lt;/h3&gt;

&lt;p&gt;SSH into the Router Appliance VM. Since I want to demonstrate a hybrid connection, we need to simulate routing towards a remote location. In real-life scenarios, this could be a remote data center, branch office, SD-WAN solution, or even another cloud environment.&lt;/p&gt;

&lt;p&gt;Create a loopback interface with a &lt;code&gt;192.168.0.0/24&lt;/code&gt; IP to simulate the remote network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create loopback ip address&lt;/span&gt;
ip addr add 192.168.0.1/24 dev lo

&lt;span class="c"&gt;# Add entry to the route table&lt;/span&gt;
ip route add 192.168.0.0/24 dev lo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gergo@nva-instance:~$ ip a
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet 192.168.0.1/24 scope global lo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  6. Install FRR and Configure BGP
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install FRR&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;frr

&lt;span class="c"&gt;# Enable BGP in FRR&lt;/span&gt;
&lt;span class="nb"&gt;sudo sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bgpd=no/bgpd=yes/'&lt;/span&gt; /etc/frr/daemons

&lt;span class="c"&gt;# Restart FRR to take effect&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart frr

&lt;span class="c"&gt;# Configure BGP&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;vtysh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'conf t'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'route-map ACCEPT-ALL permit 10'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'exit'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'router bgp 65001'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.4 remote-as 64512'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.4 description "GCP Peer 1"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.4 ebgp-multihop'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.4 disable-connected-check'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.5 remote-as 64512'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.5 description "GCP 2"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.5 ebgp-multihop'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.5 disable-connected-check'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'address-family ipv4 unicast'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'network 192.168.0.0/24'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.4 soft-reconfiguration inbound'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.4 route-map ACCEPT-ALL in'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.4 route-map ACCEPT-ALL out'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.5 soft-reconfiguration inbound'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.5 route-map ACCEPT-ALL in'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'neighbor 10.1.0.5 route-map ACCEPT-ALL out'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'end'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'write'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying Route Exchange
&lt;/h2&gt;

&lt;p&gt;After configuration, BGP neighborship with Cloud Router should be established:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nva-instance# show ip bgp summary

IPv4 Unicast Summary:
BGP router identifier 192.168.0.1, local AS number 65001 VRF default vrf-id 0
BGP table version 2
RIB entries 3, using 384 bytes of memory
Peers 2, using 47 KiB of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
10.1.0.4        4      64512       101       104        2    0    0 00:32:29            1        2 "GCP Cloud Router
10.1.0.5        4      64512       101       104        2    0    0 00:32:29            1        2 "GCP Cloud Router
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The BGP table shows the internal VPC subnet learned from Cloud Router, and the &lt;code&gt;192.168.0.0/24&lt;/code&gt; loopback advertised locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nva-instance# show ip bgp
BGP table version is 2, local router ID is 192.168.0.1, vrf id 0

     Network          Next Hop            Metric LocPrf Weight Path
 *&amp;gt;  10.1.0.0/24      10.1.0.1               100             0 64512 ?
 *=                   10.1.0.1               100             0 64512 ?
 *&amp;gt;  192.168.0.0/24   0.0.0.0                  0         32768 i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Route Tables in Google Cloud Console
&lt;/h3&gt;

&lt;p&gt;The Router Appliance VPC routing table shows the NCC Hub advertising the internal VPC, and the Router Appliance advertising &lt;code&gt;192.168.0.0/24&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7oktzh31dhk7300ouie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7oktzh31dhk7300ouie.png" alt="Router Appliance VPC routes" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Internal VPC routing table shows &lt;code&gt;192.168.0.0/24&lt;/code&gt; being advertised with next hop as NCC Hub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14ydirpbshu81p2lbw03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14ydirpbshu81p2lbw03.png" alt="Internal VPC routes" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Connectivity Test
&lt;/h3&gt;

&lt;p&gt;With firewall rules permitting traffic, connectivity testing succeeds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gergo@internal-vm:~$ ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=0.823 ms
64 bytes from 192.168.0.1: icmp_seq=2 ttl=64 time=0.336 ms
64 bytes from 192.168.0.1: icmp_seq=3 ttl=64 time=0.268 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;NCC is a powerful tool that can simplify networking setup and operation in Google Cloud. From here, you could expand the demo with additional VPCs, more Cloud Routers, or failover scenario testing.&lt;/p&gt;

&lt;p&gt;The complete Terraform code provisions everything automatically — NCC hub, spokes, Router Appliance, Cloud Router, VMs, and even the BGP routing. No manual steps required in the Google Cloud Console.&lt;/p&gt;

&lt;p&gt;Check out the full Terraform code and guide at &lt;a href="https://gergovadasz.hu/connecting-your-hybrid-cloud-with-gcp-connectivity-center-and-router-appliance-with-terraform/?utm_source=devto&amp;amp;utm_medium=crosspost" rel="noopener noreferrer"&gt;gergovadasz.hu&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://gergovadasz.hu" rel="noopener noreferrer"&gt;gergovadasz.hu&lt;/a&gt;. I write hands-on cloud networking guides with production-ready Terraform code for AWS, Azure, and GCP. &lt;a href="https://gergovadasz.hu/#/portal/signup?utm_source=devto&amp;amp;utm_medium=crosspost" rel="noopener noreferrer"&gt;Subscribe for more&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gcp</category>
      <category>terraform</category>
      <category>bgp</category>
      <category>networking</category>
    </item>
    <item>
      <title>Hybrid DNS with GCP Network Connectivity Center and Enterprise IPAM</title>
      <dc:creator>Gergo Vadasz</dc:creator>
      <pubDate>Sat, 04 Apr 2026 19:29:34 +0000</pubDate>
      <link>https://dev.to/gergovadasz/hybrid-dns-with-gcp-network-connectivity-center-and-enterprise-ipam-3g3e</link>
      <guid>https://dev.to/gergovadasz/hybrid-dns-with-gcp-network-connectivity-center-and-enterprise-ipam-3g3e</guid>
      <description>&lt;p&gt;I recently worked through a hybrid DNS design for a Google Cloud environment with some interesting constraints that I think are worth writing up.&lt;/p&gt;

&lt;p&gt;The setup involved implementing a company-wide on-premises DNS system built on enterprise IPAM platforms (Infoblox, EfficientIP, or BlueCat) with two critical requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Security policies prohibit DNS queries originating from Google's public IP ranges&lt;/li&gt;
&lt;li&gt;The IPAM must remain the authoritative source for all DNS records, including GCP-hosted zones&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The solution involved deploying virtual machines within GCP to bridge these constraints.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  How DNS Works in Google Cloud
&lt;/h2&gt;

&lt;p&gt;By default, Compute Engine instances use the VPC-internal DNS resolver at &lt;code&gt;169.254.169.254&lt;/code&gt;, handled by Cloud DNS based on the VPC network configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud DNS Zone Types
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Private zones:&lt;/strong&gt; Cloud DNS hosts records directly and is authoritative&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forwarding zones:&lt;/strong&gt; Cloud DNS forwards queries to target name servers; with private routing, source IPs originate from &lt;code&gt;35.199.192.0/19&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Peering zones:&lt;/strong&gt; Cloud DNS delegates resolution to another VPC network's DNS context via metadata-plane operations (no actual DNS packets exchanged between VPCs)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The 35.199.192.0/19 Source IP Challenge
&lt;/h3&gt;

&lt;p&gt;Cloud DNS forwarding zones support standard and private routing modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Standard forwarding:&lt;/strong&gt; Source IP depends on target (public IPs use Google ranges; RFC 1918 addresses use &lt;code&gt;35.199.192.0/19&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private forwarding:&lt;/strong&gt; Forces all queries through the VPC network using &lt;code&gt;35.199.192.0/19&lt;/code&gt;, regardless of target IP type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Critical characteristics of this range:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Google Cloud automatically installs a non-removable route for &lt;code&gt;35.199.192.0/19&lt;/code&gt; in every VPC network. This route is not visible in route tables and cannot be modified or exchanged between VPCs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Enterprise firewalls typically block this range as it appears to be from a public IP range.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Solution Is Necessary
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem 1:&lt;/strong&gt; On-premises firewalls reject Cloud DNS forwarding queries arriving from &lt;code&gt;35.199.192.0/19&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem 2:&lt;/strong&gt; Organizations require IPAM platforms to remain the single authoritative source for all DNS records across hybrid environments&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Deploy an IPAM grid member (simulated as a BIND VM) within GCP that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is authoritative for GCP zones (e.g., &lt;code&gt;gcp.example.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Forwards on-premises zone queries to on-prem DNS servers using its private IP&lt;/li&gt;
&lt;li&gt;Receives all GCP workload DNS queries via Cloud DNS forwarding&lt;/li&gt;
&lt;li&gt;Receives GCP zone queries from on-premises via conditional forwarding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Network Topology
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3c3duyyg0a9rmmkls08.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3c3duyyg0a9rmmkls08.png" alt="GCP Cloud DNS Topology" width="800" height="904"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  NCC Hub-and-Spoke Setup
&lt;/h3&gt;

&lt;p&gt;The design uses three VPC networks connected through Google Cloud's Network Connectivity Center:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infra VPC Spoke:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosts the DNS VM (IPAM grid member)&lt;/li&gt;
&lt;li&gt;Hosts the SD-WAN VM&lt;/li&gt;
&lt;li&gt;Central VPC where DNS forwarding zones reside&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;App VPC Spoke:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosts application workloads&lt;/li&gt;
&lt;li&gt;VMs query DNS through Cloud DNS, which peers to Infra VPC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;SD-WAN Router Appliance Spoke:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The SD-WAN VM (physically in Infra VPC) registered as a router appliance in NCC&lt;/li&gt;
&lt;li&gt;Runs FRR (Free Range Routing)&lt;/li&gt;
&lt;li&gt;Peers BGP with NCC Cloud Router (ASN 64515 ↔ 64514)&lt;/li&gt;
&lt;li&gt;Advertises on-premises subnet &lt;code&gt;192.168.1.0/24&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The SD-WAN VM includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NIC0 in Infra VPC (for BGP peering with NCC)&lt;/li&gt;
&lt;li&gt;NIC1 in On-Prem VPC (simulating WAN link to data center)&lt;/li&gt;
&lt;li&gt;IP forwarding enabled for inter-network routing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NCC route exchange ensures all VPCs learn about each other's subnets, enabling the App VPC to reach on-premises resources via the SD-WAN VM.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud DNS Peering and Forwarding Configuration
&lt;/h3&gt;

&lt;p&gt;Cloud DNS includes four managed zones with no private authoritative zones:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Peering Zones (in App VPC):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Zone&lt;/th&gt;
&lt;th&gt;DNS Name&lt;/th&gt;
&lt;th&gt;From&lt;/th&gt;
&lt;th&gt;To&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;gcp-dns-peering&lt;/td&gt;
&lt;td&gt;gcp.example.com&lt;/td&gt;
&lt;td&gt;App VPC&lt;/td&gt;
&lt;td&gt;Infra VPC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onprem-dns-peering&lt;/td&gt;
&lt;td&gt;on-prem.example.com&lt;/td&gt;
&lt;td&gt;App VPC&lt;/td&gt;
&lt;td&gt;Infra VPC&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Forwarding Zones (in Infra VPC):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Zone&lt;/th&gt;
&lt;th&gt;DNS Name&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;gcp-dns-forwarding&lt;/td&gt;
&lt;td&gt;gcp.example.com&lt;/td&gt;
&lt;td&gt;DNS VM (10.0.1.10)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onprem-dns-forwarding&lt;/td&gt;
&lt;td&gt;on-prem.example.com&lt;/td&gt;
&lt;td&gt;DNS VM (10.0.1.10)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both forwarding zones use &lt;code&gt;forwarding_path = "private"&lt;/code&gt; to ensure VPC routing rather than internet routing.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Why Peering Instead of Cross-VPC Forwarding?
&lt;/h3&gt;

&lt;p&gt;Cloud DNS forwarding cannot work across VPCs because of the &lt;code&gt;35.199.192.0/19&lt;/code&gt; return path behavior.&lt;/p&gt;

&lt;p&gt;When Cloud DNS uses a forwarding zone with private routing, queries originate from &lt;code&gt;35.199.192.0/19&lt;/code&gt;. Every VPC contains a special, non-removable route for this range pointing to that VPC's own Cloud DNS context. This route is not exchanged between VPCs through any mechanism (NCC, VPC peering, etc.).&lt;/p&gt;

&lt;p&gt;If the App VPC forwards a query to the DNS VM in the Infra VPC:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The query arrives with a source IP from &lt;code&gt;35.199.192.0/19&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The DNS VM responds to that source IP&lt;/li&gt;
&lt;li&gt;The Infra VPC's special route for &lt;code&gt;35.199.192.0/19&lt;/code&gt; points to its own Cloud DNS, not back to the App VPC&lt;/li&gt;
&lt;li&gt;The response is silently dropped&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;DNS peering solves this entirely by evaluating queries in the target VPC's DNS context without sending packets between VPCs, eliminating cross-VPC return path issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referenced Documentation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/vpc/docs/routes#cloud-dns" rel="noopener noreferrer"&gt;VPC Routes - Cloud DNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/dns/docs/zones/forwarding-zones" rel="noopener noreferrer"&gt;DNS Forwarding Zones&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Traffic Flows
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Flow 1: GCP Workload Resolves a GCP Hostname
&lt;/h3&gt;

&lt;p&gt;Query: &lt;code&gt;app-server.gcp.example.com&lt;/code&gt; from App VM (10.0.2.10)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App VM (10.0.2.10)
  ↓ dig app-server.gcp.example.com
Cloud DNS (169.254.169.254) -- App VPC context
  ↓ Peering zone: gcp.example.com → Infra VPC (metadata-plane)
Cloud DNS -- Infra VPC context
  ↓ Forwarding zone: gcp.example.com → 10.0.1.10, Source: 35.199.192.0/19
DNS VM / IPAM (10.0.1.10)
  ↓ Authoritative zone: gcp.example.com
  ↓ app-server = 10.0.2.10
Response: 10.0.2.10
  ↓ Returns to 35.199.192.0/19 (Infra VPC route, correct context)
Cloud DNS returns answer to App VM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The query remains within GCP, with Cloud DNS peering then forwarding to the DNS VM.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Flow 2: GCP Workload Resolves an On-Premises Hostname
&lt;/h3&gt;

&lt;p&gt;Query: &lt;code&gt;app1.on-prem.example.com&lt;/code&gt; from App VM (10.0.2.10)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App VM (10.0.2.10)
  ↓ dig app1.on-prem.example.com
Cloud DNS (169.254.169.254) -- App VPC context
  ↓ Peering zone: on-prem.example.com → Infra VPC
Cloud DNS -- Infra VPC context
  ↓ Forwarding zone: on-prem.example.com → 10.0.1.10, Source: 35.199.192.0/19
DNS VM / IPAM (10.0.1.10)
  ↓ Forward zone: on-prem.example.com → 192.168.1.10
  ↓ Source IP: 10.0.1.10 (private IP, on-prem firewall allows)
  ↓ Path: via SD-WAN VM (NCC router appliance, BGP-learned route)
On-Prem DNS (192.168.1.10)
  ↓ Authoritative zone: on-prem.example.com
  ↓ app1 = 192.168.1.50
Response travels back the same path
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The on-premises DNS server sees the query from &lt;code&gt;10.0.1.10&lt;/code&gt;, a private RFC1918 address, never from &lt;code&gt;35.199.192.0/19&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Flow 3: On-Premises Resolves a GCP Hostname
&lt;/h3&gt;

&lt;p&gt;Query: &lt;code&gt;app-server.gcp.example.com&lt;/code&gt; from on-premises client&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;On-Prem Client
  ↓ dig app-server.gcp.example.com
On-Prem DNS (192.168.1.10)
  ↓ Conditional forwarder: gcp.example.com → 10.0.1.10
  ↓ Path: via SD-WAN VM (static route in on-prem VPC)
DNS VM / IPAM (10.0.1.10)
  ↓ Authoritative zone: gcp.example.com
  ↓ app-server = 10.0.2.10
Response: 10.0.2.10
  ↓ Returns to on-prem DNS via SD-WAN VM
On-prem client receives answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The DNS VM resolves this locally as it is authoritative for &lt;code&gt;gcp.example.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Traffic Flow Summary
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;From&lt;/th&gt;
&lt;th&gt;To&lt;/th&gt;
&lt;th&gt;Zone&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;App VM&lt;/td&gt;
&lt;td&gt;GCP hostname&lt;/td&gt;
&lt;td&gt;gcp.example.com&lt;/td&gt;
&lt;td&gt;Cloud DNS peer → forward → DNS VM (authoritative)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App VM&lt;/td&gt;
&lt;td&gt;On-prem hostname&lt;/td&gt;
&lt;td&gt;on-prem.example.com&lt;/td&gt;
&lt;td&gt;Cloud DNS peer → forward → DNS VM → on-prem DNS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;On-prem&lt;/td&gt;
&lt;td&gt;GCP hostname&lt;/td&gt;
&lt;td&gt;gcp.example.com&lt;/td&gt;
&lt;td&gt;On-prem DNS → DNS VM (authoritative)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;On-prem&lt;/td&gt;
&lt;td&gt;On-prem hostname&lt;/td&gt;
&lt;td&gt;on-prem.example.com&lt;/td&gt;
&lt;td&gt;On-prem DNS (authoritative, local)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Key Design Decisions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Cloud DNS private zones:&lt;/strong&gt; The IPAM remains the single authoritative source; Cloud DNS only peers and forwards&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS peering is mandatory for cross-VPC resolution:&lt;/strong&gt; The &lt;code&gt;35.199.192.0/19&lt;/code&gt; return path constraint makes forwarding zones across VPCs non-functional&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS VM uses private IP for on-premises queries:&lt;/strong&gt; Queries originate from &lt;code&gt;10.0.1.10&lt;/code&gt; rather than &lt;code&gt;35.199.192.0/19&lt;/code&gt;, allowing enterprise firewalls to accept them into trusted zones&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NCC provides hybrid routing:&lt;/strong&gt; The SD-WAN VM advertises on-premises routes via BGP to NCC, which propagates them to all spoke VPCs&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;The complete Terraform code for this setup is available on my blog — it provisions the entire environment including the NCC hub, DNS VM with BIND, SD-WAN VM with FRR, and all Cloud DNS zones. A single &lt;code&gt;terraform apply&lt;/code&gt; gets you a working lab.&lt;/p&gt;

&lt;p&gt;Check it out at &lt;a href="https://gergovadasz.hu/hybrid-dns-with-gcp-network-connectivity-center-and-enterprise-ipam/" rel="noopener noreferrer"&gt;gergovadasz.hu&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://gergovadasz.hu" rel="noopener noreferrer"&gt;gergovadasz.hu&lt;/a&gt;. I write hands-on cloud networking guides with production-ready Terraform code for AWS, Azure, and GCP. &lt;a href="https://gergovadasz.hu/#/portal/signup" rel="noopener noreferrer"&gt;Subscribe for more&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gcp</category>
      <category>terraform</category>
      <category>dns</category>
      <category>networking</category>
    </item>
  </channel>
</rss>
