diff --git a/bin/tests/system/forward/ns4/malicious.db b/bin/tests/system/forward/ns4/malicious.db
new file mode 100644
index 0000000000000000000000000000000000000000..b47208c1640eaf40d9c23bfb4598000fd068b814
--- /dev/null
+++ b/bin/tests/system/forward/ns4/malicious.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA malicious. admin.malicious. (
+ 1 ; Serial
+ 604800 ; Refresh
+ 86400 ; Retry
+ 2419200 ; Expire
+ 86400 ) ; Negative Cache TTL
+
+@ IN NS ns
+
+ns IN A 10.53.0.4
+
+target IN CNAME subdomain.rebind.
diff --git a/bin/tests/system/forward/ns4/named.conf.in b/bin/tests/system/forward/ns4/named.conf.in
index 643e1271b53ae85e91a169413259afe84dfe1fee..fee76b41e5d46d5bfdb9fc10bd6e914436417a2b 100644
--- a/bin/tests/system/forward/ns4/named.conf.in
+++ b/bin/tests/system/forward/ns4/named.conf.in
@@ -55,3 +55,8 @@ zone "grafted" {
forward only;
forwarders { 10.53.0.2; };
};
+
+zone "malicious." {
+ type master;
+ file "malicious.db";
+};
diff --git a/bin/tests/system/forward/ns5/named.conf.in b/bin/tests/system/forward/ns5/named.conf.in
index 0e65985d52634654cf3ebb757cd1f0296e5d9cb6..6742222d4d088807ce1765c1073ef8ba16768d9c 100644
--- a/bin/tests/system/forward/ns5/named.conf.in
+++ b/bin/tests/system/forward/ns5/named.conf.in
@@ -19,9 +19,16 @@ options {
listen-on-v6 { none; };
forward only;
forwarders { 10.53.0.4; };
+ deny-answer-aliases { "rebind"; };
+ dnssec-validation yes;
};
zone "." {
type hint;
file "root.db";
};
+
+zone "rebind" {
+ type master;
+ file "rebind.db";
+};
diff --git a/bin/tests/system/forward/ns5/rebind.db b/bin/tests/system/forward/ns5/rebind.db
new file mode 100644
index 0000000000000000000000000000000000000000..3e71327a4856ab9a164db475423327de0184dd81
--- /dev/null
+++ b/bin/tests/system/forward/ns5/rebind.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA rebind. admin.rebind. (
+ 1 ; Serial
+ 604800 ; Refresh
+ 86400 ; Retry
+ 2419200 ; Expire
+ 86400 ) ; Negative Cache TTL
+
+@ IN NS ns
+
+ns IN A 10.53.0.5
+
+subdomain IN A 10.53.0.1
diff --git a/bin/tests/system/forward/tests.sh b/bin/tests/system/forward/tests.sh
index 8c64960..1da4136 100644
--- a/bin/tests/system/forward/tests.sh
+++ b/bin/tests/system/forward/tests.sh
@@ -143,5 +143,18 @@ sent=`grep "10.53.0.7#.* (.): query '\./NS/IN' approved" ns1/named.run | wc -l`
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
+n=$((n+1))
+echo_i "checking that rebinding protection works in forward only mode ($n)"
+ret=0
+# 10.53.0.5 will forward target.malicious. query to 10.53.0.4
+# which in turn will return a CNAME for subdomain.rebind.
+# to honor the option deny-answer-aliases { "rebind"; };
+# ns5 should return a SERVFAIL to avoid potential rebinding attacks
+dig_with_opts +noadd +noauth @10.53.0.5 target.malicious. > dig.out.$n || ret=1
+grep "status: SERVFAIL" dig.out.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index a8cbb10..39d33e0 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -6413,8 +6413,10 @@ is_answertarget_allowed(fetchctx_t *fctx, dns_name_t *qname, dns_name_t *rname,
/*
* If the target name is a subdomain of the search domain, allow it.
*/
- if (dns_name_issubdomain(tname, &fctx->domain))
+ if ((fctx->fwdpolicy == dns_fwdpolicy_none) &&
+ dns_name_issubdomain(tname, &fctx->domain)) {
return (ISC_TRUE);
+ }
/*
* Otherwise, apply filters.