🏠 Home
Visibility
Block
NAT
DoH/SSL
Capstone (Optional)
--
--

The DNS Whisperer

Four hands-on labs plus an optional capstone, walking through DNS visibility, policy, steering, and DoH inspection in a Zscaler tenant. The capstone closes with four real-world scenarios — blocking DoH at DNS Control, translating inbound DoH to plaintext for ZTR, a threat-intel response to an active phishing campaign, and a compliance-driven multi-category block with a documented exception — all built from the skill stack you assemble across Labs 1–4.
01
Visibility
─▶
02
Block
─▶
03
NAT
─▶
04
DoH/SSL
- - ▶
05
Capstone (Optional)
🧪 4 hands-on labs + 1 optional capstone
LAB 01

Get DNS Into Zscaler

LAB 02

Block + Custom Allow

LAB 03

Steer DNS via NAT Control

LAB 04

DoH + SSL Inspection

CAPSTONE · OPTIONAL

DNS Control in the Real World

← Back to Architecture

ZTR NAT Rule — The Default Resolver

ZIA includes a built-in Destination NAT rule called Zscaler Trusted DNS Resolver. When enabled (the default), it intercepts all DNS traffic on port 53 and redirects it to the ZTR co-located in the same data centre the user is connected to.

The ZTR NAT rule is the switch that controls whether ZTR or an external resolver handles DNS. For this lab session it stays enabled by default — Insights rows in Labs 1, 2, and 4 will show Resolver Gateway = ZTR. Lab 3 temporarily flips it to a named DNS Gateway (Cloudflare) and then restores ZTR. Building a permanent external-resolver pattern is the production play for orgs with existing DNS provider contracts; the gateway abstraction in Lab 3 is the mechanism.
ScenarioZTR NAT RuleWho ResolvesDNSSEC
Scenario 1 (bypass)N/A — DNS never reaches ZIAInternal DNS server❌ None
Scenario 2 (external)Disabled3rd-party (Cloudflare, etc.)Depends on resolver
Scenario 3 (default)EnabledZscaler ZTR✅ Validated
Portal path: ZIA Admin Portal → Policy → NAT Control → find "Zscaler Trusted DNS Resolver".
← Back to Architecture

Zscaler Trusted Resolver (ZTR)

ZTR is Zscaler's fully recursive, DNSSEC-validating resolver. It runs co-located in 160+ Zscaler data centres globally.

CapabilityDetail
LocationCo-located with ZIA Service Edge — no extra network hop
DNSSECValidates signatures on every response. Protects against cache poisoning.
GeolocationResolves from local DC — CDNs return nearest node to the user
ECS supportNot supported (hard architectural limit). Out of scope for this lab session — use an ECS-capable external resolver in production if needed.
DoH terminationZTR does not accept DoH queries directly. Lab 4 demonstrates how this creates a visibility gap and how to close it with a DNS Control rule.
Auto-failoverOn SERVFAIL/timeout, ZIA forwards DNS to 8.8.8.8 automatically — no config needed.
CostIncluded in your ZIA subscription. No separate DNS appliance or contract required.
Lab Prerequisites
Skytap Experience Center
Lab Prerequisites — Connect to the Virtual Lab Environment
As the Zscaler administrator, you need a functional pre-configured environment that mirrors a lab tenant. By the end of this section you will have signed into your Zscaler tenant from your own browser, started your Skytap pod and signed into the Corp: Client PC, confirmed the lab clipboard, and verified ZCC is signed in with Tunnel Version = v2.0, App Policy = DNS Lab, and traffic flowing through Zscaler Cloud.
Lab architecture — your Skytap pod runs a single Corp: Client PC with ZCC already installed. The client authenticates through ZIdentity and forwards traffic into Zscaler ZIA; the Zscaler Admin Portal is reached from inside the same browser session.
Lab Access Information

Search your inbox for "DNS Whisperer" to find your lab-details email. It contains the four values below — they identify your Zscaler admin tenant for the duration of the session. The examples below use zs44xx as a placeholder — your Student ID will be something different (e.g., zs4517, zs4521, etc.). The Corp: Client PC inside Skytap uses a separate local Windows password that's the same for every student.

From your tenant emailExample
Student FQDNzs44xx.safemarch.com
Zscaler Admin UIhttps://console.zscaler.com
Usernamestudent@zs44xx.safemarch.com
Passwordzs44xx+gmsY4 (yours will be different)
— the values below are the same for every student —
Corp: Client PC password (Skytap VM)Admin-123!
Navigating the Experience Center. Use the search option in the top-right of the tenant — the magnifying-glass icon, or Ctrl + K — to quickly find any feature across all menus.
Experience Center landing page — the search bar (Ctrl + K) and the magnifying-glass icon in the top-right are the fastest way to navigate during the labs.
1 Sign in to your Zscaler tenant

1a. Open the Zscaler admin console. Use any browser on your own machine.

Browser URL
https://console.zscaler.com/
You'll be redirected to the ZIdentity sign-in page to validate your identity.

1b. Authenticate with the credentials from your lab details email. The password in the email is a one-time password. You'll use it for this first sign-in only; ZIdentity will then prompt you to choose a new password (Step 1c) which you'll use for the rest of the labs.

FieldValue
Login IDstudent@<Student FQDN> — e.g., student@zs44xx.safemarch.com
Password (one-time)from the email — format <Student ID>+<random suffix>, e.g., zs44xx+gmsY4
ZIdentity sign-in page — enter your Login ID (your student@<Student FQDN> account), then the one-time password from the email. Click Sign In.

1c. Choose your password for the rest of the lab. ZIdentity prompts you to set a new password right after the first sign-in. This new password — not the one-time password from the email — is what you'll use for every Zscaler sign-in throughout the labs, including when you sign into ZCC inside the VM (Step 4). Pick something memorable.

After setting a new password, ZIdentity confirms Success! and offers a Re-Login button. Click it to sign in with your new password.
2 Start your Skytap pod and log into the Corp: Client PC

2a. Start the Skytap pod.

  • Click the Skytap Portal URL provided in your access instructions.
  • Your pod contains a single VM — Corp: Client PC. Ensure its checkbox is selected.
  • If the machine has not already started, click the Play button to launch it.
Skytap — the Corp: Client PC VM card showing Running status.

2b. Log into the Corp: Client PC as the local Student user.

  • Launch the Corp: Client PC from the Skytap portal.
  • Click the Ctrl-Alt-Del icon in the Skytap Toolbar.
  • Click the Credential (keys) icon in the Skytap Toolbar.
  • Click the Insert Credentials icon next to the password field for the student username, or type the password manually: Admin-123!
Skytap login screen — click the Insert Credentials icon next to the password field for the student username.
This local Windows login is unrelated to your Zscaler tenant credentials from Step 1. The Admin-123! password is the same for every student.
3 Use the Lab Clipboard

Throughout these labs you will frequently copy commands, URLs, and configuration values from the lab guide into the lab VMs. Skytap provides a clipboard bridge between your local machine and the VM.

3a. Copy text from your host machine to the VM clipboard.

  • Click the clipboard icon in the Skytap Toolbar.
  • Paste your text into the Copy/paste: field that appears.
Skytap toolbar clipboard icon highlighted — opens the Copy/paste panel that bridges host clipboard to VM clipboard.

3b. Paste the text inside the VM.

  • In the VM, use Ctrl+V (or right-click → Paste) to paste the copied text.
Mac users: the virtual machine is running Windows. Use Ctrl+V (not Cmd+V) inside the VM — the VM does not interpret the macOS Command key.
4 Log into ZCC on the Corp: Client PC

ZCC must be signed in and tunneling before the labs work — this is what carries DNS into ZTE.

4a. Open ZCC from the system tray. Right-click the Zscaler icon in the Windows system tray and choose Open Zscaler. The ZCC sign-in window appears.

ZCC system tray menu — click Open Zscaler to bring up the sign-in window.

4b. Sign in with your student admin credentials. Use the same Login ID as Step 1 (student@<Student FQDN>) and the new password you set in Step 1c. Paste the username via the Skytap clipboard if it's faster.

