# AZ-104 Lab 2: Secure Azure Networking –Hands-On Walkthrough

In this lab, we’ll build a secure Azure network from scratch using the Azure Portal.  
You’ll deploy virtual networks, subnets, network security groups, VNet peering, and Azure Bastion for secure RDP access.

This directly maps to **AZ-104 exam objectives** under *“Manage Virtual Networking.”*

## Lab Objectives

* Create and configure Azure VNets and subnets
    
* Apply NSGs for subnet-level security
    
* Connect VNets using peering
    
* Use Azure Bastion for secure, no-public-IP access
    

## What You’ll Need

* Active Azure subscription
    
* RDP client or web Bastion access
    
* Your **public IP** (for temporary RDP rule)
    
* Enough credit (free tier is fine if you delete resources afterward)
    

## Step 1 – Create a Resource Group

**Goal:** keep all lab resources organized and easy to delete later.

### Step 1.1

In the Azure Portal search bar, type **Resource groups** and select it.

### Step 1.2

Click **\+ Create**.

### Step 1.3

* **Subscription:** your default
    
* **Resource group name:** `rg-lab2-network`
    
* **Region:** choose your closest (e.g., *East US*)
    
* Click **Review + Create → Create**.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1761411545956/c9c996ec-b74a-4c1c-bc44-5b4c27c0460f.png align="center")

## Step 2 – Create Virtual Networks and Subnets

**Goal:** establish one “hub” (primary) and one “spoke” VNet.

### Step 2.1 – Create Primary VNet

1. In the portal, search **Virtual networks → + Create**.
    
2. **Basics tab:**
    
    * Resource group: `rg-lab2-network`
        
    * Name: `vnet-lab2-primary`
        
    * Region: *East US*
        
3. **IP Addresses tab:**
    
    * Address space: `10.1.0.0/16`
        
4. Add two subnets:
    
    * `subnet-app` → `10.1.1.0/24`
        
    * `subnet-db` → `10.1.2.0/24`
        
5. Click **Review + Create → Create**.
    

### Step 2.2 – Create Spoke VNet

1. **\+ Create → Virtual Network** again.
    
2. Resource group: `rg-lab2-network`
    
3. Name: `vnet-lab2-spoke`
    
4. Address space: `10.2.0.0/16`
    
5. Add subnet: `subnet-spoke` → `10.2.1.0/24`
    
6. **Create**.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1761414212100/60353bb5-9acf-4159-ac6f-4cd7a3c3351c.png align="left")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1761414619923/dfab4591-25f4-402e-91a2-883f7511fea0.png align="center")

## Step 3 – Deploy the Virtual Machines

**Goal:** create three small servers to test routing and security.

### Step 3.1 – Create vm-app-1

1. In the Portal, search **Virtual machines → + Create → Azure virtual machine**.
    
2. **Basics:**
    
    * RG: `rg-lab2-network`
        
    * Name: `vm-app-1`
        
    * Region: *East US*
        
    * Image: *Windows Server 2025 Datacenter*
        
    * Size: `Standard D2s`
        
    * Username: `itadmin`
        
    * Password: (secure)
        
3. **Networking tab:**
    
    * VNet: `vnet-lab2-primary`
        
    * Subnet: `subnet-app`
        
    * Public IP: Enabled
        
    * NIC NSG: **Basic → RDP (3389)**
        
4. **Review + Create → Create.**
    

### Step 3.2 – Create vm-db-1

Same process but choose **Subnet:** `subnet-db`.

### Step 3.3 – Create vm-spoke-1

* VNet: `vnet-lab2-spoke`
    
* Subnet: `subnet-spoke`
    
* Public IP: Enabled
    
* Size: small
    

## Step 4 – Install IIS on vm-app-1

**Goal:** host a test web page.

### Step 4.1

RDP into `vm-app-1` using its public IP.

### Step 4.2

Open **Server Manager → Add roles and features → Web Server (IIS)** → **Install**.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1761416953382/902d8dee-ae72-4c9c-abd3-1f92001f13ed.png align="left")

### Step 4.3

After it finishes, open a browser on the VM → visit [`http://localhost`.  
You](http://localhost.￼You) should see the IIS splash page.

### Step 4.4 (Optional)

Edit iistart.htm and type “Hello from vm-app-1”

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1761417838271/47186a3d-4910-44a2-83b5-9adad4706add.png align="center")

## Step 5 – Configure Network Security Groups (NSGs)

