My WordPress Blog

Designing a DMZ for Azure Virtual Machines

This article will show you three designs, each building on the other, for a demilitarised zone (DMZ) or perimeter network for Internet facing n-tier applications based on Azure virtual machines and networking.


The concept of a DMZ or perimeter network is not new; it’s a classic design that uses a layered network security approach to minimize the attack footprint of an application.

In a simple design:

  1. Web servers are placed in one VLAN, with just TCP 80 and TCP 443 accessible from the Internet.
  2. Application servers are in another VLAN. Web servers can communicate with the application servers using just the application protocol. The Internet has no access to this VLAN.
  3. Database servers are in a third VLAN. Application servers can communicate with the database servers using only the database communications protocol. Web servers and the Internet have no access to this VLAN.

You can modify this design in many ways, including:

  • Adding additional application layer security.
  • Including reverse proxies.
  • Using logical implementations of multiple VLANs by using other methods of network isolation, such as network security groups (NSGs) in Azure.

The concept of a DMZ with n-tier applications

So how do you recreate this concept in Azure for virtual machines? I’ll present you with three designs from Microsoft, each of which builds on the concepts of the previous ones.

Network Security Groups

The first and simplest way to build a DMZ in Azure is to use network security groups (NSGs). An NSG is a five-tuple rule that will allow or block TCP or UDP traffic between designated addresses on a virtual network.

You can deploy an n-tier solution into a single virtual network that is split into two or more subnets; each subnet plays the role of a VLAN, as shown above. NSG rules are then created to restrict network traffic. In the below diagram, NSGs will:

  • Allow web traffic into the FrontEnd subnet.
  • All application traffic to flow from the FrontEnd subnet to the BackEnd subnet.
  • Block all other traffic.

A DMZ using Azure network security groups 

The benefit of this design is that it is very simple. The drawback of this design is that it assumes that your potential hackers are stuck in the 1990s; a modern attack tries to compromise the application layer. A port scan of the above from an external point will reveal that TCP 80/443 are open, so an attacker will try to attack those ports. A simple five-tuple rule will not block that traffic, so the hacker can either flood the target with a DDOS attack or compromise application vulnerabilities.

NSGs and a Firewall

Modern edge network devices can protect and enhance hosted applications with applications layer scanning and/or reverse proxy services. The Azure Marketplace allows you to deploy these kinds of devices from multiple vendors into your Azure virtual networks.

The following design below uses a virtual network appliance to protect an application from threats; this offers more than just simple protocol filtering because the appliance understands the allowed traffic and can identify encapsulated risks.

Using a firewall virtual appliance with NSGs to create a DMZ

NSGS are deployed to enforce that all communications from the Internet must flow through the virtual appliance. NSGs will also control the protocols and ports that are allowed for internal communications between the subnets.

Ideally, we’d like to have all communications inside of the virtual network to flow through the virtual appliance, but the default routing rules of the network will prevent this from happening.

User Defined Routes, NSGs, and a Firewall

We can override the default routes of a virtual network using user-defined routes (UDRs). The following design uses one subnet in a single virtual network for each layer of the n-tier application. An additional subnet is created just for the virtual firewall appliance, which will secure the application.

UDRs are created to override the default routes between the subnets, forcing all traffic between subnets to route via the virtual firewall appliance. NSGs are created to enforce this routing and block traffic via the default routes.

An Azure DMZ made from user-defined routes, a virtual appliance firewall and NSGs (Image Credit: Microsoft)

The result is a DMZ where the virtual appliance controls all traffic to/from the Internet and between the subnets.

Tip: Try to use a next generation firewall and compliment this with defence with additional security products that will work with the Azure Security Center so that you have a single view of all trends and risks.

Azure Create Application Gateway that hosts multiple web sites using Azure PowerShell

You can use Azure Powershell to configure the hosting of multiple web sites when you create an application gateway. In this article, you define backend address pools using virtual machines scale sets. You then configure listeners and rules based on domains that you own to make sure web traffic arrives at the appropriate servers in the pools. This article assumes that you own multiple domains and uses examples of and

In this article, you learn how to:

  • Set up the network
  • Create an application gateway
  • Create backend listeners
  • Create routing rules
  • Create virtual machine scale sets with the backend pools
  • Create a CNAME record in your domain
Multi-site routing example

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


This article has been updated to use the new Azure PowerShell Az module. You can still use the AzureRM module, which will continue to receive bug fixes until at least December 2020. To learn more about the new Az module and AzureRM compatibility, see Introducing the new Azure PowerShell Az module. For Az module installation instructions, see Install Azure PowerShell.

Use Azure Cloud Shell

Azure hosts Azure Cloud Shell, an interactive shell environment that you can use through your browser. You can use either Bash or PowerShell with Cloud Shell to work with Azure services. You can use the Cloud Shell preinstalled commands to run the code in this article without having to install anything on your local environment.

To start Azure Cloud Shell:

Select Try It in the upper-right corner of a code block. Selecting Try It doesn’t automatically copy the code to Cloud Shell.Example of Try It for Azure Cloud Shell
Go to, or select the Launch Cloud Shell button to open Cloud Shell in your browser.
Select the Cloud Shell button on the menu bar at the upper right in the Azure portal.Cloud Shell button in the Azure portal

