4.55

Configure Bind DNS for Local Networks

Image
How to configure the Bind DNS server for local networks to serve both: internet real domains and local domains. Optional use local wildcard .loc domains to serve development websites with Apache HTTP Server.

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.

(c) 2022 w3soft.org, license: GPLv3 learning resources for software development and operating systems administration configuration Bind DNS Server bind conf

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

(c) 2022 w3soft.org, license: GPLv3 learning resources for software development and operating systems administration configuration Bind DNS Server bind conf

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.


(c) 2022 w3soft.org, license: GPLv3 learning resources for software development and operating systems administration configuration Bind DNS Server bind conf

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 *.loc. IN CNAME websites.loc. or * IN CNAME websites.loc. will work the same with one unexpected exception: they will solve any other non-existing domains as 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.


(c) 2022 w3soft.org, license: GPLv3 learning resources for software development and operating systems administration configuration Apache HTTP Server apache conf

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.html file 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.