TTechclick All lessons
Zscaler · ZPA · DNS & App DiscoveryInteractive · L1 → L3

ZPA DNS & App Discovery — Why "It Works by IP but Not by Name"

"It works when I type the IP, but fails by name." In ZPA that bug is almost never on the laptop — because the client never resolves your private app. The connector does. ZCC captures the FQDN, the broker hands it to a connector whose App Segment matches, and that connector resolves the name locally and connects. This lesson walks the DNS-and-discovery faults that live on the connector — split-DNS, wildcard precedence, source-IP anchoring, and an empty discovered-apps list — each with the exact symptom, the command that proves it, the expected output, the fix, and the check that confirms you're done.

📅 05 Jun 2026 · ⏱ 13 min · 12 scenarios · 4 SVGs · 🏷 10-Q assessment + AI Tutor inline
🎯 By the end of this lesson, you'll be able to

⚡ Quick Answer

In Zscaler ZPA the client never resolves the private app — the App Connector does. ZCC captures the FQDN, the broker picks a connector whose App Segment matches, and that connector resolves the name locally and connects. So DNS faults live on the connector host, not the laptop. This lesson fixes split-DNS & search-domain gaps, wildcard-vs-specific FQDN match precedence, source-IP-sensitive apps that see the connector's IP, and an empty discovered-apps list — each with the exact command, expected output, fix and verify step.

Read as:

Which DNS or discovery fault is it? Jump to the bucket

1

Resolution & Split-DNS

Works by IP, fails by name. Wrong resolver, no search domain, short-name mismatch.

2

Wildcard Precedence

One app breaks after a *.corp.local segment, or ZIA traffic gets pulled into ZPA.

3

Source-IP Anchoring

App rejects the user or sees the wrong IP — it sees the connector, not the user.

4

App Discovery

Discovered-apps list empty or stale; the internal DNS-server segment is missing.

The belief that costs you four hours

Most engineers see "works by IP, fails by name" and start debugging DNS on the user's laptop. Wrong — and that wrong instinct is exactly why a 10-minute fix turns into a half-day outage. In ZPA the laptop's resolver is irrelevant to a private app: the ZCC client intercepts the FQDN, the broker picks an App Connector whose App Segment matches, and the connector resolves the name locally via its own resolver and connects. The name only ever gets looked up on the connector host.

The everyday analogy: when you arrive at a gated society, you don't go knock flat-by-flat. The courier desk looks up the flat number and walks the parcel in. In ZPA the connector is the courier desk — it does the lookup, not you. So the senior move is never "fix the laptop's DNS". It's "which name does the connector resolve, with which resolver, and which segment claimed that name?" This blog teaches who-resolves-what first, then walks the 12 DNS-and-discovery scenarios that live on the connector.

Before you read — 3 questions to sit with

No scoring. Just notice which ones you can't answer yet — those are the sections to slow down on. We answer all three as you scroll.

  1. A user reaches 10.20.9.40 fine but hr.corp.local times out. Whose DNS do you check — the laptop's, or somewhere else?
  2. You add a *.corp.local App Segment and suddenly one specific app — or some internet traffic that should go to ZIA — starts behaving differently. Why?
  3. An app's access-control list is keyed to the user's source IP, but after moving to ZPA it rejects everyone. What IP is the app actually seeing?

The big picture — who actually resolves the app name

The ZPA App Connector is a lightweight Linux daemon you run next to your private apps — in your data centre, your VPC, your branch. The user's laptop never routes to your network and never resolves your app: ZCC simply captures the FQDN and hands it to the broker. The broker matches that name to an App Segment, picks a connector in the mapped group, and that connector does the DNS lookup with its own /etc/resolv.conf and reaches the app. That single fact — resolution happens at the connector — is the whole troubleshooting map for DNS and discovery.

Figure 1 — Who resolves the name: the client never does, the connector does
In ZPA the connector — not the client — resolves the private app name A horizontal map showing a user laptop with Zscaler Client Connector capturing the FQDN (it does NOT resolve it), the Zscaler broker matching the name to an App Segment and selecting a connector, and the App Connector resolving the name locally via internal DNS before reaching the private app. The client captures the name. The connector resolves it. User laptop ZCC captures FQDN does NOT resolve it "Sneha @ Infosys" hr.corp.local Zscaler Cloud Broker (ZEN) FQDN → App Segment picks the connector that should serve it "resolve this" App Connector RESOLVES the name /etc/resolv.conf 10.20.5.11 DNS 10.10.0.53 Private app hr.corp.local 172.16.9.40 ! DNS fault lives HERE — on the connector, not the laptop
The name hr.corp.local is captured by ZCC, matched to an App Segment by the broker, and resolved by the connector against internal DNS (10.10.0.53). The red marker is the only place a private-app DNS fault can live: the connector's own resolution. The laptop's DNS never enters the picture.
👉 So far: ZCC captures the name, the broker matches it to a segment and picks a connector, and the connector resolves it locally. Next: the four DNS-and-discovery buckets every fault falls into.

