How to access an ARM Azure virtual machine from Internet

Hi readers,

Lack of documentation ! This is my starting point for this post. I’m a regular answerer of the Microsoft TechNet forum, and I noticed a repeatable question, or an issue related to the same subject : How to access an Azure Resource Manager virtual machine (RDP, SSH, publish a port…). To avoid repeating the same answer each time I decided to write a post instead. This way, I can just do the  easy Copy/paste (Ctrl c/ Ctrl v)

So what is the goal of this post:

  1. Understand the ways you can access a virtual machine in Microsoft Azure (Azure Service Management vs Azure resource Manager)
  2. Show you how to implement it for Azure Resource Manager virtual machines
  3. Show you how to assign static Public IP addresses to Azure VMs

Before continuing : In this post, I will only talk about accessing an Azure virtual machine from the public network, internet. Accessing a VM from a private network (S2S VPN, P2S VPN, ExpressRoute…) is out of the scope of this reading as it’s considered as an internal access, just like you access a server from your corporate network (The VM is directly exposed to you unless you have a firewall or an NSG)

Suppose you created an virtual machine on Azure. Now you want to access it and you wonder how it’s happening.

I- Azure Service Management (Classic)

With the classic deployment model (which is accessible from both the classic portal and the new portal), when you create a virtual machine, you are forced to deploy it within a cloud service. A cloud service is a container of your VM or VMs like depicted on Picture 1 (You can deploy multiple VMs within the same cloud service).

CS

Picture 1 : VMs and Cloud Services

 

There are two ways to access a virtual machine in this case (Picture 2) :

  1. We can access a VM by assigning a Public IP address to the Virtual Machine. This IP called PIP belongs to the Virtual Machine  itself
  2. We can access a VM by accessing it through a public IP address assigned to the Cloud Service.This IP called VIP belongs to the Cloud Service and can be used to access all the VMs within the Cloud Service

CS-IP-PIP

Picture 2 : VMs, Cloud Services, VIP and PIP

What is the difference between accessing a VM using a PIP or the VIP ?

Using the PIP

It’s clear, the PIP belongs to the Virtual Machine itself, so when you try to access a VM using this IP, your packets will land directly on the VM (Picture 3, Left). The only obstacle between you and the VM is :

  • The VM’s firewall : you have to allow the inbound traffic for the ports you want to access the VM from (Example : 3389 for RDP or 21 for SSH or an application port)
  • A Network Security Group applied to the VM or to the subnet : You have to allow the inbound traffic for the ports wherever you are using NSG
  • ACL : If you are using ACLs, you have to allow the access to the VM also

–> If you are using nothing of the things above, then you can access the VM on any opened port. Look to this link to know how to assign a Public IP address (PIP also called ILPIP) to an Azure VM

Using the VIP

As explained above, the VIP belongs to the Cloud Service, so if you want to access a VM using the VIP, you have to tell Azure about your need. You have to tell Azure for example that if it receives a packet on the VIPx on port Y, it have to redirect it to a VM  (which belongs the cloud service) on port Z. It’s simply NAT. This is achieved using VM Endpoints (Picture 3, right). Like the link explains, you have to configure a VM endpoint each time you want to access a VM on a specific port using it’s VIP. The VM endpoint is simply a NAT rule that Azure adds to the cloud service’s configuration. It’s important to keep in mind that VM endpoints are configured at the VM level but they are related to the cloud service’s Virtual IP (VIP). As you can notice, you cannot access two VMs belonging to the same Cloud Service using the same external port.

PS : Do not forget that the Internal port used when configuring an Endpoint must be allowed (if any) at the VM’s firewall level, NSG or ACL.

 

Access VIP PIP

Picture 3 : VMs, Cloud Services, VIP and PIP

II- Azure Resource Manager

With Azure Resource Manager, things changed. And the big change concerning us is : No more Cloud Services. So the question is how to access a VM in this case!

