Route network traffic with a route table using PowerShell

Azure automatically routes traffic between all subnets within a virtual network, by default. You can create your own routes to override Azure's default routing. The ability to create custom routes is helpful if, for example, you want to route traffic between subnets through a network virtual appliance (NVA). In this article, you learn how to:

  • Create a route table
  • Create a route
  • Create a virtual network with multiple subnets
  • Associate a route table to a subnet
  • Create an NVA that routes traffic
  • Deploy virtual machines (VM) into different subnets
  • Route traffic from one subnet to another through an NVA

If you don't have an Azure subscription, create a free account before you begin.

Launch Azure Cloud Shell

The Azure Cloud Shell is a free interactive shell that you can use to run the steps in this article. It has common Azure tools preinstalled and configured to use with your account. Just click the Copy to copy the code, paste it into the Cloud Shell, and then press enter to run it. There are a few ways to launch the Cloud Shell:

Click Try It in the upper right corner of a code block. Cloud Shell in this article
Open Cloud Shell in your browser. https://shell.azure.com/powershell
Click the Cloud Shell button on the menu in the upper right of the Azure portal. Cloud Shell in the portal

If you choose to install and use PowerShell locally, this article requires the Azure PowerShell module version 5.4.1 or later. Run Get-Module -ListAvailable AzureRM to find the installed version. If you need to upgrade, see Install Azure PowerShell module. If you are running PowerShell locally, you also need to run Connect-AzureRmAccount to create a connection with Azure.

Create a route table

Before you can create a route table, create a resource group with New-AzureRmResourceGroup. The following example creates a resource group named myResourceGroup for all resources created in this article.

New-AzureRmResourceGroup -ResourceGroupName myResourceGroup -Location EastUS

Create a route table with New-AzureRmRouteTable. The following example creates a route table named myRouteTablePublic.

$routeTablePublic = New-AzureRmRouteTable `
  -Name 'myRouteTablePublic' `
  -ResourceGroupName myResourceGroup `
  -location EastUS

Create a route

Create a route by retrieving the route table object with Get-AzureRmRouteTable, create a route with Add-AzureRmRouteConfig, then write the route configuration to the route table with Set-AzureRmRouteTable.

Get-AzureRmRouteTable `
  -ResourceGroupName "myResourceGroup" `
  -Name "myRouteTablePublic" `
  | Add-AzureRmRouteConfig `
  -Name "ToPrivateSubnet" `
  -AddressPrefix 10.0.1.0/24 `
  -NextHopType "VirtualAppliance" `
  -NextHopIpAddress 10.0.2.4 `
 | Set-AzureRmRouteTable

Associate a route table to a subnet

Before you can associate a route table to a subnet, you have to create a virtual network and subnet. Create a virtual network with New-AzureRmVirtualNetwork. The following example creates a virtual network named myVirtualNetwork with the address prefix 10.0.0.0/16.

$virtualNetwork = New-AzureRmVirtualNetwork `
  -ResourceGroupName myResourceGroup `
  -Location EastUS `
  -Name myVirtualNetwork `
  -AddressPrefix 10.0.0.0/16

Create three subnets by creating three subnet configurations with New-AzureRmVirtualNetworkSubnetConfig. The following example creates three subnet configurations for Public, Private, and DMZ subnets:

$subnetConfigPublic = Add-AzureRmVirtualNetworkSubnetConfig `
  -Name Public `
  -AddressPrefix 10.0.0.0/24 `
  -VirtualNetwork $virtualNetwork

$subnetConfigPrivate = Add-AzureRmVirtualNetworkSubnetConfig `
  -Name Private `
  -AddressPrefix 10.0.1.0/24 `
  -VirtualNetwork $virtualNetwork

$subnetConfigDmz = Add-AzureRmVirtualNetworkSubnetConfig `
  -Name DMZ `
  -AddressPrefix 10.0.2.0/24 `
  -VirtualNetwork $virtualNetwork

Write the subnet configurations to the virtual network with Set-AzureRmVirtualNetwork, which creates the subnets in the virtual network:

$virtualNetwork | Set-AzureRmVirtualNetwork

