{"id":26863768,"url":"https://github.com/mddazure/subnet-peering","last_synced_at":"2025-03-31T03:32:42.888Z","repository":{"id":284563154,"uuid":"955344411","full_name":"mddazure/subnet-peering","owner":"mddazure","description":"Subnet peering connects VNETs by linking specific subnet address spaces rather than the entire VNET address spaces.","archived":false,"fork":false,"pushed_at":"2025-03-26T14:01:32.000Z","size":0,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-26T14:48:42.828Z","etag":null,"topics":["azure","networking","peering","vnet"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mddazure.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-26T13:50:37.000Z","updated_at":"2025-03-26T14:18:51.000Z","dependencies_parsed_at":"2025-03-26T14:48:46.417Z","dependency_job_id":"ffbef466-9e53-436c-b8b7-8af6bd80df07","html_url":"https://github.com/mddazure/subnet-peering","commit_stats":null,"previous_names":["mddazure/subnet-peering"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mddazure%2Fsubnet-peering","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mddazure%2Fsubnet-peering/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mddazure%2Fsubnet-peering/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mddazure%2Fsubnet-peering/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mddazure","download_url":"https://codeload.github.com/mddazure/subnet-peering/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246413364,"owners_count":20773052,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","networking","peering","vnet"],"created_at":"2025-03-31T03:32:42.353Z","updated_at":"2025-03-31T03:32:42.879Z","avatar_url":"https://github.com/mddazure.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Subnet Peering\n\n## The Basics: VNET Peering\n\nVirtual Networks in Azure can be connected thorugh [VNET Peering](https://learn.microsoft.com/en-us/azure/virtual-network/virtual-network-peering-overview). Peered VNETs become one routing domain, meaning that the entire IP space of each VNET is visible to and reachable from the other VNET. This is great for many applications: wire speed connectivity without gateways or other complexities.\n\nIn this diagram, vnet-left and vnet-right are peered: \n\n![images](/images/vnet-peering.png)\n\nThis is what that looks like in the portal for `vnet-left` (with the righthand vnet similar):\n\n![images](/images/full-peering-left.png)\n\nEffective routes of vm's in either vnet show the entire ip space of the peered vnet.\n\nFor vm `left-1` in `vnet-left`:\n\n```\naz network nic show-effective-route-table -g sn-rg -n left-1701 -o table\nSource    State    Address Prefix    Next Hop Type    Next Hop IP\n--------  -------  ----------------  ---------------  -------------\nDefault   Active   10.0.0.0/16       VnetLocal\nDefault   Active   10.1.0.0/16       VNetPeering\nDefault   Active   0.0.0.0/0         Internet\n```\n\nAnd for vm `right-1` in `vnet-right`:\n\n```\naz network nic show-effective-route-table -g sn-rg -n right-159 -o table\nSource    State    Address Prefix    Next Hop Type    Next Hop IP\n--------  -------  ----------------  ---------------  -------------\nDefault   Active   10.1.0.0/16       VnetLocal\nDefault   Active   10.0.0.0/16       VNetPeering\nDefault   Active   0.0.0.0/0         Internet\n```\n\n## The Problem\nThere are situations where completely merging the address spaces of VNETs is not desirable. \n\nThink of micro-segmentation: only the front-end of a multi-tier application must be exposed and accessible from outside the VNET, with the application- and database tiers ideally remaining isolated. Network Security Groups are now used to achieve isolation; they can block access to the internal tiers from sources outside of the vnet's ip range, or the front-end subnet.\n\nAnother scenario is IP address space exhaustion: private ip space is a scarce resource in many companies. There may not be enough free space available to assign each vnet a unique, routable, segment large enough to accomodate all resources hosted in each vnet. Again, there may not be a need for all resources to have a routable ip address as they do not need to be accessible from outside the vnet.\n\n## The Solution: Subnet Peering\nThe above scenario's could be solved for if it were possible to selectively share a vnet's address range across a peering. \n\nEnter [Subnet Peering](https://learn.microsoft.com/en-us/azure/virtual-network/how-to-configure-subnet-peering): this new capability allows selective sharing of IP address space across a peering at the subnet level. \n\nSubnet Peering is not yet available through the Azure portal, but can be configured through the Azure CLI. A few new parameters have been added to the existing `az network vnet peering create` command:\n\n- `--peer-complete-vnets {0, 1 (default), f, false, n, no, t, true, y, yes}`: when set to 0, false or no configures peering at the subnet level in stead of at the vnet level.\n- `--local-subnet-names`: list of subnets to be peered in the current vnet (i.e. the vnet called out in the `--vnet-name` parameter)\n- `--remote-vnet-names`: list of subnets to be peered in the remote vnet (i.e. the vnet called out in the `--remote-vnet` parameter)\n- `--enable-only-ipv6 {0(default), 1, f, false, n, no, t, true, y, yes}`: if set to true, peers only ipv6 space in dual stack vnets.\n\n:exclamation: Although Subnet Peering is available in all Azure regions, subscription allow-listing through this [form](https://forms.office.com/pages/responsepage.aspx?id=v4j5cvGGr0GRqy180BHbR4Qnh_A4SJlJmB_ayXa7POFUNzlOVDdXQlY5WUxHWkcyNTZPRFpQV01VUi4u\u0026route=shorturl) is still required. Please read and be aware of the caveats under point 11 on the form.\n\n### Segmentation\n\nThis command peers `subnet1` in `vnet-left` to `subnet0` and `subnet2` in `right-vnet`:\n\n```\naz network vnet peering create -g sn-rg -n left0-right0 --vnet-name vnet-left --local-subnet-names subnet1 --remote-subnet-names subnet0 subnet2 --remote-vne vnet-right --peer-complete-vnets 0 --allow-vnet-access 1\n```\n\nThen establish the peering in the other direction:\n\n```\naz network vnet peering create -g sn-rg -n right0-left0 --vnet-name vnet-right --local-subnet-names subnet0 subnet2 --remote-subnet-names subnet1 --remote-vne vnet-left --peer-complete-vnets 0 --allow-vnet-access 1\n```\n\nThis leaves `subnet0` and `subnet2` in `vnet-left`, and `subnet1` in `vnet-right` disconnected, effectively creating segmentation between the peered vnets without the use of NSGs.\n\nDetails of the peerings in both directions are below. Notice the localAddressSpace and remoteAddressSpace prefixes are those of the peered local and remote subnets.\n\n```\naz network vnet peering show -g sn-rg -n left0-right0 --vnet-name vnet-left\n```\n\n```json       \n{\n  \"allowForwardedTraffic\": false,\n  \"allowGatewayTransit\": false,\n  \"allowVirtualNetworkAccess\": true,\n  \"doNotVerifyRemoteGateways\": false,\n  \"etag\": \"W/\\\"6a80a7da-36f4-404c-8bd8-d23e1b2bdd9a\\\"\",\n  \"id\": \"/subscriptions/7cb39d93-f8a1-48a7-af6d-c8e12136f0ad/resourceGroups/sn-rg/providers/Microsoft.Network/virtualNetworks/vnet-left/virtualNetworkPeerings/left0-right0\",\n  \"localAddressSpace\": {\n    \"addressPrefixes\": [\n      \"10.0.1.0/24\"\n    ]\n  },\n  \"localSubnetNames\": [\n    \"subnet1\"\n  ],\n  \"localVirtualNetworkAddressSpace\": {\n    \"addressPrefixes\": [\n      \"10.0.1.0/24\"\n    ]\n  },\n  \"name\": \"left0-right0\",\n  \"peerCompleteVnets\": false,\n  \"peeringState\": \"Connected\",\n  \"peeringSyncLevel\": \"FullyInSync\",\n  \"provisioningState\": \"Succeeded\",\n  \"remoteAddressSpace\": {\n    \"addressPrefixes\": [\n      \"10.1.0.0/24\",\n      \"10.1.2.0/24\"\n    ]\n  },\n  \"remoteSubnetNames\": [\n    \"subnet0\",\n    \"subnet2\"\n  ],\n  \"remoteVirtualNetwork\": {\n    \"id\": \"/subscriptions/7cb39d93-f8a1-48a7-af6d-c8e12136f0ad/resourceGroups/sn-rg/providers/Microsoft.Network/virtualNetworks/vnet-right\",\n    \"resourceGroup\": \"sn-rg\"\n  },\n  \"remoteVirtualNetworkAddressSpace\": {\n    \"addressPrefixes\": [\n      \"10.1.0.0/24\",\n      \"10.1.2.0/24\"\n    ]\n  },\n  \"remoteVirtualNetworkEncryption\": {\n    \"enabled\": false,\n    \"enforcement\": \"AllowUnencrypted\"\n  },\n  \"resourceGroup\": \"sn-rg\",\n  \"resourceGuid\": \"eb63ec9e-aa48-023e-1514-152f8ab39ae7\",\n  \"type\": \"Microsoft.Network/virtualNetworks/virtualNetworkPeerings\",\n  \"useRemoteGateways\": false\n}\n```\n`az network vnet peering show -g sn-rg -n right0-left0 --vnet-name vnet-right `\n```json\n{\n  \"allowForwardedTraffic\": false,\n  \"allowGatewayTransit\": false,\n  \"allowVirtualNetworkAccess\": true,\n  \"doNotVerifyRemoteGateways\": false,\n  \"etag\": \"W/\\\"bd0f0486-e84e-4dae-9a35-c8126e935cde\\\"\",\n  \"id\": \"/subscriptions/7cb39d93-f8a1-48a7-af6d-c8e12136f0ad/resourceGroups/sn-rg/providers/Microsoft.Network/virtualNetworks/vnet-right/virtualNetworkPeerings/right0-left0\",\n  \"localAddressSpace\": {\n    \"addressPrefixes\": [\n      \"10.1.0.0/24\",\n      \"10.1.2.0/24\"\n    ]\n  },\n  \"localSubnetNames\": [\n    \"subnet0\",\n    \"subnet2\"\n  ],\n  \"localVirtualNetworkAddressSpace\": {\n    \"addressPrefixes\": [\n      \"10.1.0.0/24\",\n      \"10.1.2.0/24\"\n    ]\n  },\n  \"name\": \"right0-left0\",\n  \"peerCompleteVnets\": false,\n  \"peeringState\": \"Connected\",\n  \"peeringSyncLevel\": \"FullyInSync\",\n  \"provisioningState\": \"Succeeded\",\n  \"remoteAddressSpace\": {\n    \"addressPrefixes\": [\n      \"10.0.1.0/24\"\n    ]\n  },\n  \"remoteSubnetNames\": [\n    \"subnet1\"\n  ],\n  \"remoteVirtualNetwork\": {\n    \"id\": \"/subscriptions/7cb39d93-f8a1-48a7-af6d-c8e12136f0ad/resourceGroups/sn-rg/providers/Microsoft.Network/virtualNetworks/vnet-left\",\n    \"resourceGroup\": \"sn-rg\"\n  },\n  \"remoteVirtualNetworkAddressSpace\": {\n    \"addressPrefixes\": [\n      \"10.0.1.0/24\"\n    ]\n  },\n  \"remoteVirtualNetworkEncryption\": {\n    \"enabled\": false,\n    \"enforcement\": \"AllowUnencrypted\"\n  },\n  \"resourceGroup\": \"sn-rg\",\n  \"resourceGuid\": \"eb63ec9e-aa48-023e-1514-152f8ab39ae7\",\n  \"type\": \"Microsoft.Network/virtualNetworks/virtualNetworkPeerings\",\n  \"useRemoteGateways\": false\n}\n```\nThe peerings show in the portal as \"normal\" vnet peerings, as subnet peering is not yet supported by the portal. \n\n![images](/images/subnet-peering-left.png)\n\nThe only indication that this is *not* a full vnet peering, is the peered IP address space - this is the subnet IP range of the remote subnet(s).\n\n![images](/images/subnet-peering-left-ip-space.png)\n\n\nInspecting the effective routes on vm `left-1` shows it has routes for `subnet0` and `subnet2` but not for `subnet1` in `vnet-right`: \n\n```\naz network nic show-effective-route-table -g sn-rg -n left-1701 -o table\n```\n```\nSource    State    Address Prefix    Next Hop Type    Next Hop IP\n--------  -------  ----------------  ---------------  -------------\nDefault   Active   10.0.0.0/16       VnetLocal\nDefault   Active   172.16.0.0/24     VnetLocal\nDefault   Active   10.1.0.0/24       VNetPeering\nDefault   Active   10.1.2.0/24       VNetPeering\nDefault   Active   0.0.0.0/0         Internet\n```\n\nNote that vm's `left-0` and `left-1` *also* have routes for the same subnets in `vnet-right`, even though their subnets were not listed in the `--local-subnet-names` parameter: \n\n```\naz network nic show-effective-route-table -g sn-rg -n left-0681 -o table\n```\n```\nSource    State    Address Prefix    Next Hop Type    Next Hop IP\n--------  -------  ----------------  ---------------  -------------\nDefault   Active   10.0.0.0/16       VnetLocal\nDefault   Active   172.16.0.0/24     VnetLocal\nDefault   Active   10.1.0.0/24       VNetPeering\nDefault   Active   10.1.2.0/24       VNetPeering\nDefault   Active   0.0.0.0/0         Internet\n```\n```\naz network nic show-effective-route-table -g sn-rg -n left-2809 -o table\n```\n```\nSource    State    Address Prefix    Next Hop Type    Next Hop IP\n--------  -------  ----------------  ---------------  -------------\nDefault   Active   10.0.0.0/16       VnetLocal\nDefault   Active   172.16.0.0/24     VnetLocal\nDefault   Active   10.1.0.0/24       VNetPeering\nDefault   Active   10.1.2.0/24       VNetPeering\nDefault   Active   0.0.0.0/0         Internet\n```\nIn the current release, the ip space of the subnets listed in `--remote-subnet-names` is propagated to *all* subnets in the local vnet, not just to the subnets listed in `--local-subnet-names`.\n\nHowever, the subnets in `vnet-right` only have the address space of `subnet1` in `vnet-left` propagated, as shows in the effective routes of the vm's on the right:\n```\naz network nic show-effective-route-table -g sn-rg -n right-0814 -o table\nSource    State    Address Prefix    Next Hop Type    Next Hop IP\n--------  -------  ----------------  ---------------  -------------\nDefault   Active   10.1.0.0/16       VnetLocal\nDefault   Active   172.16.0.0/24     VnetLocal\nDefault   Active   10.0.1.0/24       VNetPeering\nDefault   Active   0.0.0.0/0         Internet\n\naz network nic show-effective-route-table -g sn-rg -n right-159 -o table    \nSource    State    Address Prefix    Next Hop Type    Next Hop IP\n--------  -------  ----------------  ---------------  -------------\nDefault   Active   10.1.0.0/16       VnetLocal\nDefault   Active   172.16.0.0/24     VnetLocal\nDefault   Active   10.0.1.0/24       VNetPeering\nDefault   Active   0.0.0.0/0         Internet\n\naz network nic show-effective-route-table -g sn-rg -n right-2283 -o table\nSource    State    Address Prefix    Next Hop Type    Next Hop IP\n--------  -------  ----------------  ---------------  -------------\nDefault   Active   10.1.0.0/16       VnetLocal\nDefault   Active   172.16.0.0/24     VnetLocal\nDefault   Active   10.0.1.0/24       VNetPeering\nDefault   Active   0.0.0.0/0         Internet\n```\n\nBidrectional routing therefore only exists between `subnet1` in `vnet-left` and `subnet0` and `subnet2` in `vnet-right`, as intended:\n\n![images](/images/subnet-peering.png)\n\nThis is demonstrated by testing with ping from `left-1` to the vm's on the right:\n```\nto right-0:\nPING 10.1.0.4 (10.1.0.4) 56(84) bytes of data.\n64 bytes from 10.1.0.4: icmp_seq=1 ttl=64 time=1.20 ms\n64 bytes from 10.1.0.4: icmp_seq=2 ttl=64 time=1.24 ms\n64 bytes from 10.1.0.4: icmp_seq=3 ttl=64 time=1.06 ms\n64 bytes from 10.1.0.4: icmp_seq=4 ttl=64 time=1.56 ms\n^C\n--- 10.1.0.4 ping statistics ---\n4 packets transmitted, 4 received, 0% packet loss, time 3005ms\n\nto right-1:\nPING 10.1.1.4 (10.1.1.4) 56(84) bytes of data.\n^C\n--- 10.1.1.4 ping statistics ---\n5 packets transmitted, 0 received, 100% packet loss, time 4131ms\n\nto right-2:\nPING 10.1.2.4 (10.1.2.4) 56(84) bytes of data.\n64 bytes from 10.1.2.4: icmp_seq=1 ttl=64 time=3.39 ms\n64 bytes from 10.1.2.4: icmp_seq=2 ttl=64 time=0.968 ms\n64 bytes from 10.1.2.4: icmp_seq=3 ttl=64 time=3.00 ms\n64 bytes from 10.1.2.4: icmp_seq=4 ttl=64 time=2.47 ms\n^C\n--- 10.1.2.4 ping statistics ---\n4 packets transmitted, 4 received, 0% packet loss, time 3005ms\n```\n### Overlapping IP Space\nNow let's add overlapping ip space to both vnets. \n\nWith the peerings removed, we add 172.16.0.0/16 to each vnet, create `subnet3` with 172.16.3.0/24 and insert a vm.\n\nWhen we try to peer the full vnets, an error results because of the address space overlap:\n```\naz network vnet peering create -g sn-rg -n left0-right0 --vnet-name vnet-left --remote-vnet vnet-right --peer-complete-vnets 1 --allow-vnet-access 1\n\n(VnetAddressSpacesOverlap) Cannot create or update peering /subscriptions/7cb39d93-f8a1-48a7-af6d-c8e12136f0ad/resourceGroups/sn-rg/providers/Microsoft.Network/virtualNetworks/vnet-left/virtualNetworkPeerings/left0-right0. Virtual networks /subscriptions/7cb39d93-f8a1-48a7-af6d-c8e12136f0ad/resourceGroups/sn-rg/providers/Microsoft.Network/virtualNetworks/vnet-left and /subscriptions/7cb39d93-f8a1-48a7-af6d-c8e12136f0ad/resourceGroups/sn-rg/providers/Microsoft.Network/virtualNetworks/vnet-right cannot be peered because their address spaces overlap. Overlapping address prefixes: 172.16.0.0/16, 172.16.0.0/16\nCode: VnetAddressSpacesOverlap\n```\n![images](/images/vnet-peering-overlap.png)\n\nNow we will again establish subnet-level peering as in the previous section:\n\n```\naz network vnet peering create -g sn-rg -n left0-right0 --vnet-name vnet-left --local-subnet-names subnet1 --remote-subnet-names subnet0 subnet2 --remote-vne vnet-right --peer-complete-vnets 0 --allow-vnet-access 1\n```\n\n```\naz network vnet peering create -g sn-rg -n right0-left0 --vnet-name vnet-right --local-subnet-names subnet0 subnet2 --remote-subnet-names subnet1 --remote-vne vnet-left --peer-complete-vnets 0 --allow-vnet-access 1\n```\n\nThis completes successfully despite the presence of overlapping address space in both vnets.\n```\naz network vnet peering show -g sn-rg -n left0-right0 --vnet-name vnet-left --query  \"[provisioningState, remoteAddressSpace]\"\n[\n  \"Succeeded\",\n  {\n    \"addressPrefixes\": [\n      \"10.1.0.0/24\",\n      \"10.1.2.0/24\"\n    ]\n  }\n]\n\naz network vnet peering show -g sn-rg -n right0-left0 --vnet-name vnet-right --query  \"[provisioningState, remoteAddressSpace]\"\n[\n  \"Succeeded\",\n  {\n    \"addressPrefixes\": [\n      \"10.0.1.0/24\"\n    ]\n  }\n]\n```\n![images](/images/subnet-peering-overlap.png)\n\nNow let's try to include `vnet-left` `subnet3`, which overlaps with `subnet3` on the right, in the peering:\n```\naz network vnet peering create -g sn-rg -n left0-right0 --vnet-name vnet-left --local-subnet-names subnet1 subnet3 --remote-subnet-names subnet0 subnet2 --remote-vne vnet-right --peer-complete-vnets 0 --allow-vnet-access 1\n\n(VnetAddressSpacesOverlap) Cannot create or update peering /subscriptions/7cb39d93-f8a1-48a7-af6d-c8e12136f0ad/resourceGroups/sn-rg/providers/Microsoft.Network/virtualNetworks/vnet-left/virtualNetworkPeerings/left0-right0. Virtual networks /subscriptions/7cb39d93-f8a1-48a7-af6d-c8e12136f0ad/resourceGroups/sn-rg/providers/Microsoft.Network/virtualNetworks/vnet-left and /subscriptions/7cb39d93-f8a1-48a7-af6d-c8e12136f0ad/resourceGroups/sn-rg/providers/Microsoft.Network/virtualNetworks/vnet-right cannot be peered because their address spaces overlap. Overlapping address prefixes: 172.16.3.0/24\nCode: VnetAddressSpacesOverlap\n```\nThis demonstrates that subnet peering allows for the partial peering of vnets that contain overlapping ip space.\n\nAs discussed, this can be very helpful in scenario's where private ip space is in short supply.\n\n# Looking ahead\nSubnet peering is now available in all Azure regions: feel free to test, experiment and use in production.\n\nThe feature is currently only available through the latest versions of the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/network/vnet/peering?view=azure-cli-latest), [Bicep](https://learn.microsoft.com/en-us/azure/templates/microsoft.network/virtualnetworks/virtualnetworkpeerings?pivots=deployment-language-bicep), [ARM template](https://learn.microsoft.com/en-us/azure/templates/microsoft.network/virtualnetworks/virtualnetworkpeerings?pivots=deployment-language-arm-template), [Terraform](https://learn.microsoft.com/en-us/azure/templates/microsoft.network/virtualnetworks/virtualnetworkpeerings?pivots=deployment-language-terraform) and Powershell. Portal support should be added soon.\n\nMeaningful next steps will be to integrate Subnet Peering in both Azure Virtual Network Manager (AVNM) and Virtual WAN, so that the advantages it brings can be leveraged at enterprise scale in  nework foundations.\n\nI will continue to track developments and update this post as appropriate.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmddazure%2Fsubnet-peering","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmddazure%2Fsubnet-peering","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmddazure%2Fsubnet-peering/lists"}