There are two ways to access a virtual machine in the ARM case (Picture 4 ) :

  1. We can access a VM by assigning a Public IP address to the Virtual Machine. This IP called PIP belongs to the Virtual Machine  itself*. It’s the same thing than the Classic mode
  2. We can access a VM by using  NAT rules added to a Load Balancer.  This is new in comparison with the classic mode which require an explanation.

* The VM’s network configuration in Azure Resource Manager differs from the classic mode.  The network configuration for a classic VM is hold by the VM itself, which means for our case that the Public IP is hold by the VM. In ARM, things changed. For each VM’s object, a virtual NIC is created and then attached to the VM. This VNIC will hold the Network configuration like the VNET/Subnet, the internal IP and the Public IP address. A VM with multiple addresses (like A3 VMs) will have multiple VNICs attached.

ARM

Picture 4 : Access an ARM VM (PIP or Azure LB)

II.1- Using the Public IP address

You can assign a Public IP address to the VM’s VNIC. You can choose to create a new Public IP address or use an existing one.

Via the Azure Portal

Go to the Azure Portal –> Virtual Machines –> Your VM –> All Settings –> Network Interfaces –> VNIC –> All Settings –> IP Addresses –> Public Ip Address Settings. Click on Enable and choose to create or use an existing IP address

0746

Via the Azure Powershell

The following Azure Powershell commands will allow you to create a Public IP Address and assign it the first VM’s VNIC


Function Create-PublicIP ($IPName, $RG, $Region, $AllocMethod, $DomainLabel)

        {

        $publicIP = New-AzureRmPublicIpAddress -Name $IPName -ResourceGroupName $RG -Location $Region –AllocationMethod $AllocMethod -DomainNameLabel $DomainLabel.ToLower()

        return $publicIP

        }

$ELBPublicIPName = Read-host ‘Public IP Address Name’
    $AllocMethod = Read-host ‘Allocation Method (Static/Dynamic)’
    $DomainLabel = Read-host ‘Domain Label’
    $RG = Read-host ‘Resource Group’
    $Region = Read-host ‘Region/Location’
    $VMName = Read-host ‘VM Name’

     # 1- Create the Public IP for the Load balancer

    $ELBPublicIP = Create-PublicIP -IPName $ELBPublicIPName -RG $RG -Region $Region -AllocMethod $AllocMethod -DomainLabel $DomainLabel

    #2- Assign the IP to the VM first IP
    $VM = Get-AzureRmVM | where {$_.Name -eq $VMname }
    $VNIC = Get-AzureRmNetworkInterface | where {$_.Id -eq $VM.NetworkInterfaceIDs[0] }
    $EIPPublicIP = Get-AzureRmPublicIpAddress | where {$_.Name -eq $EIPName}

    $VNIC.IpConfigurations[0].PublicIPAddress = $ELBPublicIP
    Set-AzureRmNetworkInterface -NetworkInterface $VNIC


II.2- Using the Azure Load Balancer

Why it’s so complicated, and why do we need to create a Load Balancer and then create NAT rules :/

To be honest, it’s not complicated and Microsoft did not change anything, they just change  names, and give you more customization. We have to thank them for this. Let me explain the steps to access a VM using this method:

  1. Create the Azure Load Balancer
  2. Create a Backend pool and associate it with the Load Balancer
  3. Create a NAT rule
  4. Associate a NAT rule to a VM’s NIC (VNIC)

II.2.1- Create the Azure Load Balancer

Microsoft provides at no extra cost the ability to deploy Load Balancers which provide load balancing features. More about the Azure Load Balancer here. Keep in mind that he goal of deploying a Load Balancer in our case is to create NAT rules and not load balancing rules. In addition, in our case, we want to create an Internet Facing Load Balancer because we aim to access internal resources from the public internet. This link is the official Microsoft link of how to create an Internet facing Load Balancer. https://azure.microsoft.com/en-us/documentation/articles/load-balancer-get-started-internet-arm-ps/