ZCC sign-in — paste your student@<Student FQDN> account into the username field and proceed through the ZIdentity flow.

4c. Verify Tunnel Version = v2.0. Once ZCC is signed in, the Zscaler Client Connector window shows the connectivity details. Confirm Tunnel Version = v2.0 - DTLS — that's the mode the labs depend on.

ZCC Connectivity panel after sign-in — Username matches your student admin account and Tunnel Version = v2.0 - DTLS.

4d. Verify the App Policy is "DNS Lab". Click the More tab in the left sidebar and scroll to the About section. Confirm App Policy: DNS Lab.

ZCC More tab — under the About section, App Policy: DNS Lab confirms the right App Profile is bound to this client.

4e. Verify traffic is going through Zscaler. Inside the Corp: Client PC browser, open:

Browser URL
https://ip.zscaler.com

If ZCC is tunneling, the page reports "You are accessing the Internet via Zscaler Cloud" along with your Zscaler proxy IP and Gateway IP. If you instead see your raw public IP and a "you are not going through Zscaler" message, ZCC isn't authenticated — revisit 4a/4b.

ip.zscaler.com from inside the Corp: Client PC — the page confirms traffic is routing through the Zscaler Cloud (in this example, Singapore IV) and shows the signed-in user (student@...).

✅ Ready for Lab 1

Signed into https://console.zscaler.com/ with your student admin account; temporary password changed.
Skytap pod is running, Corp: Client PC launched and signed in.
Skytap clipboard works — you can copy text from host into the VM.
ZCC is signed in and running on Z-Tunnel 2.0.
Live Lab
Lab 1 of 4 App Profile DNS Insights
Lab 1 — Get DNS Into Zscaler
Right now ZCC is signed in but DNS isn't reaching ZIA — the VM resolves everything itself, and DNS Insights stays empty. In this lab we'll first prove that gap with an nslookup and an empty DNS Insights view. Then we'll edit the Windows App Profile: set Domain Inclusion to * so every query is sent to Zscaler, and add three Domain Exclusions (*.corp.local, *.safemarch.com, *.qradar.com) so internal zones stay on the corporate resolver. After an Update Policy on ZCC, we'll re-run the lookups and confirm two things in DNS Insights: chatgpt.com now shows up (resolved by ZTR), and intranet.corp.local doesn't (the exclusion kept it off Zscaler entirely).
Goal: Verify that DNS for external domains flows into ZTE (visible in DNS Insights, resolved by ZTR) and DNS for internal domains continues to resolve locally (no DNS Insights entry).
1 Verify DNS isn't reaching ZIA yet

On the lab VM, open Command Prompt and run a baseline DNS query:

Windows Command Prompt
nslookup chatgpt.com
Command Prompt baseline — nslookup chatgpt.com resolves through the local gateway resolver, returning IPv4 + IPv6 records.

Now check whether ZIA saw the query. From the Experience Center top menu:

Experience Center top menu — click Logs, then under Internet & SaaS click DNS Insights.

On the DNS Insights page, click the Logs tab. Set the timeframe to the last 5 minutes. Add a filter Requested Domain Contains chatgpt and click Run Query:

DNS Insights Logs — filter by Requested Domain Contains chatgpt shows No data for selected time range. The query bypassed Zscaler entirely.
That absence is the gap. The query resolved on the VM, but ZIA never received it. The next steps fix that with one App Profile change.
2 Open the DNS Lab Windows App Profile

From the Experience Center top menu, navigate to:

Experience Center top menu — Infrastructure → Connectors, then in the left panel Client → Windows.

You'll land on the Windows page showing the App Profiles list. Find the row for the DNS Lab policy and click the Edit (pencil) icon in the Actions column:

Windows App Profiles list — click the Edit (pencil) icon on the DNS Lab row.
3 Send all DNS to Zscaler and exclude 3 internal zones

The Edit Windows Policy dialog opens to the DNS tab in the Traffic Steering section. You'll make two changes here:

  1. Set Domain Inclusion to * — sends every DNS query to Zscaler.
  2. Add three Domain Exclusions — keeps internal-zone queries on the corporate resolver so they never reach ZIA:
    • *.corp.local
    • *.safemarch.com
    • *.qradar.com
Naming note. These three zones simulate a typical corporate internal-DNS namespace for this lab.

In the Domain Inclusion field, type *. The field offers "Create ‘*’" as a suggestion — accept it:

Domain Inclusion = * with the Create ‘*’ option selected.

Now move to Domain Exclusion and add the three internal zones one at a time, pressing Enter after each. Once all three are listed, click Save at the bottom of the dialog:

Domain Exclusion populated with *.corp.local, *.safemarch.com, *.qradar.com. Click Save to commit.
⚠ Always pair wildcard Inclusion with Exclusions. Without them, internal-zone queries (AD, intranet, SIEM) also get forwarded to Zscaler — which can't resolve those private zones, so internal apps blackhole with NXDOMAIN. In production, the Exclusion list should cover every internal DNS zone the customer uses.
4 Pull the new policy on the ZCC client

On the lab VM, open the Zscaler Client Connector application (double-click the tray icon, or right-click → Open). In the left navigation, click the More tab. In the About section, click Update Policy next to the App Policy line:

ZCC client → More tab → Update Policy. Pulls the new App Profile from ZIA without restarting the service.
Update Policy is the lightweight refresh path. It pulls the fresh App Profile from ZIA and applies it in place — no service restart, no tunnel teardown.
5 Verify the query now appears in DNS Insights

Run two queries from Command Prompt on the VM — one public, one internal:

Windows Command Prompt
nslookup chatgpt.com nslookup intranet.corp.local

chatgpt.com resolves through ZTR. intranet.corp.local returns NXDOMAIN — expected, because the host doesn't really exist; we're using it as a test name that matches the *.corp.local exclusion. The proof of the exclusion working is on the next screen: no log entry in DNS Insights means ZCC never forwarded the query.

nslookup chatgpt.com succeeds via ZTR; nslookup intranet.corp.local hits the local resolver and returns NXDOMAIN because the exclusion kept the query off Zscaler.

Open Experience Center → Logs → DNS Insights → Logs and re-run the same filter (Requested Domain Contains chatgpt). The Insights pane that was empty in Step 1 now populates with rows — one per query — attributed to your user, with Resolver Gateway = ZTR:

DNS Insights Logs — same filter as Step 1, now populated with log records. Each row shows the requesting Location, Client IP, Requested Domain, and Server IP.

Now change the filter to Requested Domain Contains intranet and run the query again. The pane is empty — even though you just ran the lookup on the VM. That's the exclusion working: Zscaler never saw the query, so there's nothing to log:

DNS Insights Logs filtered by intranetNo data for selected time range. Proof that the *.corp.local exclusion stopped ZCC from forwarding the query.
If the chatgpt row still doesn't appear: re-run Update Policy on the ZCC client; confirm Save was clicked inside the App Profile dialog (it closes silently, easy to miss); give Insights another 30 seconds for log ingest.

✅ Verification

Pre-fix: chatgpt.com resolved on the VM, but DNS Insights was empty.
Post-fix: chatgpt.com appears with Resolver Gateway = ZTR, Action = Allow.
intranet.corp.local does not appear — Domain Exclusion stopped ZCC from forwarding it.
ZCC is signed in and tunneling — https://ip.zscaler.com confirms "Internet via Zscaler Cloud" (Z-Tunnel 2.0).
Quick ZCC re-check. Before moving on, open https://ip.zscaler.com inside the VM browser. If it confirms you're going through Zscaler Cloud, ZCC is healthy and Lab 2 will work. If not, sign back into ZCC (Prerequisites → Step 4) before continuing.

What you just built

DNS flow after Lab 1 — wildcard inclusion plus three internal-zone exclusions A Windows VM running ZCC issues DNS queries. The ZCC App Profile splits traffic into two paths. Public domains match Inclusion equals asterisk and are forwarded to Zscaler ZTR. Queries matching the three internal exclusion zones stay on the corporate DNS resolver and never reach Zscaler. DNS flow after Lab 1 Wildcard Inclusion + 3 internal Exclusions Windows VM running ZCC DNS query → ZCC App Profile DNS Lab match check — Exclusion first Inclusion: * Exclusion match ZTE resolves + logs to DNS Insights chatgpt.com • google.com … every other domain Corporate DNS never reaches Zscaler *.corp.local *.safemarch.com *.qradar.com

