BIND is failing to serve all zones when configured with views, specifically when some zones are explicitly listed in a view but others are not. This indicates that BIND’s view matching logic is not falling back to a default view as expected for unlisted zones, or that the default view itself is misconfigured.
Cause 1: Missing default-view Configuration
The most common reason for this is a missing or incorrectly named default-view in your named.conf file. When a query arrives for a zone not explicitly listed in any view, BIND looks for a view named default. If it doesn’t find one, it doesn’t know where to serve the zone from.
Diagnosis:
Check your named.conf (or included files) for a view "default" { ... }; block.
Fix:
Ensure you have a view "default" { ... }; block defined. This view should contain the zones that should be served to clients not matched by any other specific view. If you have other views, make sure this default view is present and contains your common zones.
view "internal" {
match-clients { internal_nets; };
zone "example.com" { type master; file "zones/db.example.com.internal"; };
zone "internal.example.com" { type master; file "zones/db.internal.example.com"; };
};
view "external" {
match-clients { any; };
zone "example.com" { type master; file "zones/db.example.com.external"; };
};
// This is the crucial part for zones not explicitly in "internal" or "external"
view "default" {
match-clients { any; };
zone "some.other.zone" { type master; file "zones/db.some.other.zone"; };
// If you want ALL zones not explicitly matched to be served from here,
// you might need to include them here or use a wildcard.
// However, it's generally better to be explicit.
};
Why it works: BIND iterates through views, matching the client’s IP address. If no explicit view matches, it falls back to the default view. If default isn’t defined, it has no fallback and cannot serve the zone.
Cause 2: default-view is Not the Last Defined View
BIND processes views in the order they appear in the configuration file. If your default view is defined before other more specific views that might also match the client, BIND might stop processing and use the default view even if a more specific view would have matched later.
Diagnosis:
Examine the order of your view blocks in named.conf.
Fix:
Place the default view block last in your named.conf file. This ensures that more specific views are evaluated first, and only if no other view matches will BIND consider the default view.
view "internal" {
match-clients { internal_nets; };
zone "example.com" { type master; file "zones/db.example.com.internal"; };
};
view "external" {
match-clients { any; };
zone "example.com" { type master; file "zones/db.example.com.external"; };
};
// Ensure this is the LAST view block
view "default" {
match-clients { any; };
zone "public.zone" { type master; file "zones/db.public.zone"; };
};
Why it works: BIND checks views sequentially. By placing default last, it acts as a true fallback, only being used when no preceding, more specific match-clients criteria are met.
Cause 3: Incorrect match-clients in default-view
If your default view’s match-clients directive is too restrictive, it might prevent BIND from serving zones even when it’s supposed to be the fallback. For example, if default uses match-clients { localnets; }; and a client outside of localnets queries for a zone not in any other view, the default view won’t match.
Diagnosis:
Review the match-clients statement within your default view.
Fix:
For the default view, which is intended as a fallback, match-clients { any; }; is usually the correct directive.
view "default" {
// This ensures it matches any client that didn't match a previous view
match-clients { any; };
zone "fallback.zone" { type master; file "zones/db.fallback.zone"; };
};
Why it works: match-clients { any; } is a universal match, ensuring that if no other view matches, the default view will be applied to any client.
Cause 4: Zone Missing from All Views (Including Default)
It’s possible that a zone is simply not defined in any view, not even the default view. BIND will not serve a zone that it doesn’t know about.
Diagnosis:
Check your named.conf and all included files to ensure the zone in question is explicitly listed in at least one view block.
Fix:
Add the zone to the appropriate view. If it’s a zone that should be served to everyone not caught by a specific view, add it to the default view.
view "default" {
match-clients { any; };
zone "missing.zone" { type master; file "zones/db.missing.zone"; }; // Add the zone here
};
Why it works: BIND requires zones to be declared within a view to be served. Adding the zone to the default view makes it available to clients that don’t match any other view.
Cause 5: allow-query or allow-recursion Restrictions in default-view
Even if the default view matches the client, specific allow-query or allow-recursion directives within that view might be preventing the zone from being served or recursion from being performed for that zone.
Diagnosis:
Inspect allow-query and allow-recursion directives within your default view.
Fix:
Ensure that allow-query { any; }; (or an appropriate ACL) and allow-recursion { any; }; (or an appropriate ACL) are present and permissive enough in your default view if you intend for it to serve zones to all clients.
view "default" {
match-clients { any; };
allow-query { any; }; // Allow queries from anyone
allow-recursion { any; }; // Allow recursion for anyone
zone "public.zone" { type master; file "zones/db.public.zone"; };
};
Why it works: These directives explicitly control who can query the server and who can use it for recursive lookups. Setting them to any in the default view allows all clients to access its zones.
Cause 6: Incorrect match-clients in Specific Views Leading to Unexpected Fallback
Sometimes, the issue isn’t with the default view itself, but with how specific views are configured. If match-clients in a specific view is too broad or incorrectly defined, it might inadvertently not match a client that you expect it to. This client then falls through to the default view, and if the zone isn’t there, it appears as if the default view isn’t working.
Diagnosis:
Carefully review the match-clients directives in all your specific views. Are they correctly defining the IP ranges or ACLs they are intended for?
Fix:
Correct the match-clients directive in the specific view that is failing to match. For example, if a view meant for 192.168.1.0/24 was accidentally configured with match-clients { 192.168.0.0/16; }, clients from 192.168.1.50 might not be matched by that view.
// Incorrect: Too broad, might not match specific intent
// view "internal" {
// match-clients { 192.168.0.0/16; };
// zone "example.com" { type master; file "zones/db.example.com.internal"; };
// };
// Corrected: Matches the intended subnet
view "internal" {
match-clients { 192.168.1.0/24; }; // Corrected match-clients
zone "example.com" { type master; file "zones/db.example.com.internal"; };
};
Why it works: By ensuring that match-clients accurately reflects the intended audience for each view, you prevent clients from being incorrectly routed to the default view when they should have been served by a more specific one.
After fixing these issues, the next error you might encounter is related to zone transfer failures if any of your zone files have incorrect syntax or permissions.