To run the code in this article in Azure Cloud Shell:

  1. Start Cloud Shell.
  2. Select the Copy button on a code block to copy the code.
  3. Paste the code into the Cloud Shell session by selecting Ctrl+Shift+V on Windows and Linux or by selecting Cmd+Shift+V on macOS.
  4. Select Enter to run the code.

If you choose to install and use the PowerShell locally, this article requires the Azure PowerShell module version 1.0.0 or later. To find the version, run Get-Module -ListAvailable Az . If you need to upgrade, see Install Azure PowerShell module. If you’re running PowerShell locally, you also need to run Login-AzAccount to create a connection with Azure.

Create a resource group

A resource group is a logical container into which Azure resources are deployed and managed. Create an Azure resource group using New-AzResourceGroup.Azure PowerShellCopyTry It

New-AzResourceGroup -Name myResourceGroupAG -Location eastus

Create network resources

Create the subnet configurations using New-AzVirtualNetworkSubnetConfig. Create the virtual network using New-AzVirtualNetwork with the subnet configurations. And finally, create the public IP address using New-AzPublicIpAddress. These resources are used to provide network connectivity to the application gateway and its associated resources.Azure PowerShellCopyTry It

$backendSubnetConfig = New-AzVirtualNetworkSubnetConfig `
  -Name myBackendSubnet `

$agSubnetConfig = New-AzVirtualNetworkSubnetConfig `
  -Name myAGSubnet `

$vnet = New-AzVirtualNetwork `
  -ResourceGroupName myResourceGroupAG `
  -Location eastus `
  -Name myVNet `
  -AddressPrefix `
  -Subnet $backendSubnetConfig, $agSubnetConfig

$pip = New-AzPublicIpAddress `
  -ResourceGroupName myResourceGroupAG `
  -Location eastus `
  -Name myAGPublicIPAddress `
  -AllocationMethod Dynamic

Create an application gateway

Create the IP configurations and frontend port

Associate the subnet that you previously created to the application gateway using New-AzApplicationGatewayIPConfiguration. Assign the public IP address to the application gateway using New-AzApplicationGatewayFrontendIPConfig.Azure PowerShellCopyTry It

$vnet = Get-AzVirtualNetwork `
  -ResourceGroupName myResourceGroupAG `
  -Name myVNet


$gipconfig = New-AzApplicationGatewayIPConfiguration `
  -Name myAGIPConfig `
  -Subnet $subnet

$fipconfig = New-AzApplicationGatewayFrontendIPConfig `
  -Name myAGFrontendIPConfig `
  -PublicIPAddress $pip

$frontendport = New-AzApplicationGatewayFrontendPort `
  -Name myFrontendPort `
  -Port 80

Create the backend pools and settings

Create the first backend address pool for the application gateway using New-AzApplicationGatewayBackendAddressPool. Configure the settings for the pool using New-AzApplicationGatewayBackendHttpSettings.Azure PowerShellCopyTry It

$contosoPool = New-AzApplicationGatewayBackendAddressPool `
  -Name contosoPool

$fabrikamPool = New-AzApplicationGatewayBackendAddressPool `
  -Name fabrikamPool

$poolSettings = New-AzApplicationGatewayBackendHttpSettings `
  -Name myPoolSettings `
  -Port 80 `
  -Protocol Http `
  -CookieBasedAffinity Enabled `
  -RequestTimeout 120

Create the listeners and rules

Listeners are required to enable the application gateway to route traffic appropriately to the backend address pools. In this article, you create two listeners for your two domains. Listeners are created for the and domains.

Create the first listener using New-AzApplicationGatewayHttpListener with the frontend configuration and frontend port that you previously created. A rule is required for the listener to know which backend pool to use for incoming traffic. Create a basic rule named contosoRule using New-AzApplicationGatewayRequestRoutingRule.Azure PowerShellCopyTry It

$contosolistener = New-AzApplicationGatewayHttpListener `
  -Name contosoListener `
  -Protocol Http `
  -FrontendIPConfiguration $fipconfig `
  -FrontendPort $frontendport `
  -HostName ""

$fabrikamlistener = New-AzApplicationGatewayHttpListener `
  -Name fabrikamListener `
  -Protocol Http `
  -FrontendIPConfiguration $fipconfig `
  -FrontendPort $frontendport `
  -HostName ""

$contosoRule = New-AzApplicationGatewayRequestRoutingRule `
  -Name contosoRule `
  -RuleType Basic `
  -HttpListener $contosoListener `
  -BackendAddressPool $contosoPool `
  -BackendHttpSettings $poolSettings

$fabrikamRule = New-AzApplicationGatewayRequestRoutingRule `
  -Name fabrikamRule `
  -RuleType Basic `
  -HttpListener $fabrikamListener `
  -BackendAddressPool $fabrikamPool `
  -BackendHttpSettings $poolSettings

Create the application gateway

