What is Azure Bastion
I'm not a big fan of maintaining VMs via IaaS nowadays, especially with the plethora of PaaS and SaaS solutions available. However, there are still a lot of applications and workloads out in the wild that require the use of VMs; and a lot of them require administrators to connect via remote desktop and perform point-and-click/scripting tasks on the VM itself. The idea of connecting using the remote desktop protocol (RDP) for a VM hosted in Azure (or any other cloud provider for that matter) over a public IP address, and typically over port 3389, would make anyone feel a little uneasy. You're basically giving hackers a freebie. That's where Azure Bastion comes in.
With Azure Bastion, you don't have to attach a public IP address to your VM. Instead, the bastion service sits at the perimeter of your virtual network and provides a funnel to access one or more virtual machines within a given virtual network.
Connecting from Windows Clients
Before I go any further, I want to point out that there is comprehensive documentation available on how to connect to an Azure VM from a Windows client, so I'll keep this short. Usually it's as simple as downloading an installing the Azure CLI, signing in via Azure CLI and then running a command like:
az network bastion rdp --name "<BastionName>" \
--resource-group "<ResourceGroupName>" \
--target-resource-id "<VMResourceId>"
But what about Linux and WSL users?
Connecting from WSL Clients
While it's easy to connect from a Windows client, connecting from a Linux/WSL client is a litte more involved. Note that there is some generic documentation on how to connect from a Linux client. However, it still leaves the reader wondering:
How do I RDP into a Windows VM on Azure from Linux/WSL?
In the steps below, I outline the method to connect to a Windows VM in Azure using Azure Bastion from WSL (Ubuntu 22.04) using KRDC. KRDC is a Linux compatible RDP client application.
To start, make sure you have the appropriate GPU driver installed. After that, for older installations, you will need to run wsl --update
to make sure you have the latest packages. For a fresh install of WSL, you can run wsl --install
in PowerShell or Command Prompt. For me this resulted in the installation of Ubuntu 22.04.
Once you've completed the above, you start installing KRDC by running the following:
sudo apt install krdc breeze-icon-theme
The breeze-icon-theme
is necessary to support the UI elements for KRDC. After you've completed installing KRDC, install Azure CLI by following the instructions in Install the Azure CLI on Linux. I followed the steps in Option 2 for which the final step after adding the signing key and repository is to run:
sudo apt-get install azure-cli
Now that we have both KRDC and Azure CLI installed within WSL, the next step is to sign-in and establish a tunnel. You'll first sign-in using the CLI:
az login –tenant <TenantID>
This will prompt you to open a browser and complete the authentication event with your work/school account. After that, just to be on the safe side, set the active subscription. This is the subscription in which the Azure Bastion service and the VMs have been provisioned. Run the following:
az account set --subscription <SubscriptionID>
Next, setup a tunnel to your VM using the following command:
az network bastion tunnel --name "<BastionName>" \
--resource-group "<ResourceGroupName>" \
--target-resource-id "<VMResourceId or VMSSInstanceResourceId>" \
--resource-port <TargetVMPort> --port <LocalMachinePort> &
You can find the values for BastionName
, ResourceGroupName
, VMResourceId
or VMSSInstanceResourceId
by browsing to the appropriate resource blades in the Azure Portal and extracting the necessary information. You may be wondering what should you plug in for TargetVMPort
and LocalMachinePort
.
If you setup your VMs and Azure Bastion Service using the defaults, the value for TargetVMPort
will be 3389. For LocalMachinePort
you can use any available port on WSL. For me, I just picked 3390.
The &
symbol at the end runs the process in the background so that it doesn't block your current shell. The output you should see is something like the following:
[1] 17174
Opening tunnel on port: 3390
Tunnel is ready, connect on port 3390
Ctrl + C to close
Note that the process ID for me was 17174
. To stop the process you can run:
kill -9 <ProcessID>
Once the tunnel is up and available, start the KRDC application by running.
krdc
This should launch a new window for the KRDC application.
Once the KRDC app is launched, do the following:
-
Change the Connect to value in the dropdown to rdp
-
Type in the parameters of the connection using the following format:
<VMAdministratorAccountName>@127.0.0.1:<LocalMachinePort>
VMAdministratorAccountName
is the username of the administrator account that was provisioned when you created the VM. TheLocalMachinePort
is the port that was specified earlier when creating the tunnel. For me this was port 3390. After you have specified the connection string, select Connect, i.e. the button with the icon select icon (>.) -
Configure elements of the connection such as resolution, keyboard, color etc. and select OK
-
Once you have completed configuring your connection, you may be prompted again for the admin username for the machine, based on whether you specified it in the connection string or not. Type in the username and select OK. Remember that this is the username of the admin account for the virtual machine provisioned in Azure.
-
Next, specify the password for the VM admin account and select OK.
And that's it, you're in! Congratulations, you have successfully connected to Azure Bastion using a Linux based RDP client within WSL.
Conclusion
The biggest thing to note is that when using Azure Bastion, if you are trying to RDP from Linux/WSL, you won't be able to use:
az network bastion rdp ...
Instead you will have to first setup a tunnel to your local machine, using:
az network bastion tunnel ...
And then you should be able to use the RDP client of your choice. In the example above, I used KRDC, but you can use other well know RDP clients too like TigerVNC or Remmina. Last but not least, you may be wondering why go through all this trouble? Why not just use a Windows client? Someone once told me that it was impossible to RDP via Azure Bastion using a Linux RDP client, and I had to prove a point 😅. Hopefully this post makes it very clear, that it is indeed possible. Thanks for stopping by and reading!