Your DNS & discovery toolbox — tap each card

These six are the commands and files you'll reach for in every scenario below — all run on the connector, because that's where resolution happens. Memorise the front of each card; the back tells you what it proves.

🌐
Resolver config
cat /etc/resolv.conf
tap to flip

Which DNS server does the connector use, and which search domains expand short names? If it points at a public resolver, internal app names never resolve.

🔎
Resolve from connector
dig @10.10.0.53 app.corp.local
tap to flip

Ask the internal DNS server directly. An answer here but NXDOMAIN from the default resolver = the connector is pointed at the wrong DNS. The truth test for every name fault.

✂️
Short vs FQDN
getent hosts app
tap to flip

If app fails but app.corp.local works, the connector has no search domain to expand the short name — and the user typed the short form the segment doesn't list.

🎯
Segment match
App Segments → which FQDN
tap to flip

A more-specific FQDN segment always wins over a wildcard. List overlapping segments to see which one actually claimed the name the user typed.

📍
Source IP seen
connector IP, not user IP
tap to flip

Without source-IP anchoring, the app sees the connector's IP. ACLs/licensing keyed to the user's IP break — fix with SIPA or by allowlisting the connector subnet.

🛰️
Discovery feed
wildcard segment + real traffic
tap to flip

Discovered apps only populate from a wildcard discovery segment plus real user traffic. No traffic or no wildcard segment = an empty list, not a bug.

Watch a name request flow — and see where it breaks

Before the scenarios, run this once. Press Play and watch the six stages a private-app name walks from the user typing it to the app actually answering. Each scenario below maps to exactly one of these stages going red.

▶ Resolving a private app — 6 stages

Press Play (auto-steps), or tap Next to walk it yourself. Stage 4 turns red — that's where the connector's own DNS lookup fails (wrong resolver, no search domain, missing record).

① TYPE Sneha's browser requests hr.corp.local. ZCC intercepts the FQDN — the laptop never resolves it.
② MATCH The broker matches hr.corp.local to the App Segment that claims it (most-specific wins).
③ PICK The broker selects a healthy connector in the segment's mapped connector group.
④ RESOLVE The connector resolves hr.corp.local via /etc/resolv.conf → internal DNS 10.10.0.53. This is the hop that fails most.
⑤ CONNECT Connector opens the session to the resolved IP (172.16.9.40) — using the connector's own source IP.
⑥ STITCH Broker stitches user↔app. Sneha reaches HR — and if discovery is on, the app is logged for the discovered-apps list.
Press Play to step through resolution. Watch stage ④ — it goes red to show the most common failure point: the connector's own DNS lookup.

Bucket 1 — Resolution path & split-DNS

Symptoms here all share one trait: the app works by IP but fails by name, or works with the full FQDN but fails with a short hostname. The fault is always on the connector's resolution — a wrong resolver, a missing search domain, or a name the user typed in a form the App Segment doesn't list. Your truth test is to resolve the app's name from the connector itself.

SCN-01Works by IP, fails by name — connector points at the wrong DNS
⚠ Problem / Symptom

Sneha at Infosys reaches the HR app by IP (172.16.9.40) but hr.corp.local times out. The connector is healthy and the segment is published.

◆ Likely cause(s)
  • The connector's /etc/resolv.conf points at a public/wrong DNS that can't resolve the internal zone
  • The internal DNS record is missing or points to the wrong IP
  • The app name only exists in a split-horizon internal view the connector isn't using
🔍 Diagnosis

Resolve the app name on the connector, and compare the default resolver against the internal DNS directly.

On the connector host
cat /etc/resolv.conf
dig +short hr.corp.local
dig @10.10.0.53 +short hr.corp.local
Expected output (wrong resolver)
nameserver 8.8.8.8            # public DNS — can't see corp.local
hr.corp.local: NXDOMAIN       # via default resolver
172.16.9.40                   # but the INTERNAL DNS knows it fine
🛠 Fix

Point the connector at the internal DNS server (10.10.0.53) that owns the corp.local zone, then restart the service.

Repair the resolver
echo "nameserver 10.10.0.53" | sudo tee /etc/resolv.conf
sudo systemctl restart zpa-connector
✓ Verify

dig +short hr.corp.local via the default resolver now returns 172.16.9.40; users reach the app by name.

SCN-02Short name fails, FQDN works — no search domain
⚠ Problem / Symptom

Users who type hr (the short hostname) get nothing, but hr.corp.local works. Some legacy bookmarks and scripts use the short form.

◆ Likely cause(s)
  • The connector's /etc/resolv.conf has no search corp.local line to expand short names
  • The App Segment lists only the FQDN, so the short name the user typed never matches a segment