Now that you created the necessary supporting resources, specify parameters for the application gateway using New-AzApplicationGatewaySku, and then create it using New-AzApplicationGateway.Azure PowerShellCopyTry It

$sku = New-AzApplicationGatewaySku `
  -Name Standard_Medium `
  -Tier Standard `
  -Capacity 2

$appgw = New-AzApplicationGateway `
  -Name myAppGateway `
  -ResourceGroupName myResourceGroupAG `
  -Location eastus `
  -BackendAddressPools $contosoPool, $fabrikamPool `
  -BackendHttpSettingsCollection $poolSettings `
  -FrontendIpConfigurations $fipconfig `
  -GatewayIpConfigurations $gipconfig `
  -FrontendPorts $frontendport `
  -HttpListeners $contosoListener, $fabrikamListener `
  -RequestRoutingRules $contosoRule, $fabrikamRule `
  -Sku $sku

Create virtual machine scale sets

In this example, you create two virtual machine scale sets that support the two backend pools that you created. The scale sets that you create are named myvmss1 and myvmss2. Each scale set contains two virtual machine instances on which you install IIS. You assign the scale set to the backend pool when you configure the IP settings.Azure PowerShellCopyTry It

$vnet = Get-AzVirtualNetwork `
  -ResourceGroupName myResourceGroupAG `
  -Name myVNet

$appgw = Get-AzApplicationGateway `
  -ResourceGroupName myResourceGroupAG `
  -Name myAppGateway

$contosoPool = Get-AzApplicationGatewayBackendAddressPool `
  -Name contosoPool `
  -ApplicationGateway $appgw

$fabrikamPool = Get-AzApplicationGatewayBackendAddressPool `
  -Name fabrikamPool `
  -ApplicationGateway $appgw

for ($i=1; $i -le 2; $i++)
  if ($i -eq 1) 
    $poolId = $contosoPool.Id
  if ($i -eq 2)
    $poolId = $fabrikamPool.Id

  $ipConfig = New-AzVmssIpConfig `
    -Name myVmssIPConfig$i `
    -SubnetId $vnet.Subnets[1].Id `
    -ApplicationGatewayBackendAddressPoolsId $poolId

  $vmssConfig = New-AzVmssConfig `
    -Location eastus `
    -SkuCapacity 2 `
    -SkuName Standard_DS2 `
    -UpgradePolicyMode Automatic

  Set-AzVmssStorageProfile $vmssConfig `
    -ImageReferencePublisher MicrosoftWindowsServer `
    -ImageReferenceOffer WindowsServer `
    -ImageReferenceSku 2016-Datacenter `
    -ImageReferenceVersion latest `
    -OsDiskCreateOption FromImage

  Set-AzVmssOsProfile $vmssConfig `
    -AdminUsername azureuser `
    -AdminPassword "Azure123456!" `
    -ComputerNamePrefix myvmss$i

  Add-AzVmssNetworkInterfaceConfiguration `
    -VirtualMachineScaleSet $vmssConfig `
    -Name myVmssNetConfig$i `
    -Primary $true `
    -IPConfiguration $ipConfig

  New-AzVmss `
    -ResourceGroupName myResourceGroupAG `
    -Name myvmss$i `
    -VirtualMachineScaleSet $vmssConfig

Install IIS

Azure PowerShellCopyTry It

$publicSettings = @{ "fileUris" = (,""); 
  "commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File appgatewayurl.ps1" }

for ($i=1; $i -le 2; $i++)
  $vmss = Get-AzVmss `
    -ResourceGroupName myResourceGroupAG `
    -VMScaleSetName myvmss$i

  Add-AzVmssExtension -VirtualMachineScaleSet $vmss `
    -Name "customScript" `
    -Publisher "Microsoft.Compute" `
    -Type "CustomScriptExtension" `
    -TypeHandlerVersion 1.8 `
    -Setting $publicSettings

  Update-AzVmss `
    -ResourceGroupName myResourceGroupAG `
    -Name myvmss$i `
    -VirtualMachineScaleSet $vmss

Create CNAME record in your domain

After the application gateway is created with its public IP address, you can get the DNS address and use it to create a CNAME record in your domain. You can use Get-AzPublicIPAddress to get the DNS address of the application gateway. Copy the fqdn value of the DNSSettings and use it as the value of the CNAME record that you create. Using A-records isn’t recommended because the VIP may change when the application gateway is restarted in the V1 SKU.Azure PowerShellCopyTry It

Get-AzPublicIPAddress -ResourceGroupName myResourceGroupAG -Name myAGPublicIPAddress

Test the application gateway

Enter your domain name into the address bar of your browser. Such as,

Test contoso site in application gateway

Change the address to your other domain and you should see something like the following example:

Test fabrikam site in application gateway

Clean up resources

When no longer needed, remove the resource group, application gateway, and all related resources using Remove-AzResourceGroup.Azure PowerShellCopyTry It

Remove-AzResourceGroup -Name myResourceGroupAG

Azure – Create, Configure Application Gateway to host multiple web sites using the Azure portal

