Configuring Bind DNS for Local Networks is not a common setup but for some scenarios it can be a good solution
This article tries to present a working solution on how to configure the Bind DNS server for serving local domains or both internet real domains and local domains at once. It also cover how to serve wildcard domains locally.
Setup a local DNS server that will resolve internet real domains and local domains:
There are many options to run a a local network DNS server for the purpose explained in this article. However the most popular DNS Servers are: Bind, Unbound, Unwind. This article will explain how to configure the Bind DNS Server only.
For software development purposes or simply to easy handle local network only domains there are situations where a local TLD like
.loc
have to be used. Thus, the DNS server used by the entire local network must be solving both: internet real domains and local domains, ending with .loc. For this situation perhaps the most simple is to go with Unbound because is more simple to configure. But Unbound can't handle wildcard domains in a realistic manner thus this article will focus on solving this using Bind. Note that the Unwind server is mostly just a solver not a real DNS server.All the below samples are written for the internal network 192.168.1.1 - 192.168.1.254 and should be adapted by your needs. The Bind server must be configured in the below scenario on the first host 192.168.1.1 and all the rest of computers in the internal network should use only the 192.168.1.1 as the DNS resolver in order to solve also local domains not only the internet real domains.
Sample Bind configuration named.conf to resolve both: internet real domains and local .loc domains
;# Sample Configuration for Bind 9 @ /etc/bind/named.conf
;# resolve: internet real domains and local domains .loc
acl clients {
localnets;
127.0.0.1;
::1;
};
options {
directory "/tmp"; // working directory, inside the /var/named chroot ; must be writable by _bind
version ""; // remove this to allow version queries
listen-on { any; };
listen-on-v6 { any; };
empty-zones-enable yes;
recursion yes;
allow-recursion { clients; };
dump-file "/var/bind/bind_cache_dump.db";
dnssec-validation auto;
};
// Standard zones
zone "." {
type hint;
file "/etc/db.root";
};
zone "localhost" {
type master;
file "/etc/db.local";
allow-transfer { localhost; };
};
zone "127.in-addr.arpa" {
type master;
file "/etc/db.127";
allow-transfer { localhost; };
};
zone "0.in-addr.arpa" {
type master;
file "/etc/db.0";
allow-transfer { localhost; };
};
zone "255.in-addr.arpa" {
type master;
file "/etc/db.255";
allow-transfer { localhost; };
};
// Custom zones, Local Network: 192.168.1.1 - 192.168.1.254
zone "1.168.192.in-addr.arpa" {
type master;
file "/etc/bind-domains/db.192.168.1";
allow-transfer { localhost; };
};
zone "loc" {
type master;
file "/etc/bind-domains/loc.hosts";
allow-transfer { localhost; };
};
; #END
Sample Bind configuration db.192.168.1 for reverse local DNS
;# Sample Configuration for Bind 9 @ /etc/bind-domains/db.192.168.1
; reverse DNS for Local Network: 192.168.1.1 - 192.168.1.254
$TTL 12H
@ IN SOA localhost. root.localhost. (
2022083101 ; serial
8H ; refresh (8 hours)
2H ; retry (2 hours)
7D ; expire (1 week)
12H ; minimum (12 hours)
)
@ IN NS localhost.
1 IN PTR router.loc.
2 IN PTR websites.loc.
3 IN PTR repos.loc.
4 IN PTR workstation1.loc.
5 IN PTR workstation2.loc.
6 IN PTR workstation3.loc.
; ...
103 IN PTR workstation100.loc.
; ...
253 IN PTR printserver.loc.
254 IN PTR backup.loc.
; #END
After setting the above configuration and restart Bind server, the reverse DNS for the local network should work as follows, from any computer on the local network (example):
$ host 192.168.1.4
4.1.168.192.in-addr.arpa domain name pointer workstation1.loc.
$ host 192.168.1.2
2.1.168.192.in-addr.arpa domain name pointer websites.loc.
$ host 192.168.1.253
253.1.168.192.in-addr.arpa domain name pointer printserver.loc.
$ host 192.168.1.254
254.1.168.192.in-addr.arpa domain name pointer backup.loc.
Sample Bind configuration loc.hosts for local DNS
;# Sample Configuration for Bind 9 @ /etc/bind-domains/loc.hosts
; DNS for Local Network: 192.168.1.1 - 192.168.1.254
$TTL 12H
loc. IN SOA ns1.loc. root.mail.loc. (
2022083107 ; serial
8H ; refresh
2H ; retry
7D ; expire
12H
)
IN NS ns1.loc.
IN A 192.168.1.1
IN MX 1 mail.loc.
ns1 IN A 192.168.1.1
mail IN A 192.168.1.1
router IN A 192.168.1.1
websites IN A 192.168.1.2
repos IN A 192.168.1.3
workstation1 IN A 192.168.1.4
; ...
workstation100 IN A 192.168.1.103
; ...
printserver IN A 192.168.1.253
backup IN A 192.168.1.254
*.loc IN CNAME websites.loc.
; #END
After setting the above configuration and restart Bind server, the DNS for the local network should work as follows, from any computer on the local network (example):
$ ping ns1.loc
PING ns1.loc (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: icmp_seq=0 ttl=255 time=0.022 ms
$ ping mail.loc
PING mail.loc (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: icmp_seq=0 ttl=255 time=0.024 ms
$ ping router.loc
PING router.loc (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: icmp_seq=0 ttl=255 time=0.021 ms
$ ping websites.loc
PING websites.loc (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=255 time=0.026 ms
$ ping repos.loc
PING repos.loc (192.168.1.3): 56 data bytes
64 bytes from 192.168.1.3: icmp_seq=0 ttl=255 time=0.025 ms
$ ping workstation1.loc
PING workstation1.loc (192.168.1.4): 56 data bytes
64 bytes from 192.168.1.4: icmp_seq=0 ttl=255 time=0.028 ms
$ ping workstation100.loc
PING workstation100.loc (192.168.1.103): 56 data bytes
64 bytes from 192.168.1.103: icmp_seq=0 ttl=255 time=0.025 ms
$ ping printserver.loc
PING printserver.loc (192.168.1.253): 56 data bytes
64 bytes from 192.168.1.253: icmp_seq=0 ttl=255 time=0.021 ms
$ ping backup.loc
PING backup.loc (192.168.1.254): 56 data bytes
64 bytes from 192.168.1.254: icmp_seq=0 ttl=255 time=0.020 ms
As you can see above, the last line in the loc.hosts file is
*.loc IN CNAME websites.loc.and this will do the trick of solving any other .loc domain non explicit set to
websites.loc
which is 192.168.1.2
as above. If you don't need this feature, just remove or uncomment this line.Why is this feature useful ? Imagine you will have a lot of websites in development, hosted on
websites.loc
computer under Apache. By example:website-1.loc
website-2.loc
website-n.loc
$ ping website-1.loc
PING website-1.loc (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=255 time=0.032 ms
$ ping website-2.loc
PING website-2.loc (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=255 time=0.030 ms
$ ping website-n.loc
PING website-n.loc (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=255 time=0.031 ms
Explanation
The wildcard example above will solve all to the IP address
192.168.1.2
thus there is no need to modify the Bind configuration each time a new development website is configured on the Apache server on the 192.168.1.2
computer. Plus, there is no need to reserve a separate IP for each website that is coming in development for a short period of time. Apache can serve any domain .loc configured explicit in the loc.hosts or any other domain not explicit configured but ending in .loc when using the wildcard so this makes the things much more simply to manage.IMPORTANT
In the above setup the last line (if needed) must be exactly *.loc IN CNAME websites.loc. and not *.loc. IN CNAME websites.loc. or * IN CNAME websites.loc.. This is because or will work the same with one unexpected exception: they will solve any other non-existing domains as
*.loc. IN CNAME websites.loc.
* IN CNAME websites.loc.
192.168.1.2
not only the domains ending in .loc which is very tricky and not explained here why ... and actually nobody wants that ! There is a very subtle difference, watch out ! Use *.loc IN CNAME websites.loc.exactly as it is or remove the line from loc.hosts if this feature (wildcard sub-domains) is not needed.
Optional Feature - local wildcard domains .loc - Set Apache Virtual Hosts with wildcard sub-domains
Modify Apache's configuration on 192.168.1.2 and add the following settings:
# /etc/apache2/virtual-hosts.conf
# add the following to the Apache's Virtual Host configuration
<VirtualHost *:80>
ServerAdmin webmaster@mail.loc
VirtualDocumentRoot /var/www/htdocs/sites/%-2/web
DocumentRoot /var/www/htdocs
ErrorLog "logs/error_log"
CustomLog "logs/access_log" common
</VirtualHost>
Create the following directories under apache web root like:
/var/www/htdocs/sites/website-1/web/
/var/www/htdocs/sites/website-2/web/
/var/www/htdocs/sites/website-n/web/
Create a sample
index.htmlfile in
/var/www/htdocs/sites/website-1/web/as /var/www/htdocs/sites/website-1/web/index.html with the following content
<h1>Website-1</h1>
. Restart Apache, use a web browser and test: http://website-1.loc/ and you should be able to see the Website-1
text served. If does not work review all the above setup steps, restart Bind and Apache and test again.