Part 2: Launch Resources into Azure VNet
Deploy two private Azure VMs and prove routing between VNet subnets.
Introduction
30 Second Summary
Private networks often split web-facing workloads from application workloads. Those labels make the design easier to understand, while the traffic between them still needs to be tested.
In this project, you will restore an Azure Virtual Network with two subnets. You will deploy two private Linux virtual machines across those subnets, connect through Azure Bastion Developer, and prove that Azure routes traffic between them by default.
What You'll Build
You will open a private browser-based terminal to your web-side VM, test the application-side VM, and watch four replies return from the other subnet.
By the end of this project, you'll have:
- A restored two-tier network where you can see two running Linux VMs using private addresses from different subnet ranges.
- A private browser-based SSH session that reaches a VM without assigning it a public IP address.
- A successful four-packet connectivity test that proves same-VNet routing works across the web and application subnets.
- Secret Mission: Reverse the traffic test from the application subnet and document the full two-way path.
Are there any prerequisites?
You need a Windows device with access to the Microsoft Azure portal. You also need an active Azure subscription with permission to create the networking and compute resources used in this project.
Before We Start
This is your moment to lock in what you are building before the hands-on work begins. You will turn a two-subnet Azure network into a private compute environment that proves why subnet segmentation needs security controls.
Restore the Lab Network
The network from Part 1 no longer exists. The two private virtual machines have nowhere to connect.
In this step, you'll use the Microsoft Azure portal to recreate the lab's Azure resource group. The finished Azure Virtual Network contains separate private address pools for web workloads and application workloads.
In this step, get ready to:
- Create NextWork-Networking in Central US.
- Recreate vnet-nextwork-lab with the web subnet.
- Add the application subnet with a non-overlapping range.
Create the resource group
A resource group is the container for this lab's Azure resources. It gives the restored network one named home.
- Search for Resource groups using the portal search bar.
- Select Resource groups from the results.
- Select + Create.
- Enter NextWork-Networking as the resource group name.
- Choose Central US as the region.
- Select Review + create.
- Select Create.
Good start. You'll see NextWork-Networking listed as a resource group in Central US.
Recreate the VNet and web subnet
The VNet defines the private address space available to its subnets. Its first subnet reserves 10.20.1.0/24 for the web-side VM.
- Search for Virtual networks using the portal search bar.
- Select Virtual networks from the results.
- Select + Create.
- Choose NextWork-Networking for the Resource group on the Basics tab.
- Enter vnet-nextwork-lab as the virtual network name.
- Choose Central US as the region.
The VNet identity is now set. Its address layout comes next.
- Select the Address space tab.
- Replace the VNet address space with 10.20.0.0/16.
- Select the initial subnet entry to edit it.
- Enter snet-web as the subnet name.
- Set the subnet address range to 10.20.1.0/24.
- Leave every optional subnet association unset.
- Select Save in the subnet editor.
How Do the Address Ranges Fit?
The VNet's 10.20.0.0/16 address space contains both planned subnet ranges. Each subnet must use a unique range inside that larger address space.
- Select Review + create.
- Select Create.
The restored VNet now exists in NextWork-Networking. Its first private address pool is ready for the web-side VM.
VNet Validation Not Passing?
- Check that the VNet address space is 10.20.0.0/16.
- Check that snet-web uses 10.20.1.0/24.
- Confirm that your Azure subscription permits resource creation in Central US.
Help me troubleshoot my VNet configuration.
Add the application subnet
The application-side VM needs its own private address pool. The 10.20.2.0/24 range fits inside the VNet without overlapping the web subnet.
- Search for vnet-nextwork-lab using the portal search bar.
- Select vnet-nextwork-lab from the results.
- Select Subnets from the VNet menu.
- Select + Subnet.
- Enter snet-app as the subnet name.
- Set the subnet address range to 10.20.2.0/24.
- Leave every optional subnet association unset.
- Select Add.
Before you compare the rows, consider whether both subnet ranges fit inside the VNet without overlapping.
- Confirm the snet-web row shows 10.20.1.0/24.
- Confirm the snet-app row shows 10.20.2.0/24.
You'll see two non-overlapping subnet ranges inside the VNet's 10.20.0.0/16 address space. Both subnets have their optional associations unset.
That's the network foundation restored. Each workload tier now has its own private address range.
Subnet Missing or Rejected?
- Return to + Subnet if snet-app does not appear in the list.
- Confirm that snet-app uses 10.20.2.0/24.
- Confirm that the new range does not match the 10.20.1.0/24 range used by snet-web.
Help me fix my application subnet.
Your two-subnet foundation is ready. Next, you'll place the first private Ubuntu VM inside snet-web.
Deploy the Web VM
Your restored Azure Virtual Network now contains two non-overlapping subnets. The web subnet still needs a running workload before its address range becomes a real endpoint.
In this step, you'll use Azure Virtual Machines to deploy vm-1 into snet-web. Azure assigns the VM a dynamic private IP address from that subnet while keeping it off the public Internet.
In this step, get ready to:
- Configure an Ubuntu VM with SSH public-key authentication.
- Connect its network interface to snet-web without a public IP address.
- Deploy the VM and record its assigned private IP address.
Configure the web-side VM
The VM configuration controls its operating system, capacity, and authentication method. These choices create the Linux workload that represents the web side of your network.
- Return to the Azure portal search bar from the VNet Subnets page.
- Enter Virtual machines in the search bar.
- Select Virtual machines from the search results.
- Select + Create.
- Select Azure virtual machine.
- Select NextWork-Networking as the resource group on the Basics tab.
- Name the virtual machine vm-1.
- Select Central US as the region.
The wizard now places vm-1 beside the VNet resources you restored earlier.
- Select No infrastructure redundancy required for the availability option.
- Select Standard as the security type.
- Select Ubuntu Server 22.04 LTS - x64 Gen2 as the image.
- Select x64 as the architecture.
- Select Standard_B2s as the size.
- Select SSH public key as the authentication type.
- Enter azureuser as the username.
- Select Generate new key pair as the SSH public key source.
The compute profile now matches the private Ubuntu workload required for this lab.
- Name the new key pair vm-1-key.
- Set Public inbound ports to None.
How Does SSH Key Access Work?
SSH uses a public key on the Linux VM to verify your identity. The matching private key stays on your Windows device.
This gives azureuser passwordless authentication without storing a reusable password on the VM.
🙋♀️ VM Choices Missing?
- Confirm that Central US remains selected before choosing the image.
- Return to the Basics tab if the wizard moved to another configuration page.
Help me resolve missing VM configuration choices in the Azure portal.
Place the VM in the web subnet
A network interface connects the VM to one subnet. Its subnet placement determines which private address range Azure uses for the VM.
- Select the Networking tab in the VM wizard.
- Select vnet-nextwork-lab as the virtual network.
- Select snet-web as the subnet.
- Set Public IP to None.
- Set NIC network security group to Advanced.
- Select Configure network security group.
- Create a network security group named nsg-lab in the configuration panel.
- Leave the Azure default security rules unchanged.
What Do These Network Choices Do?
- The snet-web selection places the VM in the 10.20.1.0/24 address range.
- The Public IP value None keeps the VM from receiving an Internet-facing address.
- The nsg-lab association attaches the network security group to the VM's network interface.
Creating the VM starts compute billing once its status reaches Running. The portal estimate lets you check the expected charge before you commit.
- Review the estimated price displayed by the portal.
You should see an estimated compute charge for Standard_B2s. Managed disk charges can also apply.
Can't Select the Web Subnet?
- Confirm that the selected virtual network is vnet-nextwork-lab.
- Confirm that the VM region is still Central US.
- Select snet-web after the virtual network list refreshes.
Help me troubleshoot why snet-web is unavailable in the vm-1 Networking tab.
Deploy and record the private endpoint
Azure validates the configuration before deploying vm-1. The key window supplies the private key file that authenticates your later connection.
Treat the downloaded file like a credential. Its matching public key can verify access without revealing the private key.
- Select Review + create.
- Confirm that the review summary names the VM vm-1.
- Confirm that the review summary lists the size as Standard_B2s.
- Confirm that the networking summary shows no public IP address.
- Select Create.
- Select Download private key and create resource in the key window.
The deployment can take several minutes while Azure creates the VM and its supporting resources. The progress screen shows when the deployment is complete.
- Confirm in your browser's download panel that vm-1-key.pem is saved in the Windows Downloads folder.
Before you check the result, which private address prefix do you expect vm-1 to receive from snet-web?
- Open vm-1 after the portal reports that deployment is complete.
You should see the VM status as Running on Overview. Its private IP address should begin with 10.20.1..
The public IP field should show that no address is assigned.
- Record the private endpoint here: your vm-1 private IP address.
VM Not Showing as Running?
- Refresh the Overview page if the deployment just completed.
- Confirm that snet-web is selected if the private IP does not begin with 10.20.1..
- Review the deployment details if Azure reports that a resource failed.
Help me diagnose why vm-1 is not running with a 10.20.1 private IP address.
You now have a private web-side VM running inside snet-web. Next, you'll add an application-side VM in the other subnet.
Deploy the Application VM
Your web-side VM is running in snet-web. The application tier now needs its own private workload in snet-app.
You will use Azure Virtual Machines to create that second workload with the same compute profile as vm-1. Its private design also tests whether your Windows device can find a destination for direct Internet SSH.
In this step, get ready to:
- Configure vm-2 as the application-side Ubuntu VM.
- Attach vm-2 to snet-app through nsg-lab.
- Inspect the direct Internet SSH prerequisites for the private VMs.
Configure the application VM
Matching vm-1's compute profile keeps the two workloads consistent. Subnet placement becomes the difference you can test later.
- Use the top search bar in the Azure portal from earlier to search for Virtual machines.
- Select Virtual machines from the search results.
- Select + Create.
- Select Azure virtual machine.
- Set Resource group to NextWork-Networking.
- Enter vm-2 for the Virtual machine name.
- Set Region to Central US.
- Select No infrastructure redundancy required for the availability option.
Why Use the Same Location?
The resource group keeps the lab resources together. The shared region matches the location of vnet-nextwork-lab.
- Set Security type to Standard.
- Select Ubuntu Server 22.04 LTS - x64 Gen2 as the image.
- Set the architecture to x64.
- Select Standard_B2s as the VM size.
Why Match vm-1?
Using the same image and size removes compute differences from the later connectivity test. The subnet ranges become the detail that matters.
SSH public-key authentication places the public key on the VM. You keep the matching private key on your Windows device.
- Choose SSH public key for the authentication type.
- Enter azureuser as the username.
- Choose Generate new key pair.
- Name the generated key pair vm-2-key.
- Set Public inbound ports to None.
Place the VM in the application subnet
Each VM receives a network interface that joins one subnet in an Azure Virtual Network. Its subnet supplies a dynamic private IP address while a network security group controls traffic.
- Select Networking in the VM creation wizard.
- Select vnet-nextwork-lab as the virtual network.
- Select snet-app as the subnet.
- Set Public IP to None.
- Set NIC network security group to Advanced.
- Select nsg-lab as the existing network security group.
- Leave the default rules in nsg-lab unchanged.
Before You Deploy
Creating vm-2 starts another billed compute resource once it runs. The portal estimate lets you review the expected charge before you commit.
Azure displays a key download window during creation. Keep the downloaded file in the Windows Downloads folder because the private key stays on your device.
Deployment usually takes a few minutes while Azure creates the VM resources.
- Review the estimated price displayed by the portal.
- Select Review + create.
- Select Create.
- Select Download private key and create resource in the key window.
- Keep vm-2-key.pem in the Windows Downloads folder.
- Wait for the deployment to finish.
That is the second workload created. vm-2 now has its own VM resource and SSH key.
- Use the Azure portal search bar to search for Virtual machines.
- Select Virtual machines from the search results.
- Select vm-2.
- Confirm the VM status shows Running.
- Confirm the Private IP address starts with 10.20.2..
- Confirm no Public IP address is assigned.
Why Does the Address Start With 10.20.2?
The network interface receives an address from 10.20.2.0/24 because it belongs to snet-app. This confirms the application VM landed in the intended subnet.
Deployment Not Completing?
Review the portal message for the field that needs attention. Confirm that the selected region matches the existing virtual network.
If the private IP begins with the wrong subnet range, check which subnet appears in the VM's networking details.
Help me troubleshoot the vm-2 deployment issue.
Inspect the private management limitation
A private VM needs a network path that reaches its private address. The connection check now tests whether your Windows device has that path.
Before you inspect the connection options, predict whether direct Internet SSH can identify a destination for vm-1.
- Return to vm-1 Overview from earlier.
- Select Networking in the vm-1 resource menu.
- Check whether a public IP resource is attached to the network interface.
- Select Connect for vm-1.
- Review the Native SSH prerequisites.
You'll find that vm-1 has no public IP address for direct Internet SSH from Windows. This shortfall is intentional because both VMs were designed as private workloads.
Before the final check, predict which subnet range each VM's private address should match.
- Return to vm-1 Overview.
- Confirm the VM status shows Running.
- Confirm the private IP address starts with 10.20.1..
- Confirm no public IP address is assigned.
vm-1 remains the private web-side endpoint in snet-web.
- Return to the Virtual machines list.
- Select vm-2.
- Confirm the VM status shows Running.
- Confirm the private IP address starts with 10.20.2..
- Confirm no public IP address is assigned.
- Keep both VMs running for the next step.
You now have two running Ubuntu VMs in separate subnet ranges with no public IP addresses. Next up, you'll use Azure Bastion Developer to create the private management path that direct Internet SSH could not provide.
Connect Through Bastion
Your VMs are running. Your Windows device still has no public destination for direct Internet SSH.
Azure Bastion Developer adds a browser-based SSH path from the Microsoft Azure portal to a VM inside your Azure Virtual Network. This keeps vm-1 private while giving you an interactive management session.
In this step, get ready to:
- Open Bastion Developer from the connection page for vm-1.
- Authenticate with azureuser and vm-1-key.pem.
- Verify that the private browser session reaches vm-1.
Connect with Bastion Developer
Bastion Developer starts from the connection page for your existing VM. It uses shared Azure infrastructure, so it does not need an AzureBastionSubnet or a public IP address.
Why Use the VM Connection Page?
The VM connection page activates Bastion Developer when you connect. The separate Bastion creation form configures a dedicated host instead.
The shared Developer service fits this lab because it supports one private VM connection at no extra cost.
- Use the Azure portal search bar to search for vm-1.
- Select vm-1 from the search results.
- Select Connect in the VM menu.
- Select Bastion.
Avoid the Paid Deployment Page
Do not select Deploy Bastion or Configure manually. Those options create a dedicated Bastion host that can incur hourly charges.
Leave any page that only offers Basic, Standard, or Premium tiers.
The Bastion pane asks for the Linux account and private key that match vm-1. Your private key stays on your Windows device during this authentication step.
- Set Authentication Type to SSH Private Key from Local File.
- Enter azureuser as the username.
- Select vm-1-key.pem from the Windows Downloads folder.
Developer Connection Form Missing?
- Confirm that vm-1 is in Central US.
- Return to vm-1 and open Connect, then Bastion.
- Stop if the page only offers paid Bastion tiers.
Help me find the Bastion Developer connection form for vm-1.
Confirm the private connection
Selecting Connect automatically deploys Bastion Developer through Azure's shared infrastructure. The first deployment normally completes in seconds before the browser terminal opens.
Before you select Connect, do you expect a browser terminal to reach vm-1 even though the VM has no public IP address?
- Select Connect.
- Allow the new browser tab if your browser asks for permission.
You should see an authenticated terminal prompt containing azureuser@vm-1.
That closes the access gap. You now have an authenticated shell on vm-1 without exposing it through a public IP address.
Bastion Session Not Opening?
- Confirm that the selected local key is vm-1-key.pem.
- Confirm that the username remains azureuser.
- Allow the Bastion browser tab if your browser blocked it.
Help me diagnose why my Bastion browser session to vm-1 is not opening.
- Return to the original Azure portal tab.
- Return to the Overview page for vm-1.
- Check the VM status.
- Check the public IP address assignment.
You should see that vm-1 remains Running. You should also see that no public IP address is assigned.
- Return to the Bastion terminal tab.
- Keep the Bastion session open for the connectivity test.
The terminal should still show a prompt containing azureuser@vm-1.
Your private management path is live. Next, you will use this terminal to test traffic from snet-web to snet-app.
Test Cross-Subnet Connectivity
Your browser-based SSH session through Azure Bastion Developer gives you a private path into vm-1. Now you can test whether that VM can reach vm-2 across a subnet boundary.
Separate subnets can look isolated. This step reveals how an Azure Virtual Network routes traffic between its subnets unless a security control blocks the path.
In this step, get ready to:
- Confirm that the two VMs occupy different subnet ranges.
- Run a four-packet connectivity test from vm-1 to vm-2.
- Capture the successful result as evidence of cross-subnet routing.
Confirm the subnet placements
A valid cross-subnet test needs endpoints in different address ranges. The VM details confirm that your source belongs to snet-web while your destination belongs to snet-app.
- Switch back to the Microsoft Azure portal tab from earlier.
- Select vm-1 in NextWork-Networking.
- Select Networking from the VM menu.
The private IP address for vm-1 should begin with 10.20.1.. This prefix places the source inside snet-web.
- Return to NextWork-Networking.
- Select vm-2.
- Select Networking from the VM menu.
The private IP address for vm-2 should begin with 10.20.2.. This prefix places the destination inside snet-app.
- Switch back to the azureuser@vm-1 Bastion terminal from earlier.
Run the connectivity test
The ping command checks whether one host receives replies from another. Limiting the test to four packets creates a compact result that is easy to verify.
Before you run the test, consider whether the subnet boundary should block the packets.
- Send four packets from vm-1 to vm-2 by running this command in the open Bastion terminal:
ping -c 4 vm-2
What does this command test?
- The ping command sends test packets to another host.
- The -c 4 option limits the test to four packets.
- The vm-2 hostname resolves to the target VM's dynamic private address.
- Identify the resolved 10.20.2.* private address in the output.
- Count four reply lines from the destination.
- Confirm 0% packet loss in the summary.
That's the key result proven. Traffic can travel from snet-web to snet-app inside the shared VNet.
No replies from vm-2?
- Confirm that vm-2 still shows Running in the Azure portal.
- Check that the destination in the command is spelled exactly vm-2.
- Return to the authenticated vm-1 Bastion session before trying the command again.
Help me diagnose the failed connectivity test.
Interpret the result
Azure supplies a system route for traffic inside the shared 10.20.0.0/16 address space. That route permits traffic between the VNet's subnet prefixes by default.
Separate subnets organize workloads into distinct address ranges. They do not create a default security boundary.
The successful test shows that the unchanged default rules in nsg-lab permit this web-to-application path.
- Keep the successful output visible in the azureuser@vm-1 terminal.
- Capture the complete terminal output using the screenshot tool on your Windows device.
- Check that the screenshot shows the 10.20.2.* destination.
- Check that the screenshot shows four replies.
- Check that the screenshot shows 0% packet loss.
- Save the screenshot as your vm-1-to-vm-2 connectivity evidence.
You have turned the network design into observable proof. Your screenshot now records successful private traffic from the web subnet to the application subnet.
Secret mission
Prove the Reverse Path
The forward ping proved that vm-1 can reach vm-2. Switch the private management session to vm-2. Document the return path to prove same-VNet connectivity works in both directions.
Clean Up Your Resources
Clean Up Your Resources
Choose whether to keep this Azure lab available, pause its compute, or remove it completely. The two running VMs cost about $0.0998 USD/hour in combined compute charges, plus managed disk and transaction charges.
Cost warning
Azure bills instance usage while vm-1 and vm-2 remain Running. Stopping them from inside Ubuntu does not deallocate them.
Managed disks can continue to incur charges after VM deallocation. Azure Bastion Developer has no hourly charge.
Resources you used:
- Resource group NextWork-Networking in Central US.
- Azure Virtual Network vnet-nextwork-lab with subnets snet-web and snet-app.
- Private Azure Virtual Machines vm-1 and vm-2 with their network interfaces and OS managed disks.
- Network Security Group nsg-lab with its default rules unchanged.
- SSH key resources vm-1-key and vm-2-key with their downloaded private key files.
- Azure Bastion Developer resource bastion-dev attached to vnet-nextwork-lab.
Keep everything running
No action is needed. Choose this option if you plan to continue directly to Part 3 with the same network and VMs.
- Keep vm-1 and vm-2 running for immediate access in the next project.
- Expect about $0.0998 USD/hour in combined VM compute charges while both VMs remain running.
- Keep vm-1-key.pem and vm-2-key.pem secured in your Windows Downloads folder.
- Keep your forward-path and reverse-path screenshots as baseline evidence for Part 3.
Pause - I'll come back to this later
Deallocate both VMs to stop instance compute billing while preserving the network for later. Managed disks and some networking resources can continue to incur charges.
- Close the open browser-based SSH session to vm-2.
- Return to vm-1 in the Azure portal.
- Select Stop.
- Wait until the status shows Stopped (deallocated).
- Return to vm-2 in the Azure portal.
- Select Stop.
- Wait until the status shows Stopped (deallocated).
Once both VM pages show Stopped (deallocated), Azure no longer bills their instance usage. Your managed disks remain available for your return.
Delete - I don't want to use this again
Remove the full Azure lab to stop project resources from remaining in your subscription. This option also removes the environment needed for Part 3.
- Close the open browser-based SSH session to vm-2.
- Return to the NextWork-Networking resource group in the Azure portal.
- Select Delete resource group.
- Enter NextWork-Networking when Azure asks you to confirm the resource group name.
- Confirm the deletion.
- Wait for Azure to finish removing the resource group.
When deletion finishes, you should no longer see NextWork-Networking in your resource group list. This confirms the VNet, subnets, VMs, network interfaces, managed disks, NSG, SSH key resources, and Bastion resource are gone.
- Permanently delete vm-1-key.pem from your Windows Downloads folder.
- Permanently delete vm-2-key.pem from your Windows Downloads folder.
Your saved connectivity screenshots can remain as project evidence because they contain no private key material.
Nice Work!
Nice Work!
Excellent work! You've built a two-tier private environment with an Azure Virtual Network and two Ubuntu virtual machines. Your connectivity evidence proves that traffic can travel between separate subnets through Azure's default system routing.
You've learned how to:
- Restore a two-subnet network foundation with snet-web at 10.20.1.0/24 and snet-app at 10.20.2.0/24.
- Deploy private Linux VMs into different subnet ranges. You also observed how each network interface receives a dynamic private IP address.
- Reach private-only VMs through Azure Bastion Developer without adding public IP addresses. You proved same-VNet routing with four successful replies and 0% packet loss.
- Secret Mission: Prove the reverse path from vm-2 to vm-1. You annotated the source subnet, destination subnet, private address ranges, and shared VNet system route.
Ready to quiz yourself?