You can use the Azure portal to configure the hosting of multiple web sites when you create an application gateway. In this tutorial, you define backend address pools using virtual machines. You then configure listeners and rules based on domains that you own to make sure web traffic arrives at the appropriate servers in the pools. This tutorial assumes that you own multiple domains and uses examples of and

In this tutorial, you learn how to:

  • Create an application gateway
  • Create virtual machines for backend servers
  • Create backend pools with the backend servers
  • Create backend listeners
  • Create routing rules
  • Create a CNAME record in your domain
Multi-site routing example

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

Sign in to Azure

Sign in to the Azure portal at

Create an application gateway

  1. Select Create a resource on the left menu of the Azure portal. The New window appears.
  2. Select Networking and then select Application Gateway in the Featured list.

Basics tab

  1. On the Basics tab, enter these values for the following application gateway settings:
    • Resource group: Select myResourceGroupAG for the resource group. If it doesn’t exist, select Create new to create it.
    • Application gateway name: Enter myAppGateway for the name of the application gateway.Create new application gateway: Basics
  2. For Azure to communicate between the resources that you create, it needs a virtual network. You can either create a new virtual network or use an existing one. In this example, you’ll create a new virtual network at the same time that you create the application gateway. Application Gateway instances are created in separate subnets. You create two subnets in this example: one for the application gateway, and another for the backend servers.Under Configure virtual network, select Create new to create a new virtual network . In the Create virtual network window that opens, enter the following values to create the virtual network and two subnets:
    • Name: Enter myVNet for the name of the virtual network.
    • Subnet name (Application Gateway subnet): The Subnets grid will show a subnet named Default. Change the name of this subnet to myAGSubnet.
      The application gateway subnet can contain only application gateways. No other resources are allowed.
    • Subnet name (backend server subnet): In the second row of the Subnets grid, enter myBackendSubnet in the Subnet name column.
    • Address range (backend server subnet): In the second row of the Subnets Grid, enter an address range that doesn’t overlap with the address range of myAGSubnet. For example, if the address range of myAGSubnet is, enter for the address range of myBackendSubnet.
    Select OK to close the Create virtual network window and save the virtual network settings.Create new application gateway: virtual network
  3. On the Basics tab, accept the default values for the other settings and then select Next: Frontends.

Frontends tab

  1. On the Frontends tab, verify Frontend IP address type is set to Public.
    You can configure the Frontend IP to be Public or Private as per your use case. In this example, you’ll choose a Public Frontend IP. NoteFor the Application Gateway v2 SKU, you can only choose Public frontend IP configuration. Private frontend IP configuration is currently not enabled for this v2 SKU.
  2. Choose Create new for the Public IP address and enter myAGPublicIPAddress for the public IP address name, and then select OK.Create new application gateway: frontends
  3. Select Next: Backends.

Backends tab

The backend pool is used to route requests to the backend servers that serve the request. Backend pools can be NICs, virtual machine scale sets, public IPs, internal IPs, fully qualified domain names (FQDN), and multi-tenant back-ends like Azure App Service. In this example, you’ll create an empty backend pool with your application gateway and then add backend targets to the backend pool.

  1. On the Backends tab, select +Add a backend pool.
  2. In the Add a backend pool window that opens, enter the following values to create an empty backend pool:
    • Name: Enter contosoPool for the name of the backend pool.
    • Add backend pool without targets: Select Yes to create a backend pool with no targets. You’ll add backend targets after creating the application gateway.
  3. In the Add a backend pool window, select Add to save the backend pool configuration and return to the Backends tab.
  4. Now add another backend pool called fabrikamPool.Create new application gateway: backends
  5. On the Backends tab, select Next: Configuration.

Configuration tab

On the Configuration tab, you’ll connect the frontend and backend pools you created using a routing rule.

  1. Select Add a rule in the Routing rules column.
  2. In the Add a routing rule window that opens, enter contosoRule for the Rule name.
  3. A routing rule requires a listener. On the Listener tab within the Add a routing rule window, enter the following values for the listener:
    • Listener name: Enter contosoListener for the name of the listener.
    • Frontend IP: Select Public to choose the public IP you created for the frontend.
    Under Additional settings:Accept the default values for the other settings on the Listener tab, then select the Backend targets tab to configure the rest of the routing rule.Create new application gateway: listener
  4. On the Backend targets tab, select contosoPool for the Backend target.
  5. For the HTTP setting, select Create new to create a new HTTP setting. The HTTP setting will determine the behavior of the routing rule. In the Add an HTTP setting window that opens, enter contosoHTTPSetting for the HTTP setting name. Accept the default values for the other settings in the Add an HTTP setting window, then select Add to return to the Add a routing rule window.
  6. On the Add a routing rule window, select Add to save the routing rule and return to the Configuration tab.
  7. Select Add a rule and add a similar rule, listener, backend target, and HTTP setting for Fabrikam.Create new application gateway: routing rule
  8. Select Next: Tags and then Next: Review + create.

Review + create tab

Review the settings on the Review + create tab, and then select Create to create the virtual network, the public IP address, and the application gateway. It may take several minutes for Azure to create the application gateway.

Wait until the deployment finishes successfully before moving on to the next section.

