User-Defined Routing

User-Defined Routing

In this lab you will learn how to do the following:

  • Log in to the Azure CLI

  • Create a firewall

  • Custom route a frontend

  • Custom route a backend

Step 1 - Logging In

Run this command to log in to the Azure account:

az login -u $username -p $password

After you log in, you should get a block of JSON with details about your sign-in.

You can view the Azure account username with this command:

echo $username

You can view the Azure account password with this command:

echo $password

Step 2 - Getting Set Up

When you connect resources, such as making one virtual machine ping another, or pinging an external website, Azure will automatically manage the routings for you. For example, if a VM running a web service requests resources from the web, Azure will automatically create and manage that connection for you. If another VM holding an API connects to the web service VM, Azure will create and manage that connection too.

But there may be times when you want to route traffic differently, such as having a specific appliance (e.g., a "firewall") intercept all incoming traffic from one resource to another. We could also control the outbound routing to the internet to go through the firewall too.

We use route tables to redirect traffic and to forward it through the appropriate resources. Azure generates its own route tables by default, but we will learn how to customize our user-defined routes (UDRs) to redirect traffic and associate them with subnets. Specifically, we will run our traffic through a virtual network appliance (firewall).

First we need a resource group. The resource group with a name saved to the variable $resource, which was created with this command:

az group create --name $resource --location eastus

Next let's create our virtual network:

az network vnet create \
    --resource-group $resource \
    --name myVnet \
    --address-prefix 10.0.0.0/16  \
    --location eastus \
    --subnet-name myFrontendSubnet \
    --subnet-prefix 10.0.1.0/24

Then let's create our network security group (NSG):

az network nsg create \
    --resource-group $resource \
    --name myNSG \
    --location eastus

Let's then allow HTTP and HTTPS traffic:

az network nsg rule create \
    --resource-group $resource \
    --nsg-name myNSG \
    --name AllowHTTP \
    --access Allow \
    --protocol Tcp \
    --direction Inbound \
    --priority 100 \
    --source-address-prefix Internet \
    --source-port-range "*" \
    --destination-address-prefix "*" \
    --destination-port-range 80
az network nsg rule create \
    --resource-group $resource \
    --nsg-name myNSG \
    --name allowHTTPS \
    --access Allow \
    --protocol Tcp \
    --direction Inbound \
    --priority 200 \
    --source-address-prefix Internet \
    --source-port-range "*" \
    --destination-address-prefix "*" \
    --destination-port-range 443

Step 3 - Creating the Firewall

Let's associate our NSG with our frontend subnet:

az network vnet subnet update \
    --vnet-name myVnet \
    --name myFrontendSubnet \
    --resource-group $resource \
    --network-security-group myNSG

Now let's create a subnet for the backend:

az network vnet subnet create \
    --address-prefix 10.0.2.0/24 \
    --name myBackendSubnet \
    --resource-group $resource \
    --vnet-name myVnet

And then let's create the DMZ subnet, or the subnet that separates the trusted network from the untrusted network that is the internet:

az network vnet subnet create \
    --address-prefix 10.0.0.0/24 \
    --name myDMZSubnet \
    --resource-group $resource \
    --vnet-name myVnet

Next, create the public IP for the firewall virtual machine:

az network public-ip create \
    --resource-group $resource \
    --name myPublicFirewallIp

And then the network interface that will do the IP forwarding:

az network nic create \
    --resource-group $resource \
    --name myFirewallNic \
    --vnet-name myVnet \
    --subnet myDmzSubnet \
    --public-ip-address myPublicFirewallIp \
    --ip-forwarding

Finally, we'll create the firewall appliance itself, which will be a VM running Ubuntu. Note that we are wiring it up with the network interface for the firewall we just created:

az vm create \
    --resource-group $resource \
    --name myFirewallVM \
    --nics myFirewallNic \
    --image UbuntuLTS \
    --admin-username azureuser \
    --generate-ssh-keys \
    --public-ip-sku BASIC

Step 4 - Routing the Frontend

Get the private IP address from the firewall VM we just created and save it to a variable:

firewallVMIp=$(az vm list-ip-addresses \
    --resource-group $resource \
    --name myFirewallVM \
    --query '[].virtualMachine.network.privateIpAddresses[0]' --out tsv)

echo $firewallVMIp

Now let's start creating the routings. First, create the routing table for the frontend subnet:

az network route-table create \
    --name routeTableFESubnet \
    --resource-group $resource

Then we can add a routing from the frontend to the backend via the firewall appliance:

az network route-table route create \
    --name routingToBE  \
    --resource-group $resource \
    --route-table-name routeTableFESubnet \
    --address-prefix 10.0.2.0/24 \
    --next-hop-type VirtualAppliance \
    --next-hop-ip-address $firewallVMIp

Passing through the firewall VM, route traffic from the frontend subnet to the internet. Note the hop-related arguments that will redirect requests to the firewall VM:

az network route-table route create \
    --name routingInternetToBE \
    --resource-group $resource \
    --route-table-name routeTableFESubnet \
    --address-prefix 0.0.0.0/0 \
    --next-hop-type VirtualAppliance \
    --next-hop-ip-address $firewallVMIp

After we create and populate the route table, let's associate it with the frontend subnet:

az network vnet subnet update \
    --name myFrontendSubnet \
    --vnet-name myVnet \
    --resource-group $resource \
    --route-table routeTableFESubnet

Oy vey! Almost done.

Step 5 - Routing the Backend

Next, we wire up the backend table and subnet, just like we did for the frontend. First let's create the route table for the backend:

az network route-table create \
    --name routeTableBESubnet \
    --resource-group $resource

We will then route traffic from the backend subnet to the frontend subnet through the firewall device. Again note the hop-related arguments that will bounce to the firewall VM:

az network route-table route create \
    --name routingToFE \
    --resource-group $resource \
    --route-table-name routeTableBESubnet \
    --address-prefix 10.0.2.0/24 \
    --next-hop-type VirtualAppliance \
    --next-hop-ip-address $firewallVMIp

Last routing! Again passing through the firewall, create a route for traffic from the backend subnet to the internet:

az network route-table route create \
    --name routeToInternetBE \
    --resource-group $resource \
    --route-table-name routeTableBESubnet \
    --address-prefix 0.0.0.0/0 \
    --next-hop-type VirtualAppliance \
    --next-hop-ip-address $firewallVMIp

Lastly, associate the route table to the subnet of the backend:

az network vnet subnet update \
    --name myBackendSubnet \
    --vnet-name myVnet \
    --resource-group $resource \
    --route-table routeTableBESubnet

Now we have configured all routings to put traffic through our virtual network appliance (firewall). This way, we configure how traffic is routed and controlled rather than letting Azure automatically manage the routings. There is nothing wrong with Azure automatically managing routings, unless you have a custom traffic filtering policy you want to impose.