What is a jumpbox? ^
A jumpbox is usually a controlled entry point into your environment. Let's assume your environment consists of a lot of virtual machines (VMs), and you want to be able to Remote Desktop Protocol (RDP) or Secure Shell (SSH) into them in case you had to. You could open up ports 3389 and 22 to your entire network so everybody can just remote in from your on-premises network. Or, better, you only allow remoting to one specific VM (your jumpbox) that sits inside a very controlled subnet and has a lot of monitoring and alerting configured. You then have to jump on from that VM to your other VMs; you can't go directly.
Jumpboxes are very common patterns—like Remote Desktop Gateways, for example, or sometimes they're just Windows VMs that have tools and scripts installed to execute maintenance tasks.
I propose the following pattern: a very small Linux VM that you tunnel your RDP connection through via SSH. Did I just say Linux, SSH, and RDP in one sentence? Yes. Yes, I did. Bear with me.
Deploying your Linux jump server ^
I am making the following assumptions here:
- you have an existing Azure VNet
- you have a subnet called jumpbox
- you have a local OS with an SSH client installed (Windows 10, for example)
Logged in to Azure and the Azure Cloud Shell, we will execute a few lines of Bash this time to deploy a small Ubuntu Server 16.04 VM. This will have an Azure VM extension installed that will help us log in to the VM securely using our Azure Active Directory (AD) credentials.
az vm create --image UbuntuLTS --generate-ssh-keys --admin-username 4soadmin --location australiaeast --name 4solinuxvm --resource-group 4soResourcegroup --size Standard_D3_v2 --vnet-name 4soNetwork --subnet jumpbox --nsg "" output table
This line will do a few things for us at the same time. It will deploy an Ubuntu server (image parameter), and it'll create SSH keys and a local admin user named 4soadmin, though we won't use either. The VM size will be Standard_D3_v2, and it will deploy the VM into the VNet 4soNetwork into its jumpbox subnet. The empty nsg parameter means the VM is supposed to inherit the network security group from the subnet. This process will take around three to four minutes. The result will be a few more resources in our resource group, including a running VM with a public IP we should be able to SSH to.
You can confirm the SSH connectivity with the following command (SSH is available in every Azure Cloud Shell)—just replace the public IP with your specific IP: ssh 4soadmin@<publicIP>
Cancel out of this for now by typing no.
The next step is to install the Azure AD (AAD) login extension for Linux to this VM, and this nice one-liner will do that for us:
az vm extension set --publisher Microsoft.Azure.ActiveDirectory.LinuxSSH name AADLoginForLinux --resource-group 4soResourcegroup --vm-name 4solinuxvm
This will again take a few minutes to complete.
Keys to the castle ^
Now instead of using SSH keys to log in to the jumpbox, we will use our AAD user. For this to work, our user requires special permissions. We can assign these permissions just like any other Azure permissions on the subscription, resource group, or even resource level. In this example, I will do it on the resource group.
Browse to the Access Control (IAM) tab and select Add role assignment. The role you are after is either Virtual Machine Administrator Login or Virtual Machine User Login. I am going to select the admin permission, but both work. Now select your AAD user, likely the one you are currently logged in as. Click Save and then head back to the Cloud Shell or any SSH client you have access to. Remember the public IP? Good.
In my case this is a multi-step process because I have multi-factor authentication (MFA) enabled on my AAD user (if you don't, go away, enable it, and then come back). I just follow the prompts, which eventually log me in to my Linux jumpbox with my AAD user credentials. This is a huge step when it comes to security. You can now control access to your VMs just like you control access to your Azure environment or even your Office 365. If you have MFA enforced, then this just works without you doing anything to deploy or configure MFA settings on that VM.
Windows to Linux to Windows ^
I promised you some OS jumping though. So here it comes. I have a Windows Server 2019 deployed in the same network without a public IP, and as I said, we don't want to open up RDP to the whole wide world, so we only allow it from our jumpboxes. The following SSH command will now enable an RDP tunnel through the AAD "secured" SSH connection to our jumpbox:
ssh -L 3388:<privateIPofTargetVM>:3389 <yourAadUser>@<publicIPofJumpbox> -N
This now again prompts me to follow the MFA process. Once that's done, the SSH tunnel will not show us the local Linux prompt but will just stay open. We can now launch our RDP client (for example, mstsc.exe) and open up a connection to localhost:3388. This will now start the authentication process to our Windows VM. We successfully launched an RDP session to a private IP on Azure via a Linux jump server using an SSH tunnel authenticated with our AAD credentials.