Add backend targets

In this example, you’ll use virtual machines as the target backend. You can either use existing virtual machines or create new ones. You’ll create two virtual machines that Azure uses as backend servers for the application gateway.

To add backend targets, you’ll:

  1. Create two new VMs, contosoVM and fabrikamVM, to be used as backend servers.
  2. Install IIS on the virtual machines to verify that the application gateway was created successfully.
  3. Add the backend servers to the backend pools.

Create a virtual machine

  1. On the Azure portal, select Create a resource. The New window appears.
  2. Select Compute and then select Windows Server 2016 Datacenter in the Popular list. The Create a virtual machine page appears.
    Application Gateway can route traffic to any type of virtual machine used in its backend pool. In this example, you use a Windows Server 2016 Datacenter.
  3. Enter these values in the Basics tab for the following virtual machine settings:
    • Resource group: Select myResourceGroupAG for the resource group name.
    • Virtual machine name: Enter contosoVM for the name of the virtual machine.
    • Username: Enter azureuser for the administrator user name.
    • Password: Enter Azure123456! for the administrator password.
  4. Accept the other defaults and then select Next: Disks.
  5. Accept the Disks tab defaults and then select Next: Networking.
  6. On the Networking tab, verify that myVNet is selected for the Virtual network and the Subnet is set to myBackendSubnet. Accept the other defaults and then select Next: Management.
    Application Gateway can communicate with instances outside of the virtual network that it is in, but you need to ensure there’s IP connectivity.
  7. On the Management tab, set Boot diagnostics to Off. Accept the other defaults and then select Review + create.
  8. On the Review + create tab, review the settings, correct any validation errors, and then select Create.
  9. Wait for the virtual machine creation to complete before continuing.

Install IIS for testing

In this example, you install IIS on the virtual machines only to verify Azure created the application gateway successfully.

  1. Open Azure PowerShell. To do so, select Cloud Shell from the top navigation bar of the Azure portal and then select PowerShell from the drop-down list.Install custom extension
  2. Run the following command to install IIS on the virtual machine:Azure PowerShellCopyTry ItSet-AzVMExtension ` -ResourceGroupName myResourceGroupAG ` -ExtensionName IIS ` -VMName contosoVM ` -Publisher Microsoft.Compute ` -ExtensionType CustomScriptExtension ` -TypeHandlerVersion 1.4 ` -SettingString '{"commandToExecute":"powershell Add-WindowsFeature Web-Server; powershell Add-Content -Path \"C:\\inetpub\\wwwroot\\Default.htm\" -Value $($env:computername)"}' ` -Location EastUS
  3. Create a second virtual machine and install IIS using the steps that you previously completed. Use fabrikamVM for the virtual machine name and for the VMName setting of the Set-AzVMExtension cmdlet.

Add backend servers to backend pools

  1. Select All resources, and then select myAppGateway.
  2. Select Backend pools from the left menu.
  3. Select contosoPool.
  4. Under Targets, select Virtual machine from the drop-down list.
  5. Under VIRTUAL MACHINE and NETWORK INTERFACES, select the contosoVM virtual machine and it’s associated network interface from the drop-down lists.
  6. Add backend servers
  7. Select Save.
  8. Repeat to add the fabrikamVM and interface to the fabrikamPool.

Wait for the deployment to complete before proceeding to the next step.

Create a www A record in your domains

After the application gateway is created with its public IP address, you can get the IP address and use it to create an A record in your domains.

  1. Click All resources, and then click myAGPublicIPAddress.Record application gateway DNS address
  2. Copy the IP address and use it as the value for a new www A record in your domains.

Test the application gateway

  1. Enter your domain name into the address bar of your browser. Such as, contoso site in application gateway
  2. Change the address to your other domain and you should see something like the following example:Test fabrikam site in application gateway

Clean up resources

When you no longer need the resources that you created with the application gateway, remove the resource group. When you remove the resource group, you also remove the application gateway and all its related resources.

To remove the resource group:

  1. On the left menu of the Azure portal, select Resource groups.
  2. On the Resource groups page, search for myResourceGroupAG in the list, then select it.
  3. On the Resource group page, select Delete resource group.
  4. Enter myResourceGroupAG for TYPE THE RESOURCE GROUP NAME and then select Delete.

Working with NSG access and Azure Bastion

When working with Azure Bastion, you can use network security groups (NSGs).

In this diagram:

  • The Bastion host is deployed to the virtual network.
  • The user connects to the Azure portal using any HTML5 browser.
  • The user navigates to the Azure virtual machine to RDP/SSH.
  • Connect Integration – Single-click RDP/SSH session inside the browser
  • No public IP is required on the Azure VM.

Network security groups

This section shows you the network traffic between the user and Azure Bastion, and through to target VMs in your virtual network:


Azure Bastion is deployed specifically to AzureBastionSubnet.

  • Ingress Traffic:
    • Ingress Traffic from public internet: The Azure Bastion will create a public IP that needs port 443 enabled on the public IP for ingress traffic. Port 3389/22 are NOT required to be opened on the AzureBastionSubnet.
    • Ingress Traffic from Azure Bastion control plane: For control plane connectivity, enable port 443 inbound from GatewayManager service tag. This enables the control plane, that is, Gateway Manager to be able to talk to Azure Bastion.
  • Egress Traffic:
    • Egress Traffic to target VMs: Azure Bastion will reach the target VMs over private IP. The NSGs need to allow egress traffic to other target VM subnets for port 3389 and 22.
    • Egress Traffic to other public endpoints in Azure: Azure Bastion needs to be able to connect to various public endpoints within Azure (for example, for storing diagnostics logs and metering logs). For this reason, Azure Bastion needs outbound to 443 to AzureCloud service tag.

Target VM Subnet

This is the subnet that contains the target virtual machine that you want to RDP/SSH to.

  • Ingress Traffic from Azure Bastion: Azure Bastion will reach to the target VM over private IP. RDP/SSH ports (ports 3389/22 respectively) need to be opened on the target VM side over private IP. As a best practice, you can add the Azure Bastion Subnet IP address range in this rule to allow only Bastion to be able to open these ports on the target VMs in your target VM subnet.

The overall NSG would look like this:

WLC L3 Security Web Authentication

In this post we will see how to implement and configure WLC to support internal Webauth.
Web authentication is a Layer 3 security feature that causes the controller to not allow IP traffic (except DHCP and DNS -related packets) from a particular client until that client has correctly supplied a valid username and password.
Web authentication is mostly used to deploy a guest-access network. We must remember that web authentication does not provide data encryption. Webauth is an authentication method without encryption.

Web authentication can be performed using:
Default login window on the WLC
Modification of the default login window on the WLC
A customised login window that we download to the controller

In this post we will only see the starting 3 ways because I don’t have any external webserver.

Let’s start with Configuration of WLC. We will follow these steps:

Create a dynamic interface and fill all the required details.
Create a WLAN and apply the settings.
Configure WLC for Webauth (Internal).
Create local user for testing.

  1. Create a dynamic interface and fill all the required details.
    From WLC GUI, Choose Controller > Interface > New and fill the details:

    Interface Name: webauth
    Vlan Id: 10

    Click Apply
  2. Click on created Interface and then add the following details:
    Vlan Identifier-10
    IP Address—
    Netmask— (24 bits)
    Primary DHCP Server— Management IP for internal DHCP server)

    Click Apply

Click Apply to save the changes.

3. Create a WLAN and apply the settings:
From the WLC GUI, click WLAN in the menu at the top, and click New on the upper right side. This page will appear. Fill Profile name and SSID.

Click Apply.

A new WLANs > Edit window appears.
Check the status box to enable the WLAN.
From the Interface menu, select the name of the VLAN interface (webauth) that we created above.
Check the Broadcast SSID box

Click on Security Tab
Click Layer 2 security and set to None.

Click the Layer 3 tab
Check the Web Policy box and choose the Authentication option.

Then click Apply from upper right side to save changes.

4. Configure WLC for Webauth(Internal).
Internal web authentication is the by default web authentication type on WLCs. NO need to change the configuration.

5. Create local user for testing:
We can use 3 ways:
Local authentication, RADIUS server, LDAP server
In this post we will tests with Local authentication.

WLC GUI, choose Security > AAA > Local Net Users > New
Enter the username, password and WLAN profile from drop down box.

Assign to the correct WLAN Profile webauth

Click Apply
Here we created 2 users:
Username: Sandeep, Password: webauth123
Username: Sandeep1, Password: webauth12345

6. Verification
On Laptop Connect to Webauth SSID

7. Then a new browser will automatically open or we have to manually enter virtual interface IP from WLC : A Login window will appears
***In my WLC I have Virtual interface IP as

8. Enter the username and password of the Local Net User that we created:
Username: sandeep, Password: webauth123

9. Modification of the default login window on the WLC

  1. Login to WLC and modify the default login window by choosing Security > Web Auth > Web Login Page and click on Apply to save it. I changed the headline and message content.

2. Now connect to webauth WLAN. Login page will appear like this.

3. Enter the username and password.

10. A customized login window that we download to the controller

To download a customized login page, first start a TFTP/FTP server and put the login page in their root directory then login to WLC GUI, click on Commands and the details.

  1. Change the WLAN setting.
    WLAN > click on WLAN ID then Security > Layer3,
    Select the Over-ride Global Config box
    Choose Customized (Downloaded) webauth type from drop down box and select the login and login failure page then click apply.

2. Enter the username/Password and click on I agree with Policy Above.

Here is the complete Web Authentication Process(How it works: )

Privilege Level 15 with Cisco ISE

In this post, I’m going to show you how to assign privilege level 15 with Cisco ISE through RADIUS.

In addition, there are some other configuration required to be applied on the network devices themselves mainly to enable AAA and RADIUS authentication and authorisation. We will go only through the most relevant configuration parts in this post.

Let’s get started with ISE configuration. First we will create a new authorisation profile and we will call it R1_PRIV_15. The option we are after is called Web Authentication (Local Web Auth). This option allows ISE to push Cisco AV Pair attribute priv-lvl=15 inside the RADIUS packets to the network device:

Let’s enable this option, and verify what attributes will be associated with it:

As we can see, by enabling the Web Authentication (Local Web Auth) option we can see the Cisco AV Pair attribute priv-lvl=15 in the attributes details section.


Now let’s create a network device and configure its Device Type as IOS. The Device Type will be used in the top conditions on the policy set, we will see this later. We are going to call the network device Router-01:


Now let’s make sure we have the AD group LabAdmins already added:

As we can see the last group on the list is the LabAdmins group.


Now let’s create a new policy set and call it ADMIN_ACCESS_PRIV_15. As mentioned above this policy set will have some conditions on the top to match the traffic coming from the network device Router-01. The conditions are the Device Type which we configured as IOS, the RADIUS NAS Port Type which is Virtual in this case, and the RADIUS Service Type which is Login.

All these conditions should match for any SSH connection to Router-01. The point here is to make the policy set as much accurate as possible to match the exact traffic that should be served by itself. In the authentication section we will configure the authentication against the AD which is already joined to ISE.

And finally in the authorisation section we will configure a rule with a condition to check if the users are located in the AD group LabAdmins, if so, then the authorisation profile we created earlier which is called R1_PRIV_15 will be applied, instead if no match, the default authorisation rule will be applied which will deny accesses:


Now that we have applied all the required configuration on ISE, let’s move on and apply the required configuration on the Router-01. Mainly what we need is to enable AAA, configure the RADIUS authentication and authorisation, associating AAA authentication and authorisation method lists to the VTY lines, and restricting the accesses to the VTY lines for SSH only:

One thing worth mentioning here is that if we want to use the RADIUS Service Type in our conditions on ISE, then we need to enable radius-server attribute 6 on-for-login-auth, if not the RADIUS Service Type would be ignored in the RADIUS packets.


All the required configurations are now in place. Let’s do some tests by initiating SSH connection from the client, and trying to connect to the router with the admin1 username which is located in the AD group LabAdmins:

As we can see, we have successfully logged into the router, and we have been straightaway placed into privilege level 15. We can verify that by looking at the # symbol or by using the command show privilege. We can also verify the connected username by using the command show users:

Finally, let’s look at RADIUS debugs and see what are the most relevant attributes for our SSH connection that have been exchanged between Router-01 and ISE:

This wraps up this Privilege Level 15 with Cisco ISE post. I hope you enjoyed it, and as always, I would love to hear your feedback. Thanks for reading!

Cisco Catalyst 2960 switch IOS recovery

Sometimes in my lab happens that students delete IOS of the switch from its flash. Unfortunately switches does not have rommon to realize quick IOS recovery over tftp. Only one way is over Xmodem.

Cat 2960 switchIOS recovery

To speed up the process of the recovery we may setup Xmodem speed to higher rate as default 9600 bits:

Set the speed rate to 115200 baud on the switch prompt of the switch:

switch: set BAUD 115200

Of course we lose our console session and therefore we need to restart it with the correct speed settings. Then  we may realize the recovery.

Enter copy command:

copy xmodem: flash:filename

for our Cat2960-24TTL:

switch:copy xmodem: flash:c2960-lanbasek9-mz.122-52.SE.bin
Begin the Xmodem or Xmodem-1K transfer now...

and start sending of the file over console Xmodem software.

Recovery over HyperTerminal

Choose Transfer > Send File.







and than we choose as protocol the Xmodem and in filename click Browse and select the Cisco IOS image (.bin file) from the disk to be uploaded.












and click Send to send the file,


Recovery over Putty

Putty does not support Xmodem protocol, tears.

Final steps

To boot the new image that we just copied over with the Xmodem procedure issue the boot flash:filename command, as the example shows:

switch: boot flash:c2960-lanbasek9-mz.122-52.SE.bin

After the Xmodem recovery, we set the BAUD rate back to 9600. If the set BAUD 9600 command does not bring the baud rate to 9600,
issue the unset BAUD command in order to bring the baud rate to a default value of 9600 bps.



SFTP provides an alternative method for client authentication. It’s called SFTP public key
authentication. This method allows users to login to your SFTP service without entering a
password and is often employed for automated file transfers.

We will need to use SecureCRT to generate the RSA Private & Public keys. Private keys are
imported into client SFTP software for the connecting host and the Public key is imported
into the SFTP user directory on the FTP Server. You can also copy the Public Key directly into
the FTP server directory into the FTP user account. This will overall bind the FTP user to use
the RSA SSH Public key.


Generate and create Private & Public key using SecureCRT :

Use SecureCRT to create an RSA Private & Public key.