**Goal:** allow only needed traffic between subnets.

### Step 5.1 – Create NSG for App Subnet

1. In the portal, search **Network security groups → + Create**.
    
2. Name: `nsg-app-lab2`, RG: `rg-lab2-network`, Region: East US → **Create**.
    
3. Open `nsg-app-lab2` → **Inbound security rules → + Add**.
    
    * **Allow-HTTP-From-Internet:**
        
        * Source: Any | Port: 80 | Protocol: TCP | Action: Allow | Priority: 200
            
    * **Allow-RDP-From-Home:**
        
        * Source: *Your home IP/32* | Port: 3389 | Action: Allow | Priority: 210
            
4. Under **Subnets**, click **Associate → vnet-lab2-primary → subnet-app.**
    

### Step 5.2 – Create NSG for DB Subnet

1. Create `nsg-db-lab2` similarly.
    
2. Add inbound rules:
    
    * **Allow-App-to-DB-1433:** Source `10.1.1.0/24`, Port 1433, Allow, Priority 200.
        
    * **Allow-App-to-DB-RDP:** Source `10.1.1.0/24`, Port 3389, Allow, Priority 210.
        
3. Associate to `subnet-db`.
    

### Step 5.3 – Test NSGs

* From your PC → RDP to `vm-app-1` - allowed
    
* From your PC → RDP to `vm-db-1` - not allowed
    
* From inside `vm-app-1` → RDP to `vm-db-1` - allowed
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1761425891033/ebe5a102-b414-43bf-ad64-b7ae5749fd8b.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1761425925956/8c77a8be-8022-4966-8d18-e7aef9c93cc8.png align="center")

## Step 6 – Peer the VNets

**Goal:** enable private routing between primary and spoke VNets.

### Step 6.1

Open `vnet-lab2-primary` → **Peerings → + Add**.

* Peering name: `primary-to-spoke`
    
* Remote VNet: `vnet-lab2-spoke`
    
* Allow traffic both ways → **Add**.
    

### Step 6.2

Check that the reverse peering appears automatically; if not, add it manually on `vnet-lab2-spoke`.

### Step 6.3 – Test Connectivity

RDP into `vm-spoke-1` → open Command Prompt:

`ping 10.1.1.x (private IP of vm-app-1)`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1761427624248/0535ccf3-8d9b-4adf-81a0-212b3d29a54a.png align="center")

## Step 7 – Deploy Azure Bastion (Zero Public RDP)

**Goal:** secure management without exposing public IPs.

### Step 7.1

Open `vnet-lab2-primary` → **Subnets → + Subnet**

* Name: `AzureBastionSubnet`
    
* Address prefix: `10.1.3.0/26` → **Save**
    

### Step 7.2

Search **Bastions → + Create**

* Name: `bastion-lab2`
    
* RG: `rg-lab2-network`
    
* VNet: `vnet-lab2-primary`
    
* Public IP: new static IP
    
* **Create**
    

### Step 7.3

Once deployed:

* Go to `vm-app-1 → Connect → Bastion → Use Bastion`.
    
* Enter credentials and connect through browser.
    
* From inside, RDP to `vm-db-1` using its **private IP**.
    
    *You’re now securely managing both VMs without public exposure.*
    

### Step 7.4

Remove the public IPs from all three VMs:

* VM → Networking → NIC → IP configurations → dissociate public IP.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1761428479903/8ed6a9a8-bc90-4408-9293-44f528fbd1a0.png align="center")

## Step 8– Validation and Cleanup

| Test | Expected | Reason |
| --- | --- | --- |
| Internet → vm-db-1 | ❌ Blocked | No public IP + NSG |
| Internet → vm-app-1 (HTTP) | ✅ Allowed (temp) | NSG rule |
| vm-app-1 → vm-db-1 (1433) | ✅ Allowed | NSG permit |
| vm-spoke-1 → vm-app-1 | ✅ Allowed | Peering |
| Bastion → vm-app-1 | ✅ Allowed | Secure TLS access |

**Cleanup:**

* Delete optional LB, public IPs, Bastion if done testing.
    
* Or delete `rg-lab2-network` entirely to avoid charges.
    

You’ve now:

* Built hub-and-spoke VNets with unique address spaces.
    
* Secured subnets with NSGs.
    
* Connected networks using peering.
    
* Replaced open RDP with Azure Bastion.
    

**Please reach out to me if you have any questions or need help with the lab. I’d be happy to hear from you!**