Associate the myRouteTablePublic route table to the Public subnet with Set-AzureRmVirtualNetworkSubnetConfig and then write the subnet configuration to the virtual network with Set-AzureRmVirtualNetwork.

Set-AzureRmVirtualNetworkSubnetConfig `
  -VirtualNetwork $virtualNetwork `
  -Name 'Public' `
  -AddressPrefix 10.0.0.0/24 `
  -RouteTable $routeTablePublic | `
Set-AzureRmVirtualNetwork

Create an NVA

An NVA is a VM that performs a network function, such as routing, firewalling, or WAN optimization.

Before creating a VM, create a network interface.

Create a network interface

Before creating a network interface, you have to retrieve the virtual network Id with Get-AzureRmVirtualNetwork, then the subnet Id with Get-AzureRmVirtualNetworkSubnetConfig. Create a network interface with New-AzureRmNetworkInterface in the DMZ subnet with IP forwarding enabled:

# Retrieve the virtual network object into a variable.
$virtualNetwork=Get-AzureRmVirtualNetwork `
  -Name myVirtualNetwork `
  -ResourceGroupName myResourceGroup

# Retrieve the subnet configuration into a variable.
$subnetConfigDmz = Get-AzureRmVirtualNetworkSubnetConfig `
  -Name DMZ `
  -VirtualNetwork $virtualNetwork

# Create the network interface.
$nic = New-AzureRmNetworkInterface `
  -ResourceGroupName myResourceGroup `
  -Location EastUS `
  -Name 'myVmNva' `
  -SubnetId $subnetConfigDmz.Id `
  -EnableIPForwarding

Create a VM

To create a VM and attach an existing network interface to it, you must first create a VM configuration with New-AzureRmVMConfig. The configuration includes the network interface created in the previous step. When prompted for a username and password, select the user name and password you want to log into the VM with.

# Create a credential object.
$cred = Get-Credential -Message "Enter a username and password for the VM."

# Create a VM configuration.
$vmConfig = New-AzureRmVMConfig `
  -VMName 'myVmNva' `
  -VMSize Standard_DS2 | `
  Set-AzureRmVMOperatingSystem -Windows `
    -ComputerName 'myVmNva' `
    -Credential $cred | `
  Set-AzureRmVMSourceImage `
    -PublisherName MicrosoftWindowsServer `
    -Offer WindowsServer `
    -Skus 2016-Datacenter `
    -Version latest | `
  Add-AzureRmVMNetworkInterface -Id $nic.Id

Create the VM using the VM configuration with New-AzureRmVM. The following example creates a VM named myVmNva.

$vmNva = New-AzureRmVM `
  -ResourceGroupName myResourceGroup `
  -Location EastUS `
  -VM $vmConfig `
  -AsJob

The -AsJob option creates the VM in the background, so you can continue to the next step.

Create virtual machines

Create two VMs in the virtual network so you can validate that traffic from the Public subnet is routed to the Private subnet through the network virtual appliance in a later step.

Create a VM in the Public subnet with New-AzureRmVM. The following example creates a VM named myVmPublic in the Public subnet of the myVirtualNetwork virtual network.

New-AzureRmVm `
  -ResourceGroupName "myResourceGroup" `
  -Location "East US" `
  -VirtualNetworkName "myVirtualNetwork" `
  -SubnetName "Public" `
  -ImageName "Win2016Datacenter" `
  -Name "myVmPublic" `
  -AsJob

Create a VM in the Private subnet.

New-AzureRmVm `
  -ResourceGroupName "myResourceGroup" `
  -Location "East US" `
  -VirtualNetworkName "myVirtualNetwork" `
  -SubnetName "Private" `
  -ImageName "Win2016Datacenter" `
  -Name "myVmPrivate"

The VM takes a few minutes to create. Don't continue with the next step until the VM is created and Azure returns output to PowerShell.

Route traffic through an NVA

Use Get-AzureRmPublicIpAddress to return the public IP address of the myVmPrivate VM. The following example returns the public IP address of the myVmPrivate VM:

Get-AzureRmPublicIpAddress `
  -Name myVmPrivate `
  -ResourceGroupName myResourceGroup `
  | Select IpAddress

Use the following command to create a remote desktop session with the myVmPrivate VM from your local computer. Replace <publicIpAddress> with the IP address returned from the previous command.

mstsc /v:<publicIpAddress>

Open the downloaded RDP file. If prompted, select Connect.

Enter the user name and password you specified when creating the VM (you may need to select More choices, then Use a different account, to specify the credentials you entered when you created the VM), then select OK. You may receive a certificate warning during the sign-in process. Select Yes to proceed with the connection.

In a later step, the tracert.exe command is used to test routing. Tracert uses the Internet Control Message Protocol (ICMP), which is denied through the Windows Firewall. Enable ICMP through the Windows firewall by entering the following command from PowerShell on the myVmPrivate VM:

New-NetFirewallRule -DisplayName "Allow ICMPv4-In" -Protocol ICMPv4

Though trace route is used to test routing in this article, allowing ICMP through the Windows Firewall for production deployments is not recommended.

You enabled IP forwarding within Azure for the VM's network interface in Enable IP fowarding. Within the VM, the operating system, or an application running within the VM, must also be able to forward network traffic. Enable IP forwarding within the operating system of the myVmNva.

From a command prompt on the myVmPrivate VM, remote desktop to the myVmNva:

mstsc /v:myvmnva

To enable IP forwarding within the operating system, enter the following command in PowerShell from the myVmNva VM:

Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters -Name IpEnableRouter -Value 1

Restart the myVmNva VM, which also disconnects the remote desktop session.

While still connected to the myVmPrivate VM, create a remote desktop session to the myVmPublic VM, after the myVmNva VM restarts:

mstsc /v:myVmPublic

Enable ICMP through the Windows firewall by entering the following command from PowerShell on the myVmPublic VM:

New-NetFirewallRule –DisplayName “Allow ICMPv4-In” –Protocol ICMPv4

To test routing of network traffic to the myVmPrivate VM from the myVmPublic VM, enter the following command from PowerShell on the myVmPublic VM:

tracert myVmPrivate

The response is similar to the following example:

Tracing route to myVmPrivate.vpgub4nqnocezhjgurw44dnxrc.bx.internal.cloudapp.net [10.0.1.4]
over a maximum of 30 hops:

1    <1 ms     *        1 ms  10.0.2.4
2     1 ms     1 ms     1 ms  10.0.1.4

Trace complete.

You can see that the first hop is 10.0.2.4, which is the NVA's private IP address. The second hop is 10.0.1.4, the private IP address of the myVmPrivate VM. The route added to the myRouteTablePublic route table and associated to the Public subnet caused Azure to route the traffic through the NVA, rather than directly to the Private subnet.

Close the remote desktop session to the myVmPublic VM, which leaves you still connected to the myVmPrivate VM.

To test routing of network traffic to the myVmPublic VM from the myVmPrivate VM, enter the following command from a command prompt on the myVmPrivate VM:

tracert myVmPublic

The response is similar to the following example:

Tracing route to myVmPublic.vpgub4nqnocezhjgurw44dnxrc.bx.internal.cloudapp.net [10.0.0.4]
over a maximum of 30 hops:

1     1 ms     1 ms     1 ms  10.0.0.4

Trace complete.

You can see that traffic is routed directly from the myVmPrivate VM to the myVmPublic VM. By default, Azure routes traffic directly between subnets.

Close the remote desktop session to the myVmPrivate VM.

Clean up resources

When no longer needed, use Remove-AzureRmResourcegroup to remove the resource group and all of the resources it contains.

Remove-AzureRmResourceGroup -Name myResourceGroup -Force

Next steps

In this article, you created a route table and associated it to a subnet. You created a simple network virtual appliance that routed traffic from a public subnet to a private subnet. Deploy a variety of pre-configured network virtual appliances that perform network functions such as firewall and WAN optimization from the Azure Marketplace. To learn more about routing, see Routing overview and Manage a route table.

While you can deploy many Azure resources within a virtual network, resources for some Azure PaaS services cannot be deployed into a virtual network. You can still restrict access to the resources of some Azure PaaS services to traffic only from a virtual network subnet though. To learn how, see Restrict network access to PaaS resources.