🔍 Diagnosis
Test short vs FQDN on the connector
getent hosts hr
getent hosts hr.corp.local
grep -E "^search|^domain" /etc/resolv.conf
Expected output (no search domain)
# getent hosts hr          -> (nothing)
172.16.9.40   hr.corp.local      # FQDN resolves
# resolv.conf has NO 'search corp.local' line
🛠 Fix

Add a search domain so the connector expands short names, and define both name forms in the App Segment so either matches.

Add the search domain
echo "search corp.local" | sudo tee -a /etc/resolv.conf
# then in the portal: add BOTH 'hr' and 'hr.corp.local' to the App Segment
sudo systemctl restart zpa-connector
✓ Verify

getent hosts hr now returns 172.16.9.40; users reach the app whether they type the short name or the FQDN.

SCN-03NXDOMAIN from the connector — internal record missing
⚠ Problem / Symptom

Rahul at TCS gets "app not reachable" for a newly-stood-up app. The connector is green; the segment is correct. From the connector, the name returns NXDOMAIN even against internal DNS.

◆ Likely cause(s)

The A record for the app simply doesn't exist in the internal zone yet (new app), or it was created in the wrong zone/view. ZPA can't broker to an IP the connector can't learn.

🔍 Diagnosis
Ask internal DNS directly
dig @10.10.0.53 newapp.corp.local
nslookup newapp.corp.local 10.10.0.53
Expected output (no record)
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN
;; QUESTION SECTION:
;newapp.corp.local.   IN  A           # internal DNS has no record at all
🛠 Fix

Create the A record in the internal zone that the connector queries (or correct the zone/view). This is a DNS-team fix, not a ZPA one — but you prove it from the connector.

✓ Verify

dig @10.10.0.53 +short newapp.corp.local returns the correct IP; the brokered session now reaches the app.

Predict: a user reaches a private app fine by its IP, but the FQDN times out. The connector is green and healthy. Where do you run dig first — on the laptop, or somewhere else — and why?

On the connector, never the laptop. In ZPA the laptop never resolves the private app — the connector does. So the laptop's resolver is irrelevant. Run dig hr.corp.local and dig @10.10.0.53 hr.corp.local on the connector: if internal DNS answers but the default resolver doesn't, the connector's /etc/resolv.conf points at the wrong DNS.
Quick check · Q1 of 10

Sneha reaches 172.16.9.40 fine but hr.corp.local times out. The connector is healthy. On the connector, dig hr.corp.local returns NXDOMAIN but dig @10.10.0.53 hr.corp.local returns the IP. What's the fix?

Correct: a. Internal DNS answers but the default resolver returns NXDOMAIN — the connector is querying the wrong server. The connector resolves app names, not the laptop, so (b) is irrelevant. Repoint /etc/resolv.conf at internal DNS and restart.
App Connector Simulator ZPA Troubleshooting Simulator

Bucket 2 — Wildcard FQDN match precedence

Resolution can be perfect and an app still break — because a wildcard App Segment claimed the name. The rule the whole bucket turns on: a more-specific FQDN segment always wins over a wildcard, and a wildcard on the wrong connector/server group can quietly steal traffic that should go to ZIA or the public internet. This is the bucket engineers misdiagnose most, because the connector and DNS both look fine.

https://admin.private.zscaler.com  ·  Applications ▸ Application Segments ▸ Add
Application Segments ▸ Add Application Segment · Domains
The Domains field is where wildcard precedence is decided. The App Connector resolves these names locally — the laptop never does.
NameHR-Portal
1Domains (specific)hr.corp.local  most-specific — always wins
2Other segment (wildcard)*.corp.local  over-matches — can steal ZIA traffic
TCP Ports443
Server GroupSG-Corp-Mumbai ▾  which connectors resolve + reach it
Save
1 a specific FQDN beats the wildcard every time   2 a careless *.corp.local on the wrong group quietly captures traffic meant for ZIA.
🖥️ Recreated for clarity — your ZPA console matches this. Path: Applications ▸ Application Segments ▸ Add ▸ Domains. Pins ①② mark the two domain entries whose precedence decides which segment wins.
Figure 2 — Match precedence: the most-specific segment wins
A more-specific FQDN App Segment always wins over a wildcard segment Two App Segments claim overlapping names: a wildcard star-dot-corp-dot-local on connector group A, and a specific hr-dot-corp-dot-local on connector group B. A name request for hr.corp.local matches the specific segment and routes to group B; everything else under corp.local falls through to the wildcard on group A. A warning shows a wildcard mistakenly pulling internet traffic away from ZIA. A name the user typed: which segment claims it? Request: hr.corp.local Specific FQDN segment — WINS hr.corp.local → Connector Group B (DC-Mumbai) HR app 172.16.9.40 Wildcard segment — catch-all *.corp.local → Connector Group A (everything else) all other *.corp.local incl. ZIA over-match risk ! Too-broad a wildcard steals names that should go to ZIA / the public internet
hr.corp.local matches the specific segment and routes to Group B; everything else under corp.local falls through to the wildcard on Group A. The danger (red): a wildcard that's too broad over-matches names that should have gone to ZIA or straight to the internet.
SCN-04One app breaks after a wildcard segment is added
⚠ Problem / Symptom

