Standard DNS wildcard implementations (RFC 4592) only handle single-level subdomains. A typical setup like:
*.example.com. IN A 192.0.2.1
will resolve foo.example.com but fail for bar.foo.example.com. This becomes problematic when building SaaS platforms or multi-tenant systems requiring dynamic subdomains.
Here are three approaches to achieve this:
1. BIND9 View Configuration
For authoritative DNS servers using BIND9:
zone "example.com" {
type master;
file "/etc/bind/db.example.com";
allow-update { none; };
// First-level wildcard
match-clients { any; };
match-destinations { any; };
view "firstlevel" {
match-clients { any; };
recursion no;
zone "." { type hint; file "/etc/bind/db.root"; };
include "/etc/bind/named.conf.default-zones";
};
// Multi-level wildcard view
view "multilevel" {
match-clients { any; };
recursion no;
zone "example.com" {
type master;
file "/etc/bind/db.example.com.wildcard";
};
};
};
2. PowerDNS Generic Mapping
For PowerDNS with Generic MySQL backend:
-- SQL schema for wildcard records
INSERT INTO records (domain_id, name, type, content, ttl)
VALUES (
(SELECT id FROM domains WHERE name='example.com'),
'%.example.com',
'A',
'192.0.2.1',
300
);
3. Cloud Provider Specific Solutions
For AWS Route 53:
{
"Comment": "Multi-level wildcard",
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "*.example.com",
"Type": "A",
"TTL": 300,
"ResourceRecords": [{ "Value": "192.0.2.1" }]
}
},
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "*.*.example.com",
"Type": "A",
"TTL": 300,
"ResourceRecords": [{ "Value": "192.0.2.1" }]
}
}]
}
Verify with dig commands:
dig +short test.example.com
dig +short abc.def.example.com
dig +short x.y.z.example.com
- Some DNS providers limit wildcard levels
- SSL certificate challenges may require explicit SAN entries
- Caching resolvers might behave unexpectedly
While single-level wildcard DNS entries (*.example.com) are common in BIND and other DNS servers, multi-level wildcards require special handling. The standard approach only captures first-level subdomains like foo.example.com but fails for bar.foo.example.com.
Here are three implementation approaches for multi-level wildcards:
1. BIND Configuration with Regex
zone "example.com" {
type master;
file "/etc/bind/db.example.com";
allow-transfer { none; };
};
// In db.example.com:
$ORIGIN example.com.
@ IN SOA ns1.example.com. hostmaster.example.com. (
2023081501 ; Serial
3h ; Refresh
1h ; Retry
1w ; Expire
1h ) ; Minimum TTL
*.* IN A 192.0.2.1
; This captures two-level wildcards like a.b.example.com
2. PowerDNS with LUA Records
PowerDNS offers more flexible wildcard handling through LUA scripting:
-- pdns.lua.conf
function wildcardresolve(qname, qtype)
if string.find(qname, ".*%.example%.com$") then
return {
{ qname=qname, qtype="A", content="192.0.2.1", ttl=300 }
}
end
end
3. Cloud Provider Specific Solutions
Major cloud DNS services handle this differently:
- AWS Route53: Supports multi-level wildcards natively with
*.*.example.com - Cloudflare: Uses Page Rules with
*.example.com/*patterns - Google Cloud DNS: Requires individual record creation via API
For a SaaS application needing dynamic tenant subdomains at any depth:
// BIND 9.16+ configuration:
$TTL 300
@ IN SOA ns1.example.com. admin.example.com. (
2023081501 ; serial
3600 ; refresh
900 ; retry
604800 ; expire
300 ) ; minimum
; Base wildcard
* IN A 192.0.2.1
; Multi-level capture (requires BIND 9.10+)
*.sites IN A 192.0.2.1
*.*.users IN A 192.0.2.2
Verify your setup with these diagnostic commands:
dig any.thing.example.com nslookup test.demo.example.com host -t A multi.level.test.example.com
Deep wildcard DNS resolution impacts:
- DNS query response times increase ~15-20ms per additional level
- DNSSEC validation becomes more complex
- Caching behavior varies across resolvers
Important security measures for multi-level wildcards:
; Prevent DNS hijacking
*.example.com. IN CAA 0 issue "letsencrypt.org"
*.example.com. IN TXT "v=spf1 -all"
; Rate limiting for dynamic subdomains
options {
rate-limit {
responses-per-second 10;
};
}