Wildcard DNS Doesn't Match a Deep Subdomain

`*.example.com` has an A record but `a.b.example.com` still NXDOMAINs. DNS wildcards cover exactly one label — here's the fix.

You set up wildcard DNS: *.example.com10.0.0.1. foo.example.com resolves. But a.b.example.com (a deeper subdomain) returns NXDOMAIN. This is not a bug — it is the rule. A DNS wildcard matches exactly one label, never a chain of them. *.example.com covers foo.example.com but not foo.bar.example.com. This is defined in RFC 4592, and crucially a wildcard does not cover its own subdomains either — *.example.com does not match anything below *.example.com.

Fastest fix: for every level you need covered, add another wildcard record for that exact parent. To make *.bar.example.com work, create a *.bar.example.com record alongside *.example.com. If you are on Cloudflare and proxying (orange cloud), a wildcard below the first label also needs Advanced Certificate Manager so the edge cert actually covers it (more on that below). If your subdomains are a finite, known list, skip wildcards entirely and add explicit A/CNAME records.

dig +short foo.example.com           # resolves -> first-level wildcard works
dig +short foo.bar.example.com       # NXDOMAIN -> no wildcard at the bar.example.com level

Which bucket are you in?

SymptomMost likely causeGo to
Single-level subs resolve, multi-level NXDOMAINWildcard only covers one labelCause 1, Fix steps 1-3
DNS resolves but browser shows cert errorSSL cert SAN doesn’t include the deeper nameCause 4, Fix step 5
Works DNS-only, breaks when proxied (Cloudflare)Edge cert doesn’t cover nested wildcardCause 5
Some users fail, others fineMissing AAAA (IPv6) at the levelCause 6
Resolves on one resolver, not anotherStale cache / not yet propagatedFix step 6

Common causes

Ordered by hit rate, highest first.

1. The wildcard covers only one label

*.example.com matches:

  • foo.example.com
  • bar.example.com

But NOT:

  • foo.bar.example.com
  • a.b.c.example.com

Per RFC 4592, the asterisk substitutes for a single label only, and a wildcard also “blocks itself” — it never synthesizes answers for names that sit below it in the tree.

How to spot it: single-label subdomains work, anything deeper returns NXDOMAIN or the wrong value.

dig +short foo.example.com            # resolves
dig +short foo.bar.example.com        # NXDOMAIN or wrong value

2. Each level needs its own wildcard

For a deeper level, add a wildcard whose parent is that exact level:

*.example.com       A    10.0.0.1
*.bar.example.com   A    10.0.0.1

*.bar.example.com covers x.bar.example.com but, again, not x.y.bar.example.com. If you genuinely need every depth, you would have to keep adding wildcards down each branch — which is why flattening the hierarchy (Fix step 4) is usually the better answer.

How to spot it: a multi-tenant app where customers create nested subdomains, but you only ever added the top wildcard.

3. Providers handle the records, not the matching, differently

The wildcard matching algorithm is standardized by RFC 4592, so a compliant resolver behaves the same everywhere. What differs is provider tooling: some panels let you type *.bar directly, some require you to create the intermediate zone first, and some block wildcards on proxied/CDN records. If a deeper wildcard “works” on one provider and not another, it is almost always because the working side has an explicit record you forgot you added — not because matching rules changed.

How to spot it: export the zone file from both providers and diff it. The working zone will have the extra wildcard or explicit record.

4. The SSL cert doesn’t cover the deeper name

Even with DNS resolving, a wildcard TLS cert only covers one label. A Let’s Encrypt *.example.com cert validates foo.example.com but not foo.bar.example.com — that needs a separate *.bar.example.com cert. As of June 2026, wildcard issuance from Let’s Encrypt still requires the ACME DNS-01 challenge (HTTP-01 cannot issue wildcards).

How to spot it: DNS resolves, but the browser shows NET::ERR_CERT_COMMON_NAME_INVALID. Confirm the cert’s SAN list:

echo | openssl s_client -connect foo.bar.example.com:443 -servername foo.bar.example.com 2>/dev/null \
  | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"

If the SAN shows only *.example.com, the deeper name isn’t covered.

5. Cloudflare proxy doesn’t cover a nested wildcard

Cloudflare states that “wildcards are only supported on the first label.” You can proxy a deeper wildcard — create a record with *.www in the Name field to cover *.www.example.com — but the catch is the certificate. Cloudflare’s Universal SSL covers the apex and first-level subdomains only. To proxy a wildcard below the first label (*.www.example.com), you need Advanced Certificate Manager so the edge has a matching cert; otherwise the orange-cloud request fails TLS even though DNS resolves.