Everything worked, then someone added a *.corp.local App Segment for convenience — and now one specific app (hr.corp.local) behaves differently or routes to the wrong location.

◆ Likely cause(s)

The wildcard now claims names that previously had no segment — and if it maps to a different connector/server group than the app's location, traffic is brokered through the wrong place. Worse, if there's no more-specific FQDN segment, the wildcard's group wins by default.

🔍 Diagnosis

In the portal, list segments that overlap the name and see which group each maps to. Use ZPA Diagnostics to confirm which segment/connector served the FQDN.

Portal → App Segments (overlap check)
# Segment 1: *.corp.local   -> Connector Group A (DC-Pune)
# Segment 2: (none specific for hr.corp.local)
# ZPA Diagnostics: hr.corp.local served by Group A  # wrong DC
Expected output (over-match)
hr.corp.local matched: *.corp.local (wildcard)
served by: Connector Group A (DC-Pune)   # app actually lives in DC-Mumbai
🛠 Fix

Add a more-specific FQDN segment for hr.corp.local mapped to the correct connector group — the specific segment then wins over the wildcard automatically.

✓ Verify

ZPA Diagnostics shows hr.corp.local now served by the correct group; the app behaves exactly as before the wildcard was added.

SCN-05Wildcard pulls ZIA-bound internet traffic into ZPA
⚠ Problem / Symptom

After a broad wildcard segment is published, some traffic that should go out through ZIA (or directly to the internet) starts trying to route via ZPA — users report certain SaaS or internet hostnames suddenly failing or slowing.

◆ Likely cause(s)

A wildcard like *.com or an over-broad internal pattern matches far more names than intended. ZPA claims them, but the connector can't (and shouldn't) resolve or reach public destinations — so those sessions die in ZPA instead of going to ZIA.

🔍 Diagnosis

Identify which names the wildcard captures, and confirm with ZPA Diagnostics that an internet hostname is being matched by a ZPA segment.

Portal → which segment served this FQDN
# ZPA Diagnostics on a failing SaaS host:
# saas-tool.example.com matched: *.example.com (ZPA wildcard)
# expected lane: ZIA / direct internet — NOT ZPA
Expected output (over-reach)
matched segment: *.example.com  (ZPA)
result: no app / unreachable     # ZPA can't serve a public SaaS host
🛠 Fix

Tighten the wildcard to the internal namespace only (e.g. *.corp.local, not *.com), and add specific FQDN segments for the handful of internal apps that need ZPA. Let everything else fall through to ZIA.

✓ Verify

ZPA Diagnostics shows the internet hostnames no longer match any ZPA segment; they route via ZIA/direct again and recover.

SCN-06Wildcard on the wrong connector group steals traffic
⚠ Problem / Symptom

An app in DC-Mumbai is suddenly slow or unreachable. The app, DNS, and connectors all look fine — but the FQDN is being brokered through a connector group in a different region.

◆ Likely cause(s)

A wildcard segment mapped to the wrong connector/server group claims the name. Without a more-specific FQDN segment pointing at the right group, the wildcard's group wins — even though it can't optimally (or at all) reach the app's subnet.

🔍 Diagnosis
Portal → segment → connector group mapping
# *.corp.local -> Connector Group A (DC-Pune)
# app lives in DC-Mumbai (Group B) but no specific segment exists
# ZPA Diagnostics: app served via Group A across the WAN
Expected output
db.corp.local matched: *.corp.local -> Group A (DC-Pune)
path: Mumbai user -> Pune connector -> Mumbai app   # hair-pinned
🛠 Fix

Create a specific FQDN segment for the app, mapped to the connector group that actually sits next to it. Precedence does the rest — the specific segment wins and the path straightens out.

✓ Verify

ZPA Diagnostics shows the app served by the local group; latency drops and reachability is restored.

Predict: an app worked perfectly, then someone added a *.corp.local App Segment mapped to a Pune connector group. Now that one app, which lives in Mumbai, is slow. The connectors and DNS are all healthy. What single change fixes it — without deleting the wildcard?

Add a more-specific FQDN segment for that exact app, mapped to the Mumbai connector group. A specific FQDN always wins over a wildcard, so precedence routes the app to the right group automatically — and the wildcard keeps catching everything else.
Quick check · Q2 of 10

A *.corp.local wildcard segment (Group A, Pune) and a specific hr.corp.local segment (Group B, Mumbai) both exist. A user requests hr.corp.local. Which segment serves it, and why?

Correct: b. ZPA match precedence is most-specific-wins: an exact FQDN segment beats a wildcard, so hr.corp.local routes to Group B. The wildcard only serves names that have no more-specific segment.