The Domain Exclusion list is evaluated before the wildcard Inclusion — that's why these three zones stay on the corporate resolver while everything else flows to Zscaler.

Live Lab
Lab 2 of 4 DNS Control App Profile
Lab 2 — Block + Custom Allow
DNS is now flowing into Zscaler, so we can start applying policy. In this lab we'll first confirm a Gambling-category domain resolves cleanly (no policy yet). Then we'll build a DNS Control rule that blocks the entire Gambling category and watch the same lookup fail. Next we'll carve a single domain (888.com) back out of the block: create a custom URL category for it, add a top-order DNS Control Allow rule that points at that category, and verify 888.com resolves while bet365.com stays blocked. Both queries stay logged in DNS Insights so you can see the block and the allow side-by-side in the audit trail.
Goal: Block the Gambling category in DNS Control. Then create a custom URL category DNS Control Exclusions containing 888.com and a top-order DNS Control rule that Allows it. After activation, bet365.com stays blocked while 888.com resolves — both visible in Insights with the right Action.
Reminder: after activating any rule, always run ipconfig /flushdns on the VM before re-testing a domain. Windows keeps cached answers and will happily serve them ahead of your new policy. DNS Insights can also lag by 2–3 minutes before the new query shows up — if the log looks empty, give it a moment and refresh.
1 Verify a gambling site resolves before any policy

From the lab VM, run a baseline query against a Gambling-category domain. With no DNS Control rule yet, the query should resolve normally:

Windows Command Prompt
nslookup www.gambling.com
Baseline — www.gambling.com resolves to public CDN IPs. Note these for comparison after the policy is in place.
2 Build a DNS Filtering Rule blocking Gambling

Navigate to DNS Control:

Policies → Access Control panel — under Firewall column, click DNS Control.

On the DNS Control page, click + Add DNS Filtering Rule:

DNS Control landing page — click + Add DNS Filtering Rule to open the rule editor.

In the DNS Filtering Rule dialog, set the rule basics:

FieldValue
Rule Order1
Rule NameBlock Gambling
Rule StatusEnabled
Rule basics — Order = 1, Name = Block Gambling, Status = Enabled.

Switch to the DNS Application tab. Set both Request and Response Categories to Gambling:

FieldValue
Request CategoriesGambling
Response CategoriesGambling
DNS Application tab — Request and Response Categories both set to Gambling.

Scroll to the bottom. Set Network Traffic action to Block and click Save:

Action panel — Network Traffic = Block. Click Save.
3 Activate the rule

The orange Pending Activation indicator appears in the top-right of the Experience Center. Click it, then click Activate:

Pending Activation panel — click Activate to push the new rule live.
Activation pushes pending changes to the ZIA service edges. Without it, the rule exists in your tenant config but doesn't fire on traffic.
4 Verify the block from the VM

