Lab 01 — Network Engine
Phase: 06 — Azure Networking & the Software-Defined Network | Difficulty: ⭐⭐⭐☆☆ | Time: 4–6 hours
When a packet is dropped in Azure, the portal will not tell you why. It shows you a green check on the NSG and a green check on the route table and leaves you to figure out that the priority-100 Deny shadowed your priority-300 Allow, or that a /32 UDR is force- tunnelling your traffic into a dead firewall, or that your Private Endpoint's DNS zone was never linked to this VNet so the name still resolves to the public IP. This lab builds the four decision engines that answer "why" — so you can read an effective-rules dump the way you read code, and so the algorithm lives in your fingers instead of in a docs tab you have to go find at 2 a.m.
What you build
subnet_usable_hosts/cidr_contains/split_subnet— the address-plan math: Azure's five reserved IPs per subnet, the /29 minimum, containment, and carving a block into children (the thing you do on a whiteboard before any VNet exists).NsgRule+evaluate_nsg— the stateful, priority-ordered, first-match-wins NSG evaluator: sort by priority ascending, the first matching rule decides, and when nothing matches fall through to Azure's default rules (allow VNet↔VNet, allow AzureLoadBalancer inbound, deny the rest).Route+effective_next_hop— the routing engine: among every route whose prefix contains the destination, pick the longest prefix; break ties UDR > BGP > system. This is how a/32UDR pins one host to a firewall and how0.0.0.0/0force-tunnels the rest.PrivateZone+resolve_fqdn— the Private Endpoint DNS override: a public PaaS FQDN resolves to a private IP for a VNet linked to theprivatelinkzone, and to the public IP for everyone else. The missing link is the #1 Private Link failure, and this function reproduces both the success and the bug.
Key concepts
| Concept | What to understand |
|---|---|
| 5 reserved IPs | every subnet loses network + .1/.2/.3 + broadcast → usable = 2^(32−p) − 5 |
| /29 minimum | a /29 has 8 − 5 = 3 usable; anything smaller is rejected by Azure |
| NSG is stateful | you evaluate the originating direction only; return traffic is implicit |
| Priority = lowest-first | priority 100 beats priority 300; first match wins, so a low-number Deny shadows a high-number Allow |
| Default rules | allow VirtualNetwork↔VirtualNetwork, allow AzureLoadBalancer in, deny all else |
| Longest-prefix match | the route with the most specific (longest) prefix decides — /32 beats /0 |
| Route tie-break | at equal prefix length: UDR > BGP > system |
| Private Endpoint DNS | success = private IP via a linked privatelink zone; broken DNS = public IP = the classic bug |
Files
| File | Purpose |
|---|---|
lab.py | skeleton with # TODO markers and full signatures/docstrings |
solution.py | complete reference; python solution.py runs a worked example |
test_lab.py | the proof — run it red, make it green |
requirements.txt | pytest only (pure stdlib otherwise) |
Run
pip install -r requirements.txt
pytest test_lab.py -v # against your lab.py
LAB_MODULE=solution pytest test_lab.py -v # against the reference
python solution.py # worked example: subnet, NSG, routes, DNS
Success criteria
- All 25 tests pass against your implementation.
- You can explain why
test_usable_hosts_29_boundaryasserts 3 (and not 6 or 8): Azure reserves 5 addresses in every subnet, so a /29's 8 addresses yield 3 usable. - You can explain why
test_nsg_priority_lower_number_winsis the whole point of NSG evaluation: a priority-100 Deny is evaluated before the priority-200 Allow, and the first match wins. - You can explain why
test_longest_prefix_32_beats_0chooses the/32route even though a0.0.0.0/0route also matches — and whytest_udr_beats_system_at_equal_prefixneeds the origin tie-break. - You can explain why
test_private_dns_returns_public_ip_when_not_linkedis the bug you will actually debug: the Private Endpoint exists, but the DNS zone is not linked to the caller's VNet, so the name resolves to the public IP and the connection either fails (NSG/firewall blocks public egress) or silently leaves the private network.
How this maps to real Azure
| This lab | Real Azure | Notes / limits |
|---|---|---|
subnet_usable_hosts | subnet sizing during VNet design | Azure reserves 5 IPs/subnet; smallest is /29; the gateway subnet wants /27+ |
evaluate_nsg | NSG security-rule evaluation in the host VFP | real priorities are 100..4096 for user rules, 65000+ for defaults; flows are stateful |
effective_next_hop | the per-NIC effective route table (az network nic show-effective-route-table) | combines system + UDR + BGP; longest-prefix wins; equal-length tie-break is UDR > BGP > system |
resolve_fqdn | Private Endpoint + Private DNS zone + VNet link | the privatelink zone must be linked to the VNet; without it, the public FQDN still resolves to the public IP |
The miniature is faithful to the algorithm; what it does not model: NSG flow logging
and connection tracking internals, Application Security Groups (ASGs) as rule sources,
augmented security rules (multiple prefixes per rule), service-tag expansion to real
Microsoft-published prefix lists, BGP route propagation and AS-path selection, UDR
0.0.0.0/0 interactions with forced tunnelling and the Internet system route's special
cases, and DNS TTL/caching. Those are the README "Extensions" below.
Extensions
- Augmented rules: let
NsgRule.source/destbe a list of prefixes/tags (Azure's augmented security rules) and an Application Security Group reference; match if the packet hits any. - Service-tag expansion: load a
ServiceTags_Public.json-shaped fixture and expandStorage.WestEuropeto its prefix list, so_endpoint_matchesresolves real tags. - BGP path selection: give
Routean AS-path length and add the real ExpressRoute tie-break (more-specific > local-pref > shortest AS-path) after prefix length. - Flow tuple + logging: emit an NSG-flow-log-shaped record (
5-tuple, decision, rule) for each evaluated packet so you can replay a capture through the engine. - Real
az: build the same VNet/NSG/UDR/Private Endpoint withaz network ...or Terraform in your own subscription, dump the effective route table and rules, and diff the live result against this engine's output for the same packets.
Resume / interview bullets
- Built a network-policy decision engine that evaluates NSG rule sets in priority order with stateful first-match semantics, computes effective routes via longest-prefix matching with UDR/BGP/system tie-breaks, and reproduces the Private Endpoint DNS-override failure mode.
- Can evaluate an Azure effective-rules dump by hand: trace why a packet was allowed or dropped, why a route force-tunnels to a firewall, and why a Private Link resource resolves to a public IP.