--- /dev/null
+; Check that cached NXDOMAIN replies for nameservers do not count towards the
+; MAX_TARGET_NX limit.
+
+server:
+ module-config: "iterator"
+ trust-anchor-signaling: no
+ target-fetch-policy: "0 0 0 0 0"
+ verbosity: 3
+ access-control: 127.0.0.1 allow_snoop
+ do-not-query-localhost: no
+ qname-minimisation: no
+ minimal-responses: no
+ rrset-roundrobin: no
+stub-zone:
+ name: "example.com"
+ stub-addr: 127.0.0.2
+stub-zone:
+ name: "nameservers.com"
+ stub-addr: 127.0.0.3
+CONFIG_END
+
+SCENARIO_BEGIN Test that the NXNS countermeasure is not triggered for cached NXDOMAIN
+
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.1
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ b.a.example.com. IN A
+ SECTION ANSWER
+ b.a.example.com. IN A 127.0.0.0
+ ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 31 100
+ ADDRESS 127.0.0.3
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns1.nameservers.com. IN A
+ SECTION ANSWER
+ ns1.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns2.nameservers.com. IN A
+ SECTION ANSWER
+ ns2.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns3.nameservers.com. IN A
+ SECTION ANSWER
+ ns3.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns4.nameservers.com. IN A
+ SECTION ANSWER
+ ns4.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns5.nameservers.com. IN A
+ SECTION ANSWER
+ ns5.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns6.nameservers.com. IN A
+ SECTION ANSWER
+ ns6.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns7.nameservers.com. IN A
+ SECTION ANSWER
+ ns7.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns8.nameservers.com. IN A
+ SECTION ANSWER
+ ns8.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns9.nameservers.com. IN A
+ SECTION ANSWER
+ ns9.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns10.nameservers.com. IN A
+ SECTION ANSWER
+ ns10.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns11.nameservers.com. IN A
+ SECTION ANSWER
+ ns11.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ ns12.nameservers.com. IN A
+ SECTION ANSWER
+ ns12.nameservers.com. IN A 127.0.0.1
+ ENTRY_END
+
+ ; Reply no-data to AAAA queries
+ ENTRY_BEGIN
+ MATCH opcode subdomain
+ ADJUST copy_id copy_query
+ REPLY QR NOERROR
+ SECTION QUESTION
+ nameservers.com. IN A
+ ENTRY_END
+RANGE_END
+
+; Query for a domain
+STEP 0 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+a.example.com. IN A
+ENTRY_END
+
+; Answer with delegation
+STEP 1 REPLY
+ENTRY_BEGIN
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.example.com. IN A
+SECTION AUTHORITY
+a.example.com. IN NS ns1.nameservers.com.
+a.example.com. IN NS ns2.nameservers.com.
+a.example.com. IN NS ns3.nameservers.com.
+a.example.com. IN NS ns4.nameservers.com.
+a.example.com. IN NS ns5.nameservers.com.
+a.example.com. IN NS ns6.nameservers.com.
+a.example.com. IN NS ns7.nameservers.com.
+a.example.com. IN NS ns8.nameservers.com.
+a.example.com. IN NS ns9.nameservers.com.
+a.example.com. IN NS ns10.nameservers.com.
+a.example.com. IN NS ns11.nameservers.com.
+a.example.com. IN NS ns12.nameservers.com.
+ENTRY_END
+
+; Reply NXDOMAIN to MAX_TARGET_NX queries(6) x2 (A+AAAA)
+STEP 2 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com email.example.com 1 2 3 4 60
+ENTRY_END
+STEP 3 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+SECTION AUTHORITY
+example.com. IN SOA ns.ns email.email 1 2 3 4 60
+ENTRY_END
+STEP 4 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 5 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 6 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 7 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 8 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 9 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 10 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 11 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 12 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 13 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+
+; We should receive SERVFAIL because MAX_TARGET_NX was reached
+STEP 14 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+a.example.com. IN A
+ENTRY_END
+
+; Query for another domain in the same delegation
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+b.a.example.com. IN A
+ENTRY_END
+
+; We still have 6 NSes that Unbound didn't try to resolve
+; Reply with NXDOMAIN for 5 of them
+STEP 21 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 22 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 23 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 24 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 25 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 26 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 27 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 28 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 29 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+STEP 30 REPLY
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.query. IN A
+ENTRY_END
+
+; Unbound will reach the upstream and get the answer for the final NS
+; which has the answer for the client query.
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+b.a.example.com. IN A
+SECTION ANSWER
+b.a.example.com. IN A 127.0.0.0
+ENTRY_END
+
+; Allow for possible pending NS query (AAAA) to get answered
+STEP 41 TRAFFIC
+
+SCENARIO_END