The following are the steps to create an Internet Facing Load Balancer:

  1. Create a Public IP address resource (If not already created) : In this step, you will create a Public IP address Resource. You can choose between a Static IP (Reserved) or a Dynamic IP, which is subject to change over time. This Public IP will be used to access the Load Balancer, and it’s used on the next step
  2. Create the Front End IP : The Front End IP is the frontal IP for the load balancer. It’s a configuration to which we will associate the Public IP address
  3. Create the Load Balancer resource

The following is a Powershell code to create an Internet Facing LB


#Variables

$IPName : The Name for the Public IP resource

$RG : The resource Group name where the resources will be created

$Region : Thee location where to deploy the resource (north europe…)

$AllocMethod : The IP allocation method, there are two possible values : Dynamic or Static

$DomainLabel : The DNS prefix for the Public IP. The public IP address will have a  DNS record associated to it of the form : $domainlabel.region.cloudapp.azure.com

$FEName : The name of the Front End configuration

$ELBName : The name of the Load Balancer resource

# 1- Create the Public IP for the Load balancer

   $PublicIP = New-AzureRmPublicIpAddress -Name $IPName -ResourceGroupName $RG -Location $Region –AllocationMethod $AllocMethod -DomainNameLabel $DomainLabel.ToLower()

   # 2- Create the front End IP for the Load balancer using the created Public IP

   $FEConfig =  New-AzureRmLoadBalancerFrontendIpConfig -Name $FEName -PublicIpAddress $PublicIP

   # 3- Create LB
   $ELB = New-AzureRmLoadBalancer -ResourceGroupName $RG -Name $ELBName -Location $Region -FrontendIpConfiguration $FEConfig

 

II.2.2- Create the BackEnd Address pool

The Backend Address pool will contain the target objects (IPs) targeted by the Load Balancer. If you want to redirect (via NAT) a packet using the Load Balancer to a VM , The VM’s NIC should be part of Backend pool

The following is a Powershell code to create a Backend Address Pool


#Variables

$BEPoolName : The name of the Backend Address Pool

1# Create the Backend Address Pool

New-AzureRmLoadBalancerBackendAddressPoolConfig -Name $BEPoolName

2# Add the Backend Address pool to the created Load Balancer

Add-AzureRmLoadBalancerBackendAddressPoolConfig -LoadBalancer $ELB -Name $BEPoolName |  Set-AzureRmLoadBalancer


 

II.2.3- Create a NAT rule

A NAT rule is a very simple and logic rule :

  • Frontal Port or External port : This is the port on which the Load Balancer will listen to incoming requests. It’s the port you will send packets to, when you are connecting from the external.
  • Frontal IP : This is the IP (Public IP) on which the Load Balancer will listen. In fact, this is mandatory since a Load Balancer can have multiple Front End IPs. This is the FrontEnd configuration of the Load Balancer
  • Protcol : tcp or udp
  • Backend Port : This is the Private port on which the service is really listening, and to which the Load Balancer will redirect the traffic

The following is a Powershell code to create a NAT rule and associate it to the Load Balancer


#Variables

$NATName : The name of the NAT rule

$Prot : tcp or udp

$FEport : The frontal port o the public port

$BEPort : The Backend port or the Private port

# Create and add a NAT rule to the Load Balancer

$ELB | Add-AzureRmLoadBalancerInboundNatRuleConfig -Name $NATName -FrontendIpConfiguration $FEconfig -FrontendPort $FEport  -BackendPort $BEPort -Protocol $Prot

$ELB | Set-AzureRmLoadBalancer


II.2.4- Associate a VNIC with a NAT rule

This is the final step. You can notice that during all the previous step, the Backend IP was not set. The Backend IP is the IP of the VM. With Azure Resource Manager, it actually means the VNIC.

The following is a Powershell code to get a VNIC resource, add it to the Backend address pool and add it as a target of the NAT rule


$VNIC = Get-AzureRmNetworkInterface –id ‘VNIC id’

$VNIC.IpConfigurations[0].LoadBalancerBackendAddressPools = $BEPool

$VNIC.IpConfigurations[0].LoadBalancerInboundNatRules = $NATRule

$SetVNIC = Set-AzureRmNetworkInterface -NetworkInterface $VNIC


