BIND DNS – Configure BIND as Forwarder Only with Encrypted RPZ Blacklist/Whitelist

binddebiandnsdnscryptrpz

My setup is getting more complex, generally I tend to divide things in pieces and assemble them together by myself. But it seems this time I need more help to get the whole gears working together. That's why I was requested by user @Rui F Ribeiro to ask this one as a separate question.


What I'm trying to achieve? Basically what I found called on the internet as DNS Firewall.
I need a BIND server configured with this features:

  • It want it to being able to FORWARD by default all the requests to an external DNS (in my case OpenDNS: 208.67.222.222, 208.67.220.220)
  • It must NOT for and for any case query the ROOT-SERVERS, because OpenDNS have some useful function of domain blocking/manipulating. So, if my bind server starts to ask things to OpenDNS and Root Servers randomly I will have different results each time. (note: this forward must be done in encrypt mode for various reasons, including not getting intercepted and further manipulated by other servers in between)
  • The bind server also has to serve as cache, it's ok send the queries to OpenDNS but if I have already fresh data is unnecessary to query again and again wasting bandwidth and time.
  • Here come my other main request that is making my config even more complex: I want to setup a RPZ zone with a huge list of domains i don't want them be able to be resolved, basically i want to have them resolving as 127.0.0.1 or another ip/host of my lan that should serve as catch-all http server for ad purpose and so on.

How can I achieve a so complex configuration ?

There's my config files, I guess something here is not working as necessary, so please help me with the config.


named.conf

// This is the primary configuration file for the BIND DNS server named.
//
// Please read /usr/share/doc/bind9/README.Debian.gz for information on the
// structure of BIND configuration files in Debian, *BEFORE* you customize
// this configuration file.
//
// If you are just adding zones, please do that in /etc/bind/named.conf.local

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";

named.conf.options

acl "trusted" {
        127.0.0.1/8;
        10.0.0.0/8;
        172.16.0.0/12;
        192.168.0.0/16;
        ::1;
};

options {

        directory "/var/cache/bind";    # bind cache directory

        recursion yes;                  # enables resursive queries

        allow-query { trusted; } ;

        allow-recursion { trusted; };   # allows recursive queries from "trusted" clients

        //listen-on { 0.0.0.0; };       # interfaces where to listen

        allow-transfer { none; };       # disable zone transfers by default

        // If there is a firewall between you and nameservers you want
        // to talk to, you may need to fix the firewall to allow multiple
        // ports to talk.  See http://www.kb.cert.org/vuls/id/800113

        // If your ISP provided one or more IP addresses for stable
        // nameservers, you probably want to use them as forwarders.
        // Uncomment the following block, and insert the addresses replacing
        // the all-0's placeholder.

        forward only;

        forwarders {
                208.67.222.222;
                208.67.220.220;
        };


        //========================================================================
        // If BIND logs error messages about the root key being expired,
        // you will need to update your keys.  See https://www.isc.org/bind-keys
        //========================================================================

        dnssec-enable no;
        dnssec-validation no;
        dnssec-lookaside auto;


        auth-nxdomain no;               # conform to RFC1035
        #listen-on-v6 { any; };

        response-policy {
                zone "rpz-white" policy PASSTHRU; // my own white list
                zone "rpz-foreign";    // obtained from producer
        };

};

zone "rpz-white" {
  type master;
  file "/etc/bind/rpz-white.db";
};

zone "rpz-foreign" {
  type master;
  file "/etc/bind/rpz-foreign.db";
};

named.conf.local

//
// Do any local configuration here
//

// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";

named.conf.default-zones

// prime the server with knowledge of the root servers
//zone "." {
//      type hint;
//      file "/etc/bind/db.root";
//};

// be authoritative for the localhost forward and reverse zones, and for
// broadcast zones as per RFC 1912

zone "localhost" {
        type master;
        file "/etc/bind/db.local";
};

zone "127.in-addr.arpa" {
        type master;
        file "/etc/bind/db.127";
};

zone "0.in-addr.arpa" {
        type master;
        file "/etc/bind/db.0";
};

zone "255.in-addr.arpa" {
        type master;
        file "/etc/bind/db.255";
};

Best Answer

So let´s examine all your wishes. I am changing the order just to tackle the easier ones first.

1) BIND has to act as a cache.

That´s what it does by default; no need to configure anything.

2) We won't be talking with root name servers.

I see you have keep root hints commented; now as we are talking to DNS servers outside the organisation/home I do recommend not forwarding requests with IP addresses. So comment forward only; and uncomment include "/etc/bind/zones.rfc1918";

3) The RPZ as is here seems fine. In the rpz-foreign.db you have to define the DNS names/domains regexp to

www.domaintoblacklist.xxx CNAME myserver

or

www.domaintoblacklist.xxx A 127.0.0.1

4) as for encrypting the connection; I am doing it with dnscrypt. DNS crypt let´s you talk DNS over TLS/SSL to several DNS providers including OpenDNS; with the added advantages that people won't be able to listen to or change your DNS requests.

The easiest way to install it is downloading the script dnscrypt-autoinstall

To download the script, do:

git clone https://github.com/simonclausen/dnscrypt-autoinstall

The script is done for a standalone dnscrypt usage, so it will take a little extra work to use BIND on top of it.

So to start:

./dnscrypt-autoinstall.sh

The script will ask a serie of questions, including with DNS service will you like to use.

It will change your /etc/resolv.conf to point to your localhost, to dnscrypt. You will have to change resolv.conf to BIND. More on that later on.

In localhost your BIND will listen; and the dnscrypt-proxy daemon will listening in 127.0.0.2 and 127.0.0.3. dnscrypt-proxy will be the one talking with opendns servers.

Forwarders BIND will also have to be configured to talk with dnscrypt:

options {
  ...
    forwarders {
            127.0.0.2;
            172.0.0.3;
    };
  ...

}

I also edited /etc/init.d/dnscrypt-proxy and changed the line with 127.0.0.1 to 127.0.0.3

$DAEMON --daemonize --ephemeral-keys --user=dnscrypt --local-address=127.0.0.3 --resolver-address=$ADDRESS1 --provider-name=$PNAME1 --provider-key=$PKEY1

The script also changes /etc/resolv.conf; you have to change it to point to BIND/ 0.0.0.0 (aka 127.0.0.1 in DNS terminology)

chattr -i /etc/resolv.conf

and edit it.

to finish:

service dnscrypt-proxy restart
service bind9 restart

After the encryption configuration is finished:

  • the clients with talk with BIND as cache
  • BIND will talk with the two instances of dnsproxy still using the "normal" DNS protocol
  • dnsproxy with talk with the selected provider with DNS encrypted over 443/UDP and 443/TCP.

If you want to monitor the packets to the outside:

sudo tcpdump -n port 443
Related Question