Confirm normal traffic still works (sanity check that you didn't block too much):

Windows Command Prompt
nslookup www.google.com
www.google.com still resolves — the rule is targeted at Gambling only.

Flush the Windows DNS cache so the previous successful Gambling response isn't served from cache:

Windows Command Prompt
ipconfig /flushdns
Cache flushed — subsequent queries hit the resolver fresh.

Re-run the gambling lookup. The query should now time out — the block fires before resolution:

Windows Command Prompt
nslookup gambling.com
nslookup gambling.com times out — the DNS Control Block Gambling rule fires before the upstream resolver answers.
5 View the blocks in DNS Insights

Filter by your Rule Name = Block Gambling and an appropriate timeframe. Click Apply Filters:

DNS Insights filter pane — Rule Name = Block Gambling, current day timeframe.

The Logs table populates with rows for each blocked query. Each shows the user, source IP, requested domain, response IP, request category, response type, and the Block action:

DNS Insights Logs — four entries for www.gambling.com blocked, attributed to the lab user. Action column shows Block.
The Insights row is the audit trail. In production this is what an SOC analyst would correlate against an incident: which user, which domain, which rule, what time.
6 Carve out 888.com with a custom URL category + Allow rule

888.com is currently caught by the Gambling block from Step 4. To provide an exception, you'll add it to a custom URL category and reference that category in a top-order DNS Control Allow rule.

Why this is the recommended pattern. Exemptions live in the same policy plane as the blocks — one place to audit, one place to change — and every query stays visible in DNS Insights. Compare with the App Profile Exclusion pattern from Lab 1, which makes the traffic invisible to Zscaler entirely.
Rule of thumb — Reserve App Profile Exclusions for non-routable internal zones; use DNS Control + custom category for everything else.

6a. Create the custom URL Category. Navigate to:

Policies → Access Control panel — under Internet & SaaS column, click URL Categories.

On the URL Categories page, click + Add URL Category. In the dialog, set:

FieldValue
NameDNS Control Exclusions
URL Super CategoryUser-Defined
Scope TypeAny
Custom URLs888.com — click Add Items to commit
Add URL Category dialog — Name = DNS Control Exclusions, Custom URLs contains 888.com. Click Add Items to commit the URL, then Save.
Custom URLs list confirms 888.com is saved into the category. Click Save on the dialog.

6b. Build a top-order Allow rule in DNS Control. Open the quick-search (top-right magnifier in Experience Center) and search for dns con, then click DNS Control:

Top-right search — typing dns con surfaces the DNS Control page (Policies → Access Control → Firewall → DNS Control).

Click + Add DNS Filtering Rule. In the rule editor, set:

FieldValue
Rule Order1must be above the Block Gambling rule
Rule NameDNS Control Exclusions
Rule StatusEnabled
New DNS Filtering Rule — Order = 1, Name = DNS Control Exclusions, Status = Enabled. Order 1 puts it above the Block Gambling rule, so it wins the first-match evaluation.

Switch to the DNS Application tab. Set both Request and Response Categories to the custom category you just built. In the Action panel, set Network Traffic to Allow:

FieldValue
Request CategoriesDNS Control Exclusions
Response CategoriesDNS Control Exclusions
Network Traffic ActionAllow
DNS Application tab — Request and Response Categories both = DNS Control Exclusions, Action = Allow. Click Save.

6c. Activate. Click the orange Pending Activation indicator and confirm:

Pending Activation — click Activate to push the new rule live.

6d. Verify. From Command Prompt on the VM, test a still-blocked Gambling domain (bet365.com) and the exempted domain (888.com) back-to-back:

Windows Command Prompt
nslookup bet365.com nslookup 888.com

bet365.com still times out — it's in the Gambling category but isn't in your custom exemption list, so the Block Gambling rule still fires. 888.com resolves to public IPs because the top-order Allow rule matched first:

Final state — nslookup bet365.com times out (still blocked by Gambling rule); nslookup 888.com returns real IPs because the Allow rule matched first.
Both queries are in DNS Insights. Filter by Requested Domain bet365 and you'll see Action = Block, Rule Name = Block Gambling. Filter by 888 and you'll see Action = Allow, Rule Name = DNS Control Exclusions. Full visibility, full audit trail — that's the value of carving out at the DNS Control layer instead of bypassing at the client.

✅ Verification

nslookup www.gambling.com and nslookup bet365.com on the VM time out.
nslookup 888.com resolves to public IPs.
DNS Insights shows bet365.com with Action = Block and 888.com with Action = Allow.
The Allow rule sits at Order 1, above Block Gambling.

What you just built

DNS Control rule evaluation after Lab 2 — custom Allow above category Block A DNS query reaches Zscaler's DNS Control engine. Rules evaluate in order, first match wins. Rule 1 allows the custom DNS Control Exclusions category, which contains 888.com. Rule 2 blocks the Gambling category. The result: 888.com is allowed, bet365.com is blocked, both logged in DNS Insights. DNS Control rule evaluation after Lab 2 First-match wins — custom Allow above category Block VM via ZCC DNS query reaches Zscaler (ZTE) 888.com bet365.com DNS Control rulebook evaluated top-down, first match wins ORDER 1 Allow Categories = DNS Control Exclusions contains: 888.com ORDER 2 Block Categories = Gambling matches: bet365.com, gambling.com, … Default: Allow everything else — logged chatgpt.com, google.com, … 888.com → resolves Insights: Action = Allow Rule = DNS Control Exclusions bet365.com → blocked Insights: Action = Block Rule = Block Gambling Recommended pattern All DNS reaches Zscaler. Controls live in DNS Control where every query is logged in DNS Insights — block and allow alike. Contrast with App Profile Domain Exclusion (Lab 1): bypasses Zscaler entirely — no log, no audit. Use that pattern only for non-routable internal zones.

Letting all DNS reach Zscaler and carving exceptions at the DNS Control layer keeps every query visible in Insights. The rule order is the policy — the Allow on top wins for 888.com, the Block underneath still catches the rest of the Gambling category.

Live Lab
Lab 3 of 4 DNS Gateway NAT Control DNS Insights
Lab 3 — Steer DNS via NAT Control
By default everything from your tenant resolves through ZTR. In this lab we'll redirect all DNS traffic to Cloudflare instead, and use netflix.com as the test domain to verify the flip. First we'll run a baseline nslookup netflix.com and confirm DNS Insights shows Resolver Gateway = ZTR, Server Protocol = UDP. Then we'll create a named DNS Gateway (Cloudflare) pointing at cloudflare-dns.com, add a top-order NAT Control rule (Network Services = DNS, no domain filter) that redirects all DNS through that gateway, activate, and re-test. The flip lives in DNS Insights: Resolver Gateway becomes Cloudflare, Server Protocol becomes DNS Over HTTPS, HTTP Status Code becomes 200 - OK. Once you've seen the change, we'll delete the NAT rule so the rest of the labs run on ZTR again.
Goal: Create a Cloudflare DNS Gateway (Primary = cloudflare-dns.com, Protocol = DoH+TCP+UDP, Failure Behavior = Return Error Response). Add a NAT Control rule at Order 1 using Redirect Request Using DoH targeting it — the rule has Network Services = DNS and no destination filter, so it applies to all DNS traffic. Use netflix.com as the probe and confirm in DNS Insights that DNS is now resolving via Cloudflare over DoH. Then delete the rule so ZTR resumes.
1 Confirm the baseline — ZTR is the current resolver

From the lab VM, run a baseline DNS query to confirm ZTR is currently answering:

Windows Command Prompt
nslookup netflix.com
Baseline — nslookup netflix.com resolves to a mix of IPv4 and IPv6 addresses. We'll keep using this same query throughout the lab to compare the before / after states.

Now check how Zscaler logged that query. Navigate to:

Filter Requested Domain Contains netflix, set the timeframe to the last few minutes, and run the query. You should see one row per nslookup attempt, with Resolver Gateway = Zscaler Trusted DNS Resolver and Server Protocol = UDP:

Baseline state in DNS Insights — netflix queries are going to Zscaler Trusted DNS Resolver over UDP. HTTP Status Code is None (DoH-only field, not applicable on UDP). This is the default we're about to flip.
Don't see those columns? They're hidden by default. Click the column customizer (three vertical dots at the top-right of the table) and use Select All.
Column customizer — click Select All.
2 Create the Cloudflare DNS Gateway

The DNS Gateway is the named, protocol-aware abstraction a NAT Control rule will point at. Build it first, then wire the rule to it.

Open the top-right search in Experience Center (magnifier icon) and type proxies. Click the Proxies and Gateways result:

Quick-search for proxies — the page lives under Infrastructure → Internet & SaaS → Network Policies → Forwarding Control, but search is the fastest way in.

On the Proxies & Gateways page, click the DNS Gateways tab. You'll see the predefined Zscaler Trusted DNS Resolver entry. Click + Add DNS Gateway and configure:

FieldValue
NameCloudflare
ProtocolDNS over HTTPS; TCP; UDP
Primary DNS Servercloudflare-dns.com
UDP / TCP Port53 (default)
DoH Port443 (default)
Secondary DNS ServerLeave empty
Failure BehaviorReturn Error Response

Click Save:

Add DNS Gateway dialog — Cloudflare over DoH (with UDP/TCP fallback) targeting cloudflare-dns.com, with Failure Behavior = Return Error Response.
The DNS Gateway is reusable. Once defined, any NAT Control rule can reference it by name.
3 Navigate to NAT Control Policy
Policies → Access Control panel — under Firewall, click Firewall Filtering Policy.

On the Firewall Filtering Policy page, switch to the NAT Control Policy tab. You'll see the predefined Zscaler Trusted DNS Resolver rule already in the list (Rule Order 1). Click + Add NAT Control Rule to layer a custom rule above it:

NAT Control Policy tab — predefined Zscaler Trusted DNS Resolver rule visible. Click + Add NAT Control Rule.
4 Build the rule pointing at the Cloudflare gateway

In the Add NAT Control Rule dialog, configure the rule basics:

FieldValue
Rule Order1 (above the predefined ZTR rule)
Rule NameCloudflare DNS
Rule StatusEnabled
Who, Where, & WhenDefault (any user, any location, any time)

Switch to the Services tab. Set Network Services = DNS. Then in the Action panel, pick Redirect Request Using DoH from the DNS Gateway or DNAT IP/FQDN & Port dropdown, and select Cloudflare from the DNS Gateway dropdown:

FieldValue
Services tab → Network ServicesDNS
Action → DNS Gateway or DNAT IP/FQDN & PortRedirect Request Using DoH
Action → DNS GatewayCloudflare

Click Save:

Add NAT Control Rule — Order 1, Name Cloudflare DNS, Services = DNS, Action = Redirect Request Using DoH via the Cloudflare gateway.
The action does more than steer — it upgrades the protocol. The VM sends plaintext UDP/53. ZIA intercepts and forwards upstream as DoH on TLS/443 — encrypted across the open internet, even though the client never negotiated DoH itself. Real security & privacy win at zero client cost.
5 Activate the rule

Click the orange Pending Activation badge in the top-right of the Experience Center, then click Activate:

Pending Activation panel — click Activate to push the new gateway + NAT rule live.
Until you activate, the gateway exists and the rule is staged but neither is in effect. NAT changes take a few seconds to propagate after activation.
6 Verify the resolver flipped

Re-run the test query on the VM:

Windows Command Prompt
nslookup netflix.com

The query still resolves; the Server: line in nslookup doesn't change — ZIA's NAT is invisible to the client. The flip lives in DNS Insights. Re-run the netflix filter and compare against Step 1:

Enable these columns now. You'll need Server Protocol and HTTP Status Code visible to see the protocol change. If they're hidden, click the column customizer (three vertical dots at the top-right of the table) and toggle them on.
ColumnBeforeAfter
Resolver GatewayZscaler Trusted DNS ResolverCloudflare
Server ProtocolUDPDNS Over HTTPS
HTTP Status CodeNone200 - OK
The protocol upgrade is visible in three columns at once: Resolver Gateway, Server Protocol, HTTP Status Code.

Surface the Server IP column to confirm the upstream — every netflix row shows a Cloudflare-owned IP (typically 1.1.1.1 or 1.0.0.1 — ZIA resolved cloudflare-dns.com to one of them):

Server IP shows a Cloudflare-owned IP on every netflix row (one of 1.1.1.1, 1.0.0.1) — Cloudflare is the upstream resolver.
DNS Control still fires on this traffic — the NAT rule changed where and how the query travels, not whether ZIA inspects it.
7 Tear down — delete the NAT Control rule

Lab 4 and the Capstone assume DNS is going through ZTR. Remove the NAT Control rule so the predefined ZTR rule takes over again — you can leave the Cloudflare DNS Gateway in place; it does nothing on its own without a rule referencing it.

7a. Delete the NAT Control Rule. Navigate back to NAT Control Policy:

Same nav as Step 3 — return to the NAT Control Policy tab.

On the NAT Control Policy list, find your Cloudflare DNS rule (Rule Order 1) and click the Edit (pencil) icon in the Actions column:

NAT Control Policy list — click the Edit pencil on the Cloudflare DNS row.

Scroll to the bottom of the Edit NAT Control Rule dialog and click Delete:

Edit NAT Control Rule dialog — click Delete at the bottom-right to remove the rule.

7b. Activate. Click the orange Pending Activation badge in the top-right and Activate. This commits the deletion:

Activate the deletion. ZTR resumes as the default resolver for downstream labs.

Re-run nslookup netflix.com from the VM to confirm resolution still works. Then in DNS Insights, the Resolver Gateway column should be back to ZTR for new queries.

Don't skip this step. Lab 4 and the Capstone assume DNS is flowing through ZTR. A leftover Cloudflare DNS rule will produce confusing behavior in those labs.

✅ Verification

While active: DNS Insights shows Resolver Gateway = Cloudflare, Server Protocol = DNS Over HTTPS, Server IP = a Cloudflare-owned IP (e.g., 1.1.1.1).
After delete + Activate: Resolver Gateway returns to ZTR for new queries.
The gateway's Failure Behavior = Return Error Response — fail-closed if Cloudflare is unreachable.

What you just built

DNS steering after Lab 3 — ZIA upgrades plaintext UDP DNS to encrypted DoH on the way to Cloudflare The VM sends a plaintext UDP/53 DNS query for netflix.com. The Zscaler NAT Control rule intercepts it and forwards it as encrypted DoH on TLS/443 to Cloudflare (cloudflare-dns.com). If Cloudflare is unreachable, the DNS Gateway returns an error response (fail-closed posture). DNS steering after Lab 3 ZIA upgrades plaintext UDP DNS to encrypted DoH on the way to Cloudflare VM via ZCC netflix.com plaintext DNS UDP / 53 Zscaler — NAT Control Cloudflare DNS rule @ Order 1 PROTOCOL UPGRADE plaintext → encrypted DoH / 443 Cloudflare cloudflare-dns.com ✓ resolves netflix.com if Cloudflare unreachable error returned Client sends plaintext UDP/53. ZIA forwards as encrypted DoH/443 — the transport upgrade is invisible to the client.

The client never knows it; the gateway turns plaintext UDP/53 into encrypted DoH on the upstream leg. If Cloudflare is unreachable, the gateway returns an error — a fail-closed posture chosen when resolver provenance matters more than availability. Flip Failure Behavior to Forward to Zscaler Trusted Resolver for the opposite trade-off.

Live Lab
Lab 4 of 4 Firefox & Chrome SSL/TLS Inspection
Lab 4 — DoH + SSL Inspection
Now let's switch gears and deal with DoH. Depending on the browser configuration, the browser can send DNS in plaintext or wrapped inside HTTPS (DoH). In this lab, we'll first verify Firefox's DoH is off (the baseline state), then watch the Lab 2 Gambling block fire as expected on plaintext DNS. Next we'll flip Firefox to DoH and check whether Zscaler can still enforce the same rule. To close the gap, we'll configure SSL Inspection so ZIA can decrypt the HTTPS, see the DNS query inside, and re-fire the block.
Goal: Prove the gap — gambling.com loads in Firefox-with-DoH but is blocked in Chrome (plaintext DNS). Add an SSL/TLS Inspection rule with Action = Inspect, Activate, and re-test — Firefox is now blocked too.
1 Verify Firefox DoH is currently OFF (baseline state)

Before running the baseline block test, confirm Firefox isn't already using DoH — if it were, the Lab 2 Gambling block would appear broken from the very first test, and you'd waste time chasing the wrong cause.

Open Firefox on the VM. Click the hamburger menu (top-right) and choose Settings:

Firefox menu — click Settings to open preferences.

In the Settings search box, type dns. Scroll to Enable DNS over HTTPS using: and confirm Off is selected (the radio with "Use your default DNS resolver"):

Firefox DoH preferences — Off is selected. Firefox will use the OS resolver (which ZCC forwards to ZIA), so the Lab 2 Block Gambling rule will fire on its queries.
Leave the Settings tab open — you'll come back to it in Step 3 to flip the radio to Max Protection.
2 Confirm the Lab 2 block still fires — baseline in Firefox

Without DoH configured yet, Firefox uses the Windows system resolver. ZCC tunnels system DNS to ZIA (Lab 1), and the Lab 2 Block Gambling rule fires. Browse www.gambling.com in Firefox — the page should fail to load:

Firefox — www.gambling.com fails to load with Server Not Found. The DNS query went via system DNS through ZIA and got blocked by the Lab 2 rule.
3 Configure DNS over HTTPS in Firefox

Return to the Firefox Settings tab from Step 1 (or reopen it via the hamburger menu → Settings, search dns). This time, flip the radio from Off to Max Protection. Confirm the provider is Cloudflare (Default):

Firefox DoH preferences — Max Protection enabled, provider = Cloudflare (Default). From now on, Firefox sends DNS queries as encrypted HTTPS to Cloudflare instead of using the OS resolver.
4 Reload gambling.com — it now loads

Reload www.gambling.com in Firefox. The page loads:

Firefox — www.gambling.com now loads. The DNS query was encrypted to Cloudflare; ZIA saw the HTTPS connection but couldn't read the DNS query inside, so the Lab 2 Block rule didn't fire.
DNS Control matches DNS protocol fields. DoH wraps the DNS protocol inside TLS. Without SSL Inspection, ZIA sees ciphertext and cannot match against it.
5 Cross-browser sanity check — gambling.com in Chrome

Open Chrome and try gambling.com. Chrome (on Windows by default) uses the system resolver — plaintext DNS to ZCC, then ZIA. The Lab 2 rule fires:

Chrome — gambling.com blocked with DNS_PROBE_FINISHED_NXDOMAIN. The query went via plaintext DNS through ZIA, which blocked it as designed. Same domain, same DNS Control rule, different outcome — the difference is purely the DNS transport (plaintext vs. DoH).
Two browsers, same machine, same DNS Control rule, opposite results — the only difference is the DNS transport.
6 Add an SSL/TLS Inspection rule

Navigate to SSL Inspection policy:

Policies → Common Configuration → SSL/TLS Inspection → click SSL/TLS Inspection Policy.

Click + Add SSL/TLS Inspection Rule. Configure the basics:

FieldValue
Rule Order1
Rule NameInspect All traffic
Rule StatusEnabled
Add SSL/TLS Inspection Rule — Rule Order 1, Name Inspect All traffic, Status Enabled.

Scroll to the Action section. Set Action = Inspect. Leave the other fields at their defaults for the lab. Click Save:

SSL/TLS Inspection Rule action — Inspect. Click Save.
7 Activate and verify Firefox now blocks

Click the orange Pending Activation badge in the top-right of the Experience Center, then click Activate:

Pending Activation panel — click Activate.

Before re-testing, clear out any cached state from the previous DoH-bypass run — otherwise Firefox or the OS may serve the old resolution and the test will look like SSL Inspection didn't work:

  1. Quit Firefox completely (close all windows, then File → Exit — not just the tab).
  2. Open Command Prompt and flush the Windows DNS cache:
    Windows Command Prompt
    ipconfig /flushdns
  3. Relaunch Firefox and browse to www.gambling.com.

The page now fails to load — same as the baseline at Step 2:

Firefox — gambling.com blocked again. SSL Inspection let ZIA decrypt the Cloudflare DoH connection, see the DNS query inside, and apply the Lab 2 block.
8 DNS Insights deep-dive — where DoH actually went

Filter by Requested Domain Contains gambling. With SSL Inspection on, the DoH queries are now visible to ZIA. The Insights row detail tells you exactly how each query reached the resolver:

DNS Insights — rows split by transport: DNS Tunnel & Network App column shows Cloudflare DNS on DoH rows and DNS on plaintext rows; Protocol Type column reads DNS Over HTTPS vs UDP. The DoH queries resolved against Cloudflare, not ZTR — that's where Firefox's DoH provider points.
SSL Inspection lets ZIA see DoH queries; it doesn't change where they resolve. Firefox is still talking to Cloudflare. To redirect DoH to ZTR instead, use the Lab 3 NAT Control pattern.

✅ Verification

Before DoH: Firefox gambling.com blocked.
After Firefox DoH: gambling.com loads. Chrome (plaintext) still blocked.
After SSL Inspection + Activate: Firefox blocks again.
DNS Insights DoH rows show Network App = Cloudflare DNS, Protocol = DNS Over HTTPS.

What you just built

SSL Inspection closes the DoH bypass — before vs after Two horizontal flows comparing the same Firefox-with-DoH request. Without SSL Inspection, ZIA sees only opaque TLS, the DNS query inside is hidden, and gambling.com loads. With SSL Inspection enabled, ZIA decrypts the HTTPS connection, sees the DNS query inside, DNS Control fires the Block Gambling rule, and gambling.com is blocked. SSL Inspection closes the DoH bypass Same Firefox-with-DoH request, two outcomes — visibility depends on inspection Before SSL/TLS Inspection rule is OFF Firefox + DoH gambling.com DoH / TLS:443 ZIA TLS opaque — can't see DNS query DNS Control has nothing to match passes through ✗ gambling.com loads block bypassed via DoH After SSL/TLS Inspection rule activated (Action = Inspect) Firefox + DoH gambling.com DoH / TLS:443 ZIA — SSL Inspection decrypts TLS → sees DNS query inside DNS Control fires Block Gambling block fires ✓ gambling.com blocked DoH bypass closed SSL Inspection doesn't change where DoH resolves — Firefox still talks to Cloudflare. It just lets ZIA see the DNS query inside, so DNS Control can match it.

Same encrypted DoH stream, two outcomes. Without inspection, the DNS query inside HTTPS is opaque to ZIA — DNS Control is layer-blind, the block doesn't fire, gambling.com loads. With inspection on, ZIA decrypts, sees the query, and the Lab 2 Block Gambling rule fires normally.

Capstone Lab · Optional
Capstone Optional Open-ended
Capstone (Optional) — DNS Control in the Real World
Optional — do this if you've finished Labs 1–4 and have time. Four real-world workflows, in priority order of what you'll actually run into at customer sites. Parts A and B handle DoH (block it, or translate it through to ZTR). Parts C and D apply the same skill stack to threat-intel response and compliance blocking. Unlike Labs 1–4, this is not step-by-step — each part gives you a scenario and the success criteria, and you build from memory of Labs 1–4. Progressive hints are available if you get stuck. Each part is independent (~15 min each) and assumes SSL Inspection from Lab 4 is active.
How to work the Capstone: read the scenario, look at the success criteria, then attempt the build using only what you remember from Labs 1–4. If you're stuck after a few minutes, reveal Hint 1 (approach). Still stuck, Hint 2 (where to look). Last resort, Hint 3 (exact config). You'll know you're done when all the test cases in the success criteria pass.
1 Part A — Block DoH at DNS Control
Scenario · ~15 minutes
Your security team's new policy: all DNS must be inspectable. Encrypted DNS — DoH from browsers like Firefox and Chrome — bypasses traditional DNS controls because the queries are wrapped inside HTTPS to providers like Cloudflare, Google, or NextDNS. Your task: block DoH outright so users can't tunnel their DNS through encrypted channels.
Unlike a category-based block, this match happens at the application protocol layer — DNS Control can identify DoH traffic regardless of which resolver the browser was configured to use.
Why block DoH outright? SSL Inspection can decrypt most encrypted DNS — but not all. Categories like banking, healthcare, and government are commonly excluded from SSL Inspection for legal and privacy reasons. DoH queries that ride those bypassed paths stay opaque to ZIA, so policy can't fire on them. Blocking DoH at the DNS Control layer closes that gap by forcing all DNS to come in as plaintext, which DNS Control can always evaluate.
Success criteria.
  • Firefox on the VM has DoH enabled (Settings → Privacy & Security → DNS over HTTPS → Max Protection, provider = Cloudflare).
  • After your rule is active, browsing any site in Firefox fails to resolve. The DoH path is closed.
  • DNS Insights shows the DoH attempts with Action = Block, attributed to your new rule.
  • Plaintext DNS (e.g., nslookup google.com in Command Prompt) still resolves — only DoH is blocked.

Try this without the hints first. You already have SSL Inspection on from Lab 4 — that's what gives ZIA visibility into DoH traffic in the first place.

This can be done via DNS Control policy.

2 Part B — Translate DoH to plaintext for ZTR
Scenario · ~15 minutes
Different ask, same root problem: your team doesn't want to block DoH (users have grown to expect it), but you do need DNS visibility and consistent resolver hygiene. The solution: let DoH come in, translate it at DNS Control, and resolve it through ZTR over plaintext UDP/53.
Mechanism: the endpoint sends DoH to Cloudflare's DoH endpoint. SSL Inspection decrypts the HTTPS. DNS Control sees the inner DNS query, evaluates it under policy, and the resolution proceeds through the standard NAT Control path — which is ZTR by default. The protocol downgrade from DoH to UDP is the implicit result of that policy chain.
Important: if you completed Part A, your Block DoH rule will catch this traffic first. Either disable it before you start Part B, or build Part B's rule at a higher Order. The two parts are alternative strategies, not stackable.
Success criteria.
  • Firefox with DoH enabled resolves websites normally — no Block fires on its queries.
  • In DNS Insights, the same query shows: inbound Network App = Cloudflare DNS (or similar DoH), and the resolution row has Resolver Gateway = ZTR with Server Protocol = UDP.
  • That column split is your proof: the user submitted DoH, but ZIA resolved it through ZTR in plaintext.

Three preconditions: SSL Inspection on (Lab 4), no leftover Cloudflare NAT rule from Lab 3 (tear-down was Step 7), and the Block DoH rule from Part A disabled if you built it.

This can be done via DNS Control policy.

3 Part C — Threat-Intel Response: Contain a Phishing Campaign
Scenario · ~15 minutes
It's Monday morning. Your SOC just received a TI alert: a financially-motivated actor is running a Microsoft 365 credential-harvest campaign. Three IOC domains are confirmed in the feed:
  • m365-validate-portal.com
  • onedrive-secure-doc.app
  • outlook-mfa-reset.net
Your job: contain the campaign tenant-wide using DNS Control, find every endpoint that touched the IOCs in the last 24 hours, and confirm the block isn't bypassable via DoH. You have ~15 minutes.
Note on the IOCs: these are synthetic names for the lab. DNS Control intercepts the query before resolution, so whether the upstream domain is actually registered doesn't matter — the Block fires either way.
Success criteria. When you're done, these test cases should all be true:
  • nslookup m365-validate-portal.com on the VM returns the Zscaler block IP.
  • nslookup google.com still resolves normally — your block is targeted.
  • DNS Insights filtered by the IOC domain over the last 24h surfaces every user/endpoint that hit it. Pre-activation rows are the impacted users; post-activation rows show Action = Block.
  • Loading the IOC URL in Firefox with DoH enabled still hits the block (SSL Inspection from Lab 4 decrypts the DoH).

Try this without the hints first. The skills are all from Labs 1, 2, and 4 — this is a re-application, not new material.

What primitives should you reach for?

Two questions to ask yourself:

  1. How do you teach DNS Control to recognise three specific FQDNs as a single match-target? Lab 2's Allow exception used the same primitive, just inverted.
  2. Once DNS Control matches the IOCs, what Action do you set? At what Rule Order, given that the Lab 2 Block Gambling rule already sits at Order 1?

The forensic sweep is a DNS Insights filter — same pattern as Lab 1's verification, but you're looking for who hit the IOC before activation, not after. The DoH check is just re-running the Lab 4 mental model: encrypted DNS bypasses unless something decrypts it.

Menu paths
  1. Custom URL Category: Policies → Internet & SaaS → URL Categories → + Add URL Category.
  2. DNS Control rule: Policies → Access Control → Firewall → DNS Control → + Add DNS Filtering Rule. Reference your new custom category in both Request and Response Categories. Action = Block.
  3. Forensic sweep: Logs → DNS Insights → Logs. Filter Requested Domain Contains <IOC>. Timeframe = last 24h. Each row tells you the user, location, action, and timestamp.
  4. DoH verification: SSL Inspection from Lab 4 should already be live. Open the IOC URL in Firefox (DoH on) and confirm it's still blocked. If not, revisit Lab 4 to re-activate SSL Inspection.
Concrete field values

Custom URL Category

FieldValue
NamePhishing IOCs — M365 Campaign
Super Categoryany (User-defined is fine)
Custom URLsall three IOC FQDNs from the scenario

DNS Control rule

FieldValue
Rule Order1
Rule NamePhishing Campaign Block
Rule StatusEnabled
Request Categoriesyour new custom category
Response Categoriessame
Action / Network TrafficBlock

Save the rule, click the orange Pending Activation badge, and Activate. Then run the test cases. If DNS Insights doesn't update for 2–3 min, that's normal ingest lag.

4 Part D — Compliance Blocking with a Documented Exception
Scenario · ~15 minutes
Different context: you're the security admin at a mid-size investment firm. Compliance hands you a written requirement and asks when it will be enforced:
Effective immediately, outbound DNS shall block (a) Gambling, (b) Adult Material, and (c) Cryptocurrency. Exception: the Research team may access coindesk.com for market analysis. The control must be auditable. Browser-level DNS encryption shall not allow circumvention.
Success criteria.
  • nslookup bet365.com (Gambling) and nslookup binance.com (Crypto) both return the Zscaler block IP.
  • nslookup coindesk.com resolves to real IPs — the exception works.
  • nslookup google.com still resolves normally.
  • DNS Insights filtered by your Compliance Block rule's name surfaces the blocked queries per category. A second filter by the exception rule's name surfaces only the allowed coindesk.com queries. That split is your audit-ready report.
  • Firefox with DoH still hits the block (SSL Inspection from Lab 4 is decrypting it).

Part C's pattern carries here (custom URL Category + Block rule), with one twist: the exception, modelled on Lab 2's 888.com Allow. Try without hints first.

What primitives should you reach for?

Three questions:

  1. Can one DNS Control rule block three categories at once, or do you need three rules? Check the Request Categories field carefully.
  2. Where does the exception live? You've built this pattern before — Lab 2 (888.com Allow) and Part C (IOC Block) both use the same primitive, just for different actions.
  3. Once both rules exist, what determines whether the exception wins on coindesk.com queries before the Compliance Block catches it?
Menu paths
  1. Compliance Block: DNS Control → + Add DNS Filtering Rule. One rule. Set Request + Response Categories to all three (the picker supports multi-select). Action = Block.
  2. Exception category: Policies → Internet & SaaS → URL Categories → + Add URL Category. Name it for Compliance to audit. Add coindesk.com.
  3. Exception rule: DNS Control → + Add DNS Filtering Rule. Reference your exception category. Action = Allow. Rule Order matters — remember first-match wins.
  4. Audit trail: Logs → DNS Insights → Logs. Filter by Rule Name. Two separate filters — one per rule — give you the auditor's split view.
Concrete field values

Compliance Block rule

FieldValue
Rule Order2 (below the Part C Phishing rule, or 1 if you skipped Part C)
Rule NameCompliance Block — Gambling / Adult / Crypto
Request CategoriesGambling + Adult Material + Cryptocurrency (multi-select)
Response Categoriessame three
Action / Network TrafficBlock

Exception category

FieldValue
NameCompliance Exceptions — Crypto Research
Custom URLscoindesk.com

Exception rule

FieldValue
Rule Order1 (must be above the Compliance Block)
Rule NameCompliance Exceptions — Allow Research
Request Categoriesyour new exception custom category
Action / Network TrafficAllow

Activate both. Test all five success criteria. If coindesk.com is still blocked, the Allow rule isn't at Order 1 — first-match wins.

What you just demonstrated

Four different motivations — a security team blocks DoH outright, an operations team translates DoH inbound and resolves it through ZTR, a SOC contains a phishing campaign, a compliance team enforces a regulatory rule — resolved by the same skill stack from Labs 1–4: DNS Control rules scoped on category and application service, custom URL Categories, deliberate rule ordering, DNS Insights for forensics and audit, SSL Inspection to make encrypted DNS visible. The DNS layer carries real enforcement weight when you use these in combination; you just shipped four production-ready postures without leaving the DNS stack.

Knowledge Check — DNS Control Quiz

10 real-world scenarios drawn from the deck and the labs. Answer all 10, hit Submit, and you'll see your score plus a short explanation for every question — including the ones you got right. You can retake as many times as you want.

Progress
0/10
Question 1 of 10 DNS as a control point
During an architecture review, a colleague claims DNS Control is redundant because you already inspect HTTPS with URL Filtering. What's the strongest technical rebuttal?
Question 2 of 10 App Profile vs. DNS Control
An engineer wants to exempt cnn.com from a category block by adding it to the App Profile Domain Exclusion list. As the senior admin, what's the right pushback?
Question 3 of 10 DNS Control first-match
You built a Block rule for Gambling at Order 2 and an Allow rule for a custom category containing 888.com at Order 3. 888.com is still blocked. The most direct fix?
Question 4 of 10 DNS Insights forensics
A SOC alert lands at 9:42 AM with three phishing IOC domains. You activate a DNS Control Block at 9:47 AM. The CISO asks: "Did anyone hit those domains today?" Fastest answer?
Question 5 of 10 NAT Control + DNS Gateway
Compliance requires DNS for one application to route through Quad9 instead of ZTR. Everything else continues via ZTR. What's the right config?
Question 6 of 10 DoH bypass
A user reports a DNS-Control-blocked domain loads in Firefox. Firefox DoH is on (Max Protection, Cloudflare). SSL Inspection is not yet enabled. What's happening?
Question 7 of 10 Insights resolver column
After redirecting Netflix DNS through a new DNS Gateway, some netflix.com rows in DNS Insights still show Resolver Gateway = ZTR. Most likely cause?
Question 8 of 10 Compliance exception
Compliance approves an exception: the Research team needs access to coindesk.com despite the firm-wide Cryptocurrency block. Auditable, maintainable pattern?
Question 9 of 10 Hosts file / layered controls
A Red Team demonstrates that with local Admin rights, they bypass DNS Control by editing C:\Windows\System32\drivers\etc\hosts. The CISO asks: "Why doesn't DNS Control catch that?"
Question 10 of 10 Proxy model — two evaluations
DNS Control is described as a proxy model that evaluates each transaction twice. What does the second evaluation catch that the first doesn't?
All 10 questions must be answered before you can submit.
0/10
0%
Troubleshooting

Common symptoms attendees hit during the live labs. Find your lab, find your symptom, follow the fix.

LAB 01 Get DNS Into Zscaler
chatgpt.com still absent from DNS Insights after configuring Domain Inclusion = *
Most common cause: the Save dialog closed silently and Save wasn't actually clicked. Re-edit the DNS Lab App Profile, set Domain Inclusion = *, click Save, then run ZCC tray → More → Update Policy on the VM.
Update Policy succeeded but Insights is still empty after 30 seconds
Confirm ZCC is connected (tray icon green). Confirm the policy actually updated — the App Policy line in ZCC → More should reflect the new policy version. Insights ingest is typically < 10 s; if > 60 s, refresh and verify the time window covers "now".
LAB 02 Block + Custom Allow
www.gambling.com still resolves after activating the Block Gambling rule
Three causes: (1) the rule's Request Categories field doesn't include Gambling, (2) Activate was skipped (rule shows as Pending Activation), (3) the VM has a cached DNS answer — run ipconfig /flushdns then re-test.
888.com is still blocked after creating the custom Allow rule
The Allow rule is ranked below the Block Gambling rule. NAT/DNS Control is first-match — drag the new rule to Order 1 and Activate. Also confirm the custom URL Category actually contains 888.com (open it under Policies → Internet & SaaS → URL Categories).
LAB 03 Steer DNS via NAT Control
The Cloudflare gateway doesn't appear in the NAT rule's DNS Gateway dropdown
The gateway must be created and saved before the NAT rule can reference it. Go back to Proxies & Gateways → DNS Gateways, confirm the Cloudflare row exists and was saved, then reopen the NAT rule dialog.
DNS Insights Resolver Gateway still shows ZTR after activating the Cloudflare DNS rule
The new rule is ranked below the predefined ZTR rule, OR the Action wasn't set to Redirect Request Using DoH, OR Network Services wasn't set to DNS on the Services tab. NAT Control is first-match — the rule must sit at Order 1 with the correct action. The flip is server-side — nslookup output won't look different; check Insights.
Insights Resolver Gateway shows Cloudflare only for newer queries; older rows still show ZTR
Expected. The Insights column reflects the resolver each query used at that moment. Filter to a time range AFTER your Activate to see only post-rule queries.
After deleting the rule + gateway, ZTR doesn't resume
Activate is required after Delete, just like after Save. Confirm the orange Pending Activation badge fired and you clicked Activate. Also confirm you deleted the rule before the gateway (the rule references the gateway). Then re-test with nslookup netflix.com.
LAB 04 DoH + SSL Inspection
Firefox still shows Server Not Found for gambling.com even after enabling DoH
(1) DoH provider isn't actually set — recheck Firefox preferences, ensure provider = Cloudflare (Default). (2) Firefox has cached the prior failure — close Firefox completely (not just the tab) and reopen. (3) The Zscaler root CA isn't trusted by Firefox (uses its own cert store). The lab VM should already have it; if not, import.
Firefox keeps loading gambling.com even after activating SSL Inspection
Hard reload (Ctrl+Shift+R), not soft reload — the browser cached the previously-resolved page. If still loading, check that the SSL Inspection rule action is Inspect (not Do Not Inspect or Block) and that Activate fired.
Insights doesn't show the Network App / Protocol columns
Click the column-picker icon (three vertical dots) on the Insights table header and enable DNS Tunnels & Network Apps and Protocol Type. Tenant-specific defaults vary.
CAPSTONE DNS Control in the Real World
IOC custom URL Category doesn't appear in the DNS Control rule's Categories dropdown
The custom URL Category must be saved before it shows up in the rule editor. Go back to Policies → Internet & SaaS → URL Categories, confirm the Phishing IOCs — M365 Campaign entry exists, then re-open the rule.
IOC nslookup returns NXDOMAIN instead of the Zscaler block IP
Two possibilities: (1) the rule's Request Categories field doesn't include your custom Phishing IOCs category — reopen the rule and re-save; (2) Activate was skipped (orange Pending Activation badge still showing). NXDOMAIN means the upstream domain doesn't exist; the Zscaler block produces a redirect to the block IP instead.
DNS Insights forensic filter shows no matching rows even though you know queries were made
Insights ingest can lag by 2–3 minutes — wait and re-run. Confirm the timeframe covers the query times (extend to last 24h if unsure). Confirm the filter field is Requested Domain Contains not Equals.
Part B: coindesk.com is still blocked after creating the Allow rule
DNS Control is first-match. The Allow rule must be at Order 1, above the Compliance Block rule. Also confirm the custom URL Category for the exception actually contains coindesk.com (Policies → Internet & SaaS → URL Categories).
Part D: the Compliance Block fires on coindesk.com even with the Allow rule at Order 1
Activate was skipped after creating the Allow rule. Click the orange Pending Activation badge and Activate. Also flush DNS cache (ipconfig /flushdns) before re-testing.
Command Cheat Sheet

Test commands and key configuration values for every lab. All commands run from the lab VM unless noted.

LAB 01

Get DNS Into Zscaler

Baseline + verification
nslookup chatgpt.com
Pre-fix: resolves on VM but absent from Insights. Post-fix: appears with Resolver Gateway = ZTR.
LAB 02

Block + Custom Allow

Test the block
nslookup www.gambling.com
Flush before re-testing
ipconfig /flushdns
Verify custom Allow
nslookup bet365.com nslookup 888.com
After: bet365.com times out (still Gambling), 888.com resolves (top-order Allow). Both visible in Insights.
LAB 03

Steer DNS via NAT Control

Test resolver flip
nslookup netflix.com
The Server: line in nslookup won't change — ZIA's NAT is invisible to the client. In DNS Insights: Resolver Gateway flips ZTRCloudflare, Server Protocol flips UDPDNS Over HTTPS, HTTP Status Code becomes 200 - OK.
LAB 04

DoH + SSL Inspection

No CLI — browser-driven. Recipe:
  • Firefox about:preferences → search dnsMax Protection / Cloudflare
  • Browse gambling.com in Firefox → loads (DoH bypass)
  • Browse same in Chrome → blocked (plaintext DNS)
  • Add SSL/TLS Inspection rule with Action = Inspect
  • Hard-reload Firefox (Ctrl+Shift+R) → now blocked
  • Insights: filter gambling, check Network App = Cloudflare DNS
CAPSTONE

DNS Control in the Real World

Part C — IOC block test
ipconfig /flushdns nslookup m365-validate-portal.com
Part D — Compliance + exception
nslookup bet365.com nslookup binance.com nslookup coindesk.com
Part C pattern: custom URL Category for the IOCs → DNS Control Block at Order 1 → DNS Insights filter for forensic sweep. Part D pattern: single multi-category Block (Gambling + Adult + Crypto) → custom URL Category for the exception → Allow rule at Order 1 above the Block. Audit trail in DNS Insights via Rule Name filter.
Key configuration values
Lab 1 — App Profile / DNS tab
Domain Inclusion = *
+ Exclusions: *.corp.local, *.safemarch.com, *.qradar.com
Lab 2 — Custom URL Category + DNS Control rule
Custom URLs = 888.com
Allow rule @ Order 1
Lab 3 — DNS Gateway + NAT Control rule
Gateway: Cloudflare / DoH+TCP+UDP / cloudflare-dns.com
Failure Behavior: Return Error Response
Rule action: Redirect Request Using DoH
Lab 4 — SSL/TLS Inspection Rule
Action = Inspect
Apply on client after every change
ZCC → More → Update Policy
DNS Control — The Proxy Model

ZTE contains the full chain — F/w → DNS Control → NAT Control → resolver. Auth DNS is the only thing truly outside.

DNS Control: The Proxy Model Full request and response chain through the Zero Trust Exchange. User to F/w Control to DNS Control to NAT Control to one of three destinations (ZTR, DNS Gateway, Transit). ZTR and Transit resolve recursively against the external root, TLD and Auth DNS hierarchy. DNS Gateway forwards to a 3rd-party DNS server which then performs the recursive resolution. The response returns through DNS Control which evaluates a second time, catching DNS poisoning. ZTE — ZERO TRUST EXCHANGE Policy fires TWICE per transaction — REQUEST + RESPONSE User Endpoint via ZCC / GRE F/w Control Allow port 53 DNS Control REQUEST Domain · Category RESPONSE IP · Category two evaluation points NAT Control Routes via DNAT rule ZTR Recursive (default) DNS Gateway (Object) Forwards out Transit Pass-through 3rd party DNS server DNS Resolution Root TLD Auth DNS OUTSIDE ZTE 1 2 3 4 iterative 5 6
Share Your Feedback

Two minutes to make the next version better. All numbered questions are required — the comments are optional. Your feedback is recorded locally; the instructor will collect it after the session.

Please enter a valid email address (e.g. name@example.com).
1. How useful was the session to you?*
1 = not useful10 = extremely useful
2. Did you prefer the interactive web format or a traditional PDF lab guide?*
3. Would you recommend this session to a colleague?*
1 = definitely not10 = absolutely
4. How would you rate the instructor?*
1 = poor10 = outstanding
Admin — Feedback Dashboard
Admin mode active. Feedback is stored in this browser's localStorage (no backend — submissions on other machines aren't visible here). To exit admin mode: run disableAdminMode() in DevTools console or clear the URL hash and refresh.