Forward only zones should forward queries regardless of RD flag.
Summary
When a query does not have an RD flag set and a zone is configured as a forward only the query does not get recursed
and thus does not get an answer.
In my understanding forward zones are not real zones, and forwarding is not really a recursion.
Not in a DNS sense anyway.
Forward zones function more in a way of a reverse proxy to an actual server and as such should always recurse
and let the downstream servers handle the query as is. That includes an RD flag.
In addition, since a forward zone is just a reverse proxy, it should return verbatim what it has received from the downstream. That includes authority section.
This is useful when there is a single public facing name server with subdomains controlled by different, not publically accessible, name servers throughout the intranet. This can also be achieved by placing a public facing dns reverse proxy in front of intranet bind instances, but there is nothing quite like bind out there :)
BIND version used
BIND 9.16.11 (Stable Release) <id:9ff601b>
running on Linux x86_64 4.19.121-linuxkit #1 SMP Tue Dec 1 17:50:32 UTC 2020
built by make with '--build=x86_64-alpine-linux-musl' '--host=x86_64-alpine-linux-musl' '--prefix=/usr' '--sysconfdir=/etc/bind' '--localstatedir=/var' '--mandir=/usr/share/man' '--infodir=/usr/share/info' '--with-dlopen=yes' '--with-dlz-filesystem=yes' '--with-dlz-ldap=yes' '--with-dlz-stub=yes' '--with-gssapi=/usr' '--with-libjson' '--with-libtool' '--with-libxml2' '--with-openssl=/usr' '--with-python=python3' '--enable-dnstap' '--enable-largefile' '--enable-linux-caps' '--enable-shared' '--enable-static' '--disable-isc-spnego' '--disable-backtrace' 'build_alias=x86_64-alpine-linux-musl' 'host_alias=x86_64-alpine-linux-musl' 'CC=gcc' 'CFLAGS=-Os -fomit-frame-pointer -D_GNU_SOURCE' 'LDFLAGS=-Wl,--as-needed' 'CPPFLAGS=-Os -fomit-frame-pointer'
compiled by GCC 10.2.1 20201203
compiled with OpenSSL version: OpenSSL 1.1.1i 8 Dec 2020
linked to OpenSSL version: OpenSSL 1.1.1i 8 Dec 2020
compiled with libuv version: 1.40.0
linked to libuv version: 1.40.0
compiled with libxml2 version: 2.9.10
linked to libxml2 version: 20910
compiled with json-c version: 0.15
linked to json-c version: 0.15
compiled with zlib version: 1.2.11
linked to zlib version: 1.2.11
compiled with protobuf-c version: 1.3.3
linked to protobuf-c version: 1.3.3
threads support is enabled
Steps to reproduce
Configure 2 instances of named.
Public named with a master zone and a forward zone
zone "example.com" {
type master;
file "example.com";
};
zone "sub.example.com" {
type forward;
forward only;
forwarders { ip_of_private_named port 2053; };
};
where zone file has
sub.example.com NS ip_of_private_named
Private named with a forwarded zone
zone "sub.example.com" {
type master;
file "sub.example.com";
};
Run a recursive query against a private named and get authoritative response:
$ nslookup -port=2053 sub.example.com 127.0.0.1
Server: 127.0.0.1
Address: 127.0.0.1#2053
Name: sub.example.com
Address: 127.0.0.1
Run a query against a public named and get non-authoritative response
$ nslookup -port=1053 sub.example.com 127.0.0.1
Server: 127.0.0.1
Address: 127.0.0.1#1053
Non-authoritative answer:
Name: sub.example.com
Address: 127.0.0.1
Run a non-recursive query against a private named and get back authoritative response
$ nslookup -port=2053 -norecurse sub.example.com 127.0.0.1
Server: 127.0.0.1
Address: 127.0.0.1#2053
Name: sub.example.com
Address: 127.0.0.1
Run a non-recursive query against a public named and get back no answer:
$ nslookup -port=1053 -norecurse sub.example.com 127.0.0.1
Server: 127.0.0.1
Address: 127.0.0.1#1053
Non-authoritative answer:
*** Can't find sub.example.com: No answer
What is the current bug behavior?
Non-recursive query against a public named returns a No answer
Recursive query against a public named returns non-authoritative
response
What is the expected correct behavior?
Non-recursive query against a public named should forward to the specified server and behave as if it was a recursive query. Any query against a public named should return whatever forwared named responded with AS IS, thus maintaining authority if it was returned.
Relevant configuration files
Attaching a tar with configurations and a run.sh to spin up public and private instances. Replace all occurences of 192.168.2.10 with the local ip of your docker host. Run run.sh to spin up 2 containers: bind9-public and bind9-private. Run nslookup queries from Steps to reproduce.
Relevant logs and/or screenshots
In Steps to reproduce
Possible fixes
I am proposing a fix that would handle the forwarding. I am not certain how to approach the authority response yet.
https://gitlab.isc.org/maxfortun/bind9/-/blob/fix-forward-zone-recursion/lib/ns/query.c