BONUS

As a BONUS, I uploaded here a ‘preview’ script containing all the previous commands. This script is interactive, and will let you create an End to End NAT rule using an Azure Load Balancer or assign a Public IP address to a VM’s NIC

Download it and just run it –> https://gallery.technet.microsoft.com/Create-a-NAT-rule-on-Azure-6e48dd84

NB : Please, read the release note of the script

15 thoughts on “How to access an ARM Azure virtual machine from Internet

  1. Do you have more details on the NAT that needs to be configured. I am trying to use the ARM Portal to setup LB but running into some issue. I have most of it setup but when I try to web to the VIP I am seeing on the backend VM’s packets coming in and going out to IP 168.63.129.16. Not sure what to change.

    thanks

  2. Tons of Thank you Samir for this post. I was struggling to connect to vm from ARM from 10 days but haven’t found any post. At last i got your post. Once again thank you thank you thank you. Keep posting more information on Azure.

  3. HI Samir,
    I followed the steps given in ( II.1- Using the Public IP address ) and able to RDP the VM from Home Internet. I need to try from Script. Now I am facing same issue from Corporate network. As corporate network block few ports on security purpose, its not allowing me to RDP using 3389 port, I tried to RDP the VM by changing the port to 443 and 80 @ Inbound rules of NSG, but no luck. It would be great if you can throw some light on this.

  4. Hi,
    Great, i totally understand your issue. As described on this post, there are two conditions to successfully connect to a VM : Allow the connection (Public IP or NAT Rule) + Security (Windows Firewall and/or NSG).
    In your case, you are using the Public IP, so the packets land directly on the VM on port 3386. If you want to access the VM on another port than 3386 you need to change the port at the Windows Level ( 80 instead of 3386). Do not forget to allow 80 on the Windows Firewall and NSG if you applied NSG on this VM.
    https://support.microsoft.com/en-us/kb/306759

    Bjt I would recommend that you create a NAT rule (80 –> your VM 3386). This way you can at any time change easily the external port (80, 50, 60….) and not modify the system default ports

  5. Alright Samir Thank you for the post. As of now i created Point to Site Network and RDP to VM’s. Will work on your solution as well and share my experience.

  6. Hello,

    I want to setup a simple IIS Web Server with multiple web applications in an Azure VM.

    The Web Server will talk to SQL Server VM in same Vnet but in different subnet.

    I want multiple Public IP addresses to be mapped to the Web Server VM to run multiple SSL and Non-SSL websites.

    I have created 10 Public IP addresses in New Azure Portal, but I am unable to find a way to map them all to the single Web Server VM.

    I went through this documentation of Azure Load Balancer with Frontend Pool and Backend Pool and found this to be the closest solution for my requirement.

    Requesting someone to tell if this (Azure Load Balancer) is the right solution for my use case or some other simple solution is there which I may have overlooked.

    Thanks,
    Pankaj

  7. I just had to put a note on to say thank-you so much for publishing this article – I’ve spent the last few days trying to wrap my brain around the load-balancer setup in Azure RM and finding the lack of documentation truly frustrating!

    Last section is the real gem here – Every other article I have read has not explained how you associate the VM with the NAT rules – so it was a breath of fresh air to finally find an article details how it all ties together.

    Thank you so much!

    Martin

  8. Hi,

    I’m trying to give acces to all my Azure VMs (in RM) through RDP but I need to change the public port to Access each VM. So, for example I need to acces each VM through port 4000 but this port redirect to 3389 on each VM.

    I undertand that the only way is with LB and NAT rules but, If I need the same 4000 port for each VM, do I need to créate one LB for each VM? Or is posible with only one?

    Thanks in advance.

  9. It’s a pity you don’t have a donate button! I’d without a doubt
    donate to this superb blog! I guess for now i’ll settle for
    book-marking and adding your RSS feed to my Google account.
    I look forward to brand new updates and will talk about this blog with my Facebook
    group. Talk soon!

Leave a reply to Samir Farhat Cancel reply