You will have the choice of storing your public key in a file that matches the IETF standard format) or in the OpenSSH format. If you are connecting to an OpenSSH server, you may want to use the OpenSSH format to simplify the process involved with setting up the remote server with your public-key file. If you are connecting to a VShell server, you can use either format since VShell accepts them both. The format (Vandyke does not work with VShell and it has been tried and test. OpenSSH works well.


Public– and Private-key files are placed in a local folder on the machine where the client application resides, usually with the filename “Identity“.



Using Filezilla Client to import the generated and save Private Key :

1. Goto file File, Click on “Site Manager”
2. Click on “New Site”
3. Fill these details :

Host :
Protocol : SFTP – SSH File Transfer Protocol
Logon Type : Key file
User : ftpuser
Key file : C:/Users/c_salmana\Documents\Identity

4. Click “OK” to save new site created.

FTPZilla-Site-ManagerFTPZilla-New Site



Server SFTP – VShell :

Configuring VShell Server to Recognize Your Public-Key File :

In order to use your public key you must transfer the public-key file created by the Key Generation
wizard to the individual user’s folder under the Publickey folder on the SSH2 server.

For example:

C:\Program files\VShell\Publickey\%User%\




This configuration needs to go under “configure sync” in order for it to sync over to the HA Pair.
Run “show switch-profile status” in order to check for “Profile-Revision” and have configuration
put on the hardware with the highest revision no. If the lower revision no. HA pair is used it will
not be accepted and will not sync configuration over to other HA pair.

This configuration allows the two Ethernet1221/1/1Ethernet1222/1/1 ports where the server is
directly connected with 2 seperate Nics, in order to provide load balancing using the LACP
etherchanneling technology.

The server is using a HP Network Config utility in order to team the network adapters together and
is put in auto mode in order to detect the LACP off the nexus switches.

The feature here it uses is “802.3ad Dynamic with Fault Tolerance“.
The can be seen on the HP utility under statistics and the Speed/Duplex as well as calculated throughput.


configure sync
switch-profile OSYS
interface port-channel205
description DERRRESYNCBC04
switchport access vlan 704
spanning-tree port type edge
interface Ethernet121/1/1
switchport access vlan 704
spanning-tree port type edge
channel-group 205 mode active
interface Ethernet122/1/1
switchport access vlan 704
spanning-tree port type edge
channel-group 205 mode active

Diagnostics :

show port-channel summary

205   Po205(SU)   Eth      LACP      Eth121/1/1(P)  Eth122/1/1(P)


show interface Eth121/1/1

Ethernet121/1/1 is up
Hardware: 100/1000 Ethernet, address: d4a0.2aff.c0c2 (bia d4a0.2aff.c0c2)
  MTU 1500 bytes, BW 1000000 Kbit, DLY 10 usec
  reliability 255/255, txload 1/255, rxload 1/255

show interface Eth122/1/1

Ethernet122/1/1 is up
  Hardware: 100/1000 Ethernet, address: 04da.d2d7.98c2 (bia 04da.d2d7.98c2)
  MTU 1500 bytes, BW 1000000 Kbit, DLY 10 usec
  reliability 255/255, txload 1/255, rxload 1/255

show interface port-channel 205

port-channel205 is up
 vPC Status: Up, vPC number: 262348
  Hardware: Port-Channel, address: d4a0.2aff.c0c2 (bia d4a0.2aff.c0c2)
  Description: DERRRESYNCBC04
  MTU 1500 bytes, BW 2000000 Kbit, DLY 10 usec
  reliability 255/255, txload 1/255, rxload 1/255


HP Teaming Tool


Setting up NetFlow Lite on the 2960x Switch

Step 1: create a flow record

flow record flows
match datalink mac source address input
match datalink mac destination address input
match ipv4 tos
match ipv4 protocol
match ipv4 source address
match ipv4 destination address
match transport source-port
match transport destination-port
collect transport tcp flags
collect interface input
collect flow sampler
collect counter bytes long
collect counter packets long
collect timestamp sys-uptime first
collect timestamp sys-uptime last

Step 2: create a flow exporter

flow exporter export-to-inside
description flexible NF v9
source Vlan98
transport udp 9996
template data timeout 60
!lets export some cool option templates
option interface-table
option exporter-stats
option sampler-table

Step 3: create a flow monitor

flow monitor nftest
record flows
exporter export-to-inside
cache timeout active 60
statistics packet protocol

Step 4 : Define a sampler :

sampler my-random-sampler
mode random 1 out-of 100

Step 5: Apply the flow monitor ‘nftest’ to each interface with the defined
sampler ‘my-random-sampler input” is for ingress

interface GigabitEthernet1/0/47
ip flow monitor nftest sampler my-random-sampler input
interface GigabitEthernet1/0/48
ip flow monitor nftest sampler my-random-sampler input

Diagnostics :

show flow exporter
show flow exporter export-to-inside statistics

Flow Exporter export-to-inside:
Packet send statistics (last cleared 00:13:03 ago):
Successfully sent: 0 (0 bytes)
Enqueued to process level: 18 (13924 bytes)

Client send statistics:
Client: Option options interface-table
Records added: 112
– sent: 112
Bytes added: 11200
– sent: 11200

Client: Option options exporter-statistics
Records added: 2
– sent: 2
Bytes added: 56
– sent: 56

Client: Option options sampler-table
Records added: 2
– sent: 2
Bytes added: 94
– sent: 94

Client: Flow Monitor nftest
Records added: 10
– sent: 10
Bytes added: 590
– sent: 590