Bucket 3 — Source-IP anchoring for IP-sensitive apps

Resolution and precedence are correct, the app is reachable — but it rejects the user or logs the wrong source. The reason is structural to ZTNA: the app server sees the connection coming from the connector's IP, not the user's. Any ACL, licence, or geo-rule keyed to the user's source IP breaks. The decision tree below is your triage map for the whole blog; print it.

Figure 3 — Decision tree: "works by IP, fails by name" → root cause
DNS and discovery decision tree for ZPA private apps A decision tree starting from the symptom: does the app work by IP but fail by name? If yes, branch to connector resolver, short-name search domain, or missing record. If it resolves but still misbehaves, branch to wildcard precedence, source-IP anchoring, or empty discovered-apps. Works by IP, butfails by name? YES dig on the CONNECTOR (not the laptop) wrong resolver→ internal DNSSCN-01 short name only→ search domainSCN-02 NXDOMAIN→ add A recordSCN-03 NO Resolves, but wrong route / rejected / missing? wrong segment→ precedenceSCN-04..06 app rejects user→ anchor IPSCN-07..08 empty discovery→ wildcard+trafficSCN-09..12 The one rule that splits the whole tree "Fails by name" = a RESOLUTION problem on the connector (left branch). "Resolves but misbehaves" = a SEGMENT / anchoring / discovery problem (right branch). Run dig on the connector first. It saves you three hours on the wrong laptop.
Triage every name ticket here first: does it work by IP but fail by name? That single answer routes you to the left half (the connector's resolution) or the right half (segment precedence, anchoring, discovery) of every scenario in this blog.
SCN-07App rejects the user — it sees the connector's IP, not the user's
⚠ Problem / Symptom

Priya at Wipro can resolve and reach an internal app, but it rejects her — or logs the wrong source. The app's allow-list / licence is keyed to the user's office IP range, and after moving to ZPA every session looks like it comes from one IP.

◆ Likely cause(s)

In ZTNA the connector terminates the user session and opens a fresh one to the app — so the app sees the connector's source IP (e.g. 10.20.5.11), not the user's. Any ACL, geo-rule, or licence keyed to the user's IP now fails or mis-attributes.

🔍 Diagnosis

Check what source IP the app server actually logs for a ZPA session, and compare it to the connector's IP.

On the app server
# app access log for a ZPA-brokered request:
tail -f /var/log/app/access.log
ip addr show   # on the connector — note its source IP
Expected output (connector IP)
access.log: 10.20.5.11 - - "GET /hr" 403 (ACL: src not allowed)
# 10.20.5.11 = the App Connector, NOT the user's 192.0.2.x office IP
🛠 Fix

Two options: (1) allowlist the connector's subnet on the app/ACL (simplest, but loses per-user IP granularity), or (2) use Source IP Anchoring (SIPA) so the app sees a controlled, known source IP. Note: pure ZTNA can't preserve each user's original client IP — anchoring gives you a predictable one instead.

✓ Verify

The app's access log shows the expected anchored/allowlisted source IP, the 403s stop, and IP-keyed licensing counts sessions correctly.

SCN-08Licensing / geo-rule keyed to source IP breaks under ZPA
⚠ Problem / Symptom

A vendor app counts "concurrent IPs" for licensing, or applies a geo/IP rule. Under ZPA it either over-counts (everyone shares the connector IP looks like one user) or blocks users because the connector's IP isn't in the licensed range.

◆ Likely cause(s)

The app's logic assumes the source IP identifies the user or their location. Behind ZPA, the source is always the connector — so per-user IP assumptions collapse.

🔍 Diagnosis
Confirm the anchored source
# on the app/licence server, inspect the source seen for several users:
grep "license check" /var/log/app/license.log | tail
Expected output
license: src 10.20.5.11 (connector)  user=sneha  -> OK
license: src 10.20.5.11 (connector)  user=rahul  -> counted as SAME IP
# IP-based seat counting is meaningless behind ZPA
🛠 Fix

Allowlist the connector subnet in the app's licensed range so the connector IP is accepted, and move seat-counting to a user identity signal (ZPA passes the authenticated user), not source IP. Use Source IP Anchoring where the vendor must see a specific public egress IP.

✓ Verify

Licensed users are admitted, seat counts track real users (by identity), and the geo/IP rule passes for the anchored source.

Quick check · Q3 of 10

An internal app's ACL only allows the office IP range. After cutover to ZPA it 403s every user, and its access log shows source 10.20.5.11 for all of them. What is 10.20.5.11, and what's the right fix?

Correct: b. In ZTNA the connector terminates and re-opens the session, so the app sees the connector's source IP for every user. Allowlist that subnet on the ACL, or use Source IP Anchoring (SIPA) to present a controlled known IP. ZPA can't preserve each user's original client IP.

Bucket 4 — Application discovery

Everything resolves and routes correctly — but the discovered-apps list is empty or stale, so you can't see what's actually being accessed. Discovery isn't broken; it has prerequisites. It needs the feature enabled, a wildcard discovery segment, and — crucially — real user traffic to observe. No traffic, no discovery. This bucket also covers making your internal DNS server itself reachable through ZPA.

SCN-09Discovered-apps list is empty — discovery isn't enabled
⚠ Problem / Symptom

You open the discovered-applications view expecting to see what users access — and it's empty. Users are reaching apps successfully, so the connectors clearly work.

◆ Likely cause(s)
  • Application discovery is simply not enabled in the tenant
  • There's no wildcard discovery segment for the connector to observe traffic against
  • Discovery is on, but users aren't yet sending traffic through the relevant segment
🔍 Diagnosis

In the portal, confirm discovery is enabled and that a wildcard segment exists for the namespace you expect to discover.

Portal → discovery prerequisites
# 1. Application discovery feature: ENABLED?
# 2. Wildcard discovery segment e.g. *.corp.local : exists + access policy?
# 3. Are users actually sending traffic to *.corp.local names yet?
Expected output (not configured)
discovery: OFF
wildcard discovery segment: none
=> discovered-apps list will stay empty by design
🛠 Fix

Enable application discovery, create a wildcard discovery segment (e.g. *.corp.local) with an access policy for the target users, then let real traffic flow. ZPA observes the interactions and populates the list.

✓ Verify

After real user traffic flows for a while, the discovered-apps list begins to populate with the FQDNs/IPs users actually hit.

SCN-10Discovery on, but list stays empty — no real traffic yet
⚠ Problem / Symptom

Discovery is enabled and a *.corp.local wildcard segment exists, but nothing shows up. The team suspects a bug.

◆ Likely cause(s)

Discovery is traffic-driven: it learns apps by watching real user sessions. If users haven't been assigned to the discovery segment, or simply haven't accessed anything under it yet, there's nothing to learn. An empty list is the expected state, not a fault.

🔍 Diagnosis
Portal → access policy + activity
# Access policy: do target users actually MATCH the discovery segment?
# Are there recent allowed sessions to *.corp.local in the logs?
Expected output
discovery segment *.corp.local: 0 sessions in last 24h
=> nobody has generated traffic to learn from yet
🛠 Fix

Confirm the access policy lets the right users reach the discovery segment, then drive a representative set of users to actually use their apps. Give it time — discovery accumulates as traffic flows.

✓ Verify

As sessions to *.corp.local names appear in the logs, matching apps begin showing in the discovered-apps list.

SCN-11Promote discovered apps into defined segments
⚠ Problem / Symptom

Discovery is working and the list is full — but everything is still being served by the broad wildcard, so you have no per-app policy, logging, or precedence control.

◆ Likely cause(s)

A wildcard discovery segment is meant to be a starting point. Leaving every app on the wildcard gives you no granularity — and no way to route a specific app to the right connector group (precedence only kicks in once a specific segment exists).

🔍 Diagnosis
Portal → discovered apps → review
# discovered: hr.corp.local, payroll.corp.local, wiki.corp.local ...
# all currently served by the *.corp.local wildcard
# group/owner unknown for several -> need to classify
Expected output
3 business apps identified, 5 to evaluate with app owners
=> promote the known ones to defined FQDN segments
🛠 Fix

For each identified app, create a defined (specific) FQDN segment mapped to the correct connector group, with its own access policy. The specific segment wins over the wildcard by precedence; engage app owners to classify the ambiguous ones.

✓ Verify

ZPA Diagnostics shows each promoted app served by its specific segment/group; per-app policy and logging now work, and the wildcard only catches the long tail.

SCN-12Make internal DNS reachable through ZPA (the DNS-server segment)
⚠ Problem / Symptom

A subset of clients or services need to query the internal DNS server itself over ZPA, but they can't — name resolution that depends on reaching 10.10.0.53 fails for those flows.

◆ Likely cause(s)

The internal DNS server is just another private resource — if there's no App Segment that brokers traffic to it (TCP/UDP 53 to 10.10.0.53), ZPA won't carry those queries. Don't confuse this with the connector's own resolution, which uses the host's /etc/resolv.conf directly.

🔍 Diagnosis
Confirm whether DNS is brokered
# Is there an App Segment for the DNS server?
# e.g. 10.10.0.53  ports: TCP/UDP 53  -> connector group near it
Expected output (missing segment)
no App Segment claims 10.10.0.53 / port 53
=> ZPA cannot broker queries to the internal DNS server
🛠 Fix

Create an App Segment for the internal DNS server (its IP or FQDN, ports TCP/UDP 53), mapped to a connector group that sits next to it, with an access policy for the clients that need it.

✓ Verify

The dependent clients can resolve names that require the internal DNS server over ZPA; the brokered DNS flow shows up in the logs against the new segment.

Figure 4 — One-glance cheat-sheet: top symptom → first move
DNS and discovery cheat-sheet: symptom mapped to the first move A grid of six cheat-sheet tiles mapping a top DNS or discovery symptom to the first move: works by IP fails by name to dig on the connector, short name fails to add a search domain, app breaks after a wildcard to add a specific FQDN segment, app rejects the user to check the source IP and anchor it, discovered list empty to enable discovery plus a wildcard segment, internal DNS unreachable to add a DNS-server app segment. When the name ticket lands — do THIS first Works by IP, not name dig @10.10.0.53 app.fqdnon the CONNECTORwrong resolver? missing record? Short name fails grep search /etc/resolv.confadd 'search corp.local'+ both forms in segment App broke after wildcard Add a specific FQDNsegment → right groupmost-specific wins App rejects the user app sees CONNECTOR IPallowlist subnet / SIPAACL keyed to user IP? Discovered list empty enable discovery +wildcard segment + trafficno traffic = no discovery Internal DNS unreachable App Segment for 10.10.0.53ports TCP/UDP 53broker the DNS server too Golden order: resolve on connector → search domain → segment precedence → anchor IP → discovery The client never resolves the app — the connector does. Run dig on the connector before you touch anything else.
Stick this on the wall. Six symptoms, the one first move each, and the golden rule that decides every ZPA name ticket: the connector resolves, not the laptop.
👉 So far: all 12 scenarios sort into 4 buckets — resolution, wildcard precedence, source-IP anchoring, discovery. The aha: "fails by name" is a resolution problem on the connector; "resolves but misbehaves" is a segment/anchoring/discovery problem. Name the side first.

Predict: you enabled application discovery and built a *.corp.local wildcard segment yesterday, but the discovered-apps list is still empty this morning. The connectors are healthy and users reach apps fine. Bug or expected — and what makes the list fill?

Expected, not a bug. Discovery is traffic-driven — it learns apps only by observing real user sessions against the wildcard discovery segment. If the right users aren't matched by the access policy, or simply haven't accessed those apps yet, there's nothing to learn. Confirm the policy and let representative traffic flow; the list fills as sessions accrue, then you promote the known apps to specific FQDN segments.
Quick check · Q4 of 10

A few clients need to query the internal DNS server (10.10.0.53) over ZPA, but those queries fail. Connectors are healthy and other apps resolve fine. What's the fix?

Correct: c. The internal DNS server is just another private resource — ZPA only brokers what an App Segment declares. Without a segment for 10.10.0.53 on TCP/UDP 53, those queries are never carried. The connector's own /etc/resolv.conf (b) governs the connector's resolution, not what ZPA brokers for clients.
App Connector Simulator ZPA Troubleshooting Simulator

🤖 Ask the ZPA DNS & Discovery Tutor

Tap any question — instant, scoped to this lesson. The kind of thing you'd ask after reading.

Pre-curated from Zscaler docs + community threads. For deeper/live questions, paste your config into chat.techclick.in.

✍️ Explain it back (generation effect)

In two lines: why is "it works by IP but not by name" almost never a laptop-DNS problem in ZPA? Type your answer first — then reveal the expert version and compare.

Expert answer: In ZPA the laptop never resolves a private app — ZCC just captures the FQDN, the broker matches it to an App Segment, and the connector resolves the name with its own /etc/resolv.conf. So a name fault lives on the connector (wrong resolver, no search domain, missing record), and the laptop's DNS is irrelevant. You run dig on the connector, not on the laptop.
🎁 Teach a friend

Tap to generate a one-liner you can paste to a teammate stuck on a "works by IP, fails by name" ZPA app.

"Quick tip: in ZPA the laptop never resolves the private app — the connector does. So for 'works by IP, fails by name', SSH to the connector and run dig app.corp.local + dig @internal-dns app.corp.local. Wrong resolver, no search domain, or a missing record — fix it there. And remember: a specific FQDN segment always beats a wildcard. — learned this on ai.techclick.in"
✓ You're set — 3 micro-questions on Day 1 / 7 / 30.

📖 Glossary

App Connector
A lightweight Linux daemon (zpa-connector) deployed next to your private apps. It — not the user's laptop — resolves the app's name and connects.
ZPA
Zscaler Private Access — connects users to private apps over the Zscaler cloud, no network-level VPN.
ZCC (Client Connector)
The agent on the user's device. It captures the app FQDN and forwards it to Zscaler — it does not resolve the private app.
Split-DNS
The same name resolving to different answers for internal vs external clients. The connector must use the internal view to reach private apps.
Search domain
A suffix (e.g. corp.local) in /etc/resolv.conf that lets the connector expand a short hostname (hr) into an FQDN (hr.corp.local).
Application Segment
The portal object declaring which domains/ports an app uses; the broker uses it to pick which connector resolves and reaches the app.
Wildcard / match precedence
A *.corp.local segment catches many names, but a more-specific FQDN segment always wins over a wildcard.
Source IP Anchoring (SIPA)
Presents a controlled, known source IP to the app so IP-based ACLs/licensing keep working — because by default the app sees the connector's IP, not the user's.
Application Discovery
A traffic-driven feature: a wildcard discovery segment plus real user traffic lets ZPA learn which apps users access, so you can promote them to defined segments.

🎓 Prove it — 10-question assessment

Q1–Q4 above already count. Answer Q5–Q10 below, then Submit. Pass = 70% (7/10). Passing marks this lesson complete on your profile.

Q5 · Remember

In ZPA, which component actually performs the DNS lookup for a private application's name?

Correct: c. ZCC only captures the FQDN and the broker only matches it to a segment and picks a connector — the connector does the actual lookup with its local resolver. That's why every private-app name fault lives on the connector, not the laptop.
Q6 · Analyze

A user reaches an app by IP but the FQDN times out. On the connector, dig app.corp.local returns NXDOMAIN while dig @10.10.0.53 app.corp.local returns the IP. Root cause?

Correct: a. Internal DNS answers but the connector's default resolver returns NXDOMAIN — the connector is querying the wrong server. Repoint its /etc/resolv.conf at internal DNS. The laptop (b) and broker (c) never resolve the app; a port range (d) wouldn't cause NXDOMAIN.
Q7 · Analyze

A user types the short hostname hr and gets nothing, but hr.corp.local works. On the connector, getent hosts hr returns nothing and /etc/resolv.conf has no search line. What's the complete fix?

Correct: d. Two gaps: no search domain to expand the short name on the connector, and the segment lists only the FQDN. Fix both — add search corp.local and list both name forms. (a)(b) are unrelated; (c) is false — short names work once the search domain and segment cover them.
Q8 · Analyze

A *.corp.local wildcard segment (Group A) and a specific hr.corp.local segment (Group B) both exist. ZPA Diagnostics shows hr.corp.local being served by Group A. Most likely explanation?

Correct: b. A more-specific FQDN always wins over a wildcard — so if the wildcard is serving hr.corp.local, the specific segment isn't an active match (disabled, wrong policy, or not published). (a) inverts the rule; clock (c) and DNS (d) don't decide segment precedence.
Q9 · Evaluate

A vendor app licences by "concurrent source IPs". After ZPA cutover it counts every user as one IP (the connector's), under-counting seats — and rejects users whose connector IP isn't in the licensed range. Best design response?

Correct: c. The app sees the connector's IP for everyone, so IP-based seat counting is structurally meaningless behind ZTNA. Allowlist the connector subnet, count by identity, and use SIPA when a specific egress IP is mandatory. VPN (a) abandons zero-trust; (b)(d) are non-starters.
Q10 · Evaluate

A team turned on application discovery and built a *.corp.local wildcard segment, but after a week the discovered-apps list is still nearly empty. Users access apps daily. What's the best conclusion and next step?

Correct: d. Discovery is traffic-driven: it only learns from real sessions matched to the wildcard discovery segment. A nearly-empty list after a week means the right users aren't reaching that segment — fix the access policy, not the connectors. Deleting the wildcard (c) removes discovery entirely; more connectors (b) don't help.
Lesson complete — saved to your profile.
Almost! You need 70% (7 of 10) — re-read the bucket that tripped you up and tap "Try again".

📚 Sources

  1. Zscaler Help — Networking Deployed App Connectors (the connector resolves app DNS names and enumerates each resolved IP as a load-balanced server). help.zscaler.com/zpa/networking-deployed-connectors
  2. Zscaler Help — About Applications & About Application Segments Settings (wildcard vs explicit FQDN; most-specific match wins). help.zscaler.com/zpa
  3. Zscaler Help — Configuring Defined Application Segments (domains, short names, DNS-server segments). help.zscaler.com/zpa/configuring-defined-application-segments
  4. Zscaler Community (Zenith) — Zscaler Private Access and resolving wildcard DNS. community.zscaler.com/t/…/14155
  5. Zscaler Help — Understanding / Configuring Source IP Anchoring (the destination sees the App Connector's IP; preserving IP-based controls). help.zscaler.com/zpa/understanding-source-ip-anchoring-direct
  6. Zscaler Reference Architecture — Zero Trust App Segmentation with ZPA (start with wildcard discovery segments + access policy, learn from real traffic, then define granular segments). help.zscaler.com/downloads/zpa/reference-architecture
  7. Zscaler Help — Troubleshooting App Connectors (connector-side DNS diagnosis). help.zscaler.com/zpa/troubleshooting-app-connectors
  8. Zscaler Academy — ZDTA Certification blueprint (App Segments, DNS resolution, application discovery). zscaler.com/zscaler-cyber-academy

What's next?

You can now diagnose any ZPA name or discovery fault. Go deeper: the full troubleshooting playbook ties resolution into enrollment, tunnel, and health — and the App Segments lesson covers the domain sets, ports, and server-group mapping these DNS fixes plug into.

— Techclick Team