How to spot it: the name works DNS-only (grey cloud) but throws a 525/handshake error or cert warning when proxied.

6. Missing AAAA record for IPv6

You added *.example.com A but no AAAA. Clients that prefer IPv6 fail on the deeper subdomain while IPv4-only clients are fine.

How to spot it: some users work, others don’t.

dig +short AAAA foo.bar.example.com   # empty while the A record resolves

Shortest path to fix

Step 1: Map the actual subdomain depth

foo.example.com          → 1 label
bar.foo.example.com      → 2 labels
baz.bar.foo.example.com  → 3 labels

Every level you want covered needs its own wildcard or an explicit record.

Step 2: Add one wildcard per level

*.example.com               A    10.0.0.1
*.foo.example.com           A    10.0.0.1
*.bar.foo.example.com       A    10.0.0.1

Tedious, but it follows the one-label rule exactly. On most panels you enter only the left part in the Name field (*, *.foo, *.bar.foo) and the zone supplies the rest.

Step 3: Or add explicit records for known subdomains

If the set is finite (not user-generated), enumerate it — no wildcard ambiguity, and SSL is simpler:

foo.example.com               A    10.0.0.1
bar.foo.example.com           A    10.0.0.1
baz.foo.example.com           A    10.0.0.1

Step 4: For multi-tenant apps, flatten the hierarchy

If you have customer.team.app.example.com, restructure to customer-team.example.com. A single one-label wildcard (*.example.com) then covers every tenant, and one wildcard cert covers them all. This is the cleanest long-term fix for user-generated subdomains.

Step 5: Get a cert that matches each level

For TLS across multiple levels you need one of:

  • Separate wildcard certs (*.example.com and *.foo.example.com), each issued via the Let’s Encrypt DNS-01 challenge.
  • A single multi-SAN cert listing each level explicitly.
  • On Cloudflare, Advanced Certificate Manager to cover proxied wildcards below the first label.

Verify after issuance:

echo | openssl s_client -connect baz.bar.foo.example.com:443 \
  -servername baz.bar.foo.example.com 2>/dev/null \
  | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"

Step 6: Test from multiple resolvers

for resolver in 8.8.8.8 1.1.1.1; do
  for sub in foo bar.foo baz.bar.foo; do
    echo -n "$sub.example.com @$resolver: "
    dig @$resolver +short "$sub.example.com"
  done
done

Every line should return your IP. An empty line means that level still has no wildcard or record (or your change hasn’t propagated — wait out the parent zone’s TTL, often 300-3600s).

How to confirm it’s fixed

  1. dig +short a.b.example.com returns your IP from at least two resolvers (8.8.8.8, 1.1.1.1).
  2. curl -sI https://a.b.example.com returns an HTTP status (not a connection or TLS error).
  3. The openssl s_client SAN check lists a wildcard that covers a.b.example.com.
  4. If proxied on Cloudflare, the same curl succeeds with the orange cloud on, not just grey.

FAQ

Why does *.example.com work for foo.example.com but not foo.bar.example.com? A wildcard substitutes for a single label only (RFC 4592). foo is one label, so it matches; foo.bar is two labels below the wildcard, so there is nothing to synthesize and you get NXDOMAIN.

Does *.example.com cover bar.example.com and everything under it? No. It covers direct children like bar.example.com, but not x.bar.example.com. A wildcard never matches names below itself — you need a separate *.bar.example.com record for that level.

Can one wildcard SSL cert cover every depth? No. A *.example.com cert covers foo.example.com only. Each deeper level (*.bar.example.com) needs its own wildcard cert or a multi-SAN cert listing the names. Let’s Encrypt wildcards must use the DNS-01 challenge.

My nested wildcard works without the proxy but breaks behind Cloudflare. Why? Universal SSL only covers the apex and first-level subdomains. A proxied wildcard below the first label (*.www.example.com) needs Advanced Certificate Manager so the edge presents a matching certificate.

Is there a way to avoid maintaining a wildcard per level? Yes — flatten the hierarchy. Replace team.customer.example.com with team-customer.example.com so a single *.example.com record and cert cover everything. For a finite list, explicit records are also simpler than nested wildcards.

Prevention

  • Design subdomain hierarchies with the one-label rule in mind; aim for <= 2 levels.
  • For multi-tenant apps, use one-label subdomains (customer-team.example.com, not team.customer.example.com).
  • For every wildcard level, plan the matching SSL strategy at the same time.
  • When adding a new subdomain level, audit DNS, the cert SAN, and CDN/proxy config together.
  • Document the wildcard structure in your DNS notes so the next engineer doesn’t trip on it.

Tags: #Troubleshooting