I'm fairly sure I've uncovered a bug, but I'm trying to make sense of it and maybe get a sanity check.
Scenario
A policy where if the request is looking for a specific record AND
the client IP is not in a particular subnet, the policy matches and results in a CNAME
record, the target of which is not covered by the policy and does not exist in a scope.
Example:
- Zone =
example.com
- Records in
example.com
default scope:testme IN A 10.1.2.3
testOther IN A 10.11.11.11
- Zone Scope =
TesterScope
- Record in
TesterScope
:testme IN CNAME testOther.example.com.
- Client Subnet
MySubnet
contains10.8.8.0/24
QRP with EQ
for Client Subnet
- Query Resolution Policy
MyQRP
with following config:- Condition =
And
- Content =
TesterScope
- Criteria:
- FQDN =
EQ,testme.example.com.
- ClientSubnet =
EQ,MySubnet
- FQDN =
- Condition =
This will produce the expected results, that is:
- If a request comes in for
testme.example.com
from an IP withinMySubnet
(should match), it will correctly return (and resolve) theCNAME
record, even though theCNAME
must be resolved in the default scope (the QRP specifically should only match whenFQDN
istestme.example.com
not fortestOther.example.com
). Therefore, the result is10.11.11.11
, which is correct. - If a request comes in for
testme.example.com
from an IP outsideMySubnet
(should not match), it resolves to10.1.2.3
as expected.
QRP with NE
for Client Subnet
- Query Resolution Policy
MyQRP
with following config:- Condition =
And
- Content =
TesterScope
- Criteria:
- FQDN =
EQ,testme.example.com.
- ClientSubnet =
NE,MySubnet
<- change here
- FQDN =
- Condition =
This will produces unexpected results:
- If a request comes in for
testme.example.com
from an IP outsideMySubnet
(should match), it will correctly return theCNAME
record, but it is unable to resolve it. Further testing revealed that if the target of theCNAME
also exists within the zone scope, it will resolve, but it shouldn't be doing this because there is no QRP that matches requests for that target to make the queries use the scope. - If a request comes in for
testme.example.com
from an IP insideMySubnet
(should not match), it resolves to10.1.2.3
as expected.
Additional Notes
- The
ClientSubnet
criteria can contain bothEQ
andNE
operators in one (likeEQ,ThisSubnet;NE,ThatSubnet
). The behavior happens anytime theNE
operator is included. - I am aware that these
CNAME
resolutions are being done internally on the DNS server; the client is not receiving theCNAME
and then resolving it in a different request. - I contend that the
EQ
-only behavior is correct, because as previously mentioned the target of theCNAME
has no QRP that should cause the zone scope to be used. Additionally, if a client were to directly request the target of theCNAME
, it will not use the rule, so I feel that the results should be consistent between internal and externalCNAME
resolution. - Even if my contentions above are incorrect, the result of the internal
CNAME
resolution is still inconsistent with itself (different results withEQ
vsNE
). - If the record within the zone scope is an
A
record instead of aCNAME
(doesn't require internal resolution) then everything works as planned (this is a possible but in my opinion undesirable workaround).
PowerShell to Demonstrate
(I've done my own tests, but not directly with this code, let me know if it's broken)
$myZone = 'example.com'
$myScope = 'MyScope'
$mySubnetName = 'MySubnet'
$mySubnetCIDR = '10.8.8.0/24'
$commonName = 'testme'
$commonValue = '10.1.2.3'
$otherName = 'testOther'
$otherValue = '10.11.11.11'
$myPolicy = 'MyQRP'
$myCommonFqdn = "${commonName}.${myZone}."
$myOtherFqdn = "${otherName}.${myZone}."
$myDC = 'My2016DC'
Import-Module DnsServer
$PSDefaultParameterValues = @{
'*-DnsServer*:ComputerName' = $myDC
}
Add-DnsServerClientSubnet -Name $mySubnetName -IPv4Subnet $mySubnetCIDR
Add-DnsServerZoneScope -ZoneName $myZone -Name $myScope
Add-DnsServerResourceRecord -ZoneName $myZone -Name $commonName -A -IPv4Address $commonValue
Add-DnsServerResourceRecord -ZoneName $myZone -Name $otherName -A -IPv4Address $otherValue
Add-DnsServerResourceRecord -ZoneName $myZone -ZoneScope $myScope -Name $commonName -CName -HostNameAlias $myOtherFqdn
# Add the policy with EQ that works correctly
Add-DnsServerQueryResolutionPolicy -ZoneName $myZone -ZoneScope $myScope -Name $myPolicy -Fqdn "EQ,$myCommonFqdn" -ClientSubnet "EQ,$mySubnetName"
# Uncomment these to change it around
# Use NE instead of EQ
# Set-DnsServerQueryResolutionPolicy -ZoneName $myZone -ZoneScope $myScope -Name $myPolicy -Fqdn "EQ,$myCommonFqdn" -ClientSubnet "NE,$mySubnetName" -Action REPLACE
# Set it back to using EQ
# Set-DnsServerQueryResolutionPolicy -ZoneName $myZone -ZoneScope $myScope -Name $myPolicy -Fqdn "EQ,$myCommonFqdn" -ClientSubnet "EQ,$mySubnetName" -Action REPLACE
That should create a reproducible scenario in your environment (change the variables as needed). From there you can use nslookup
or dig
as needed to check the results. Note you must only check against the single DC that this is applied to if you're in an AD environment (the policies/subnets don't get replicated).
Update -- Wed 24 May
I have a case open with Microsoft for this issue. They claim they can not reproduce it.
Anyone out there willing to give this a try?
Update -- Wed 26 Jul
Microsoft is able to reproduce the issue, after repeated demonstrations. I am awaiting a deeper response from the internal team.
The expected behaviour is : For CNAME/DNAME/ADDITIONAL SECTIONS • For each part of a chained response, the policies must be applied all over again. The criteria of these policy will be matched against the values in the original query (e.g. TimeOfDay, Client subnet etc.) except for QTYPE and FQDN. • If any of the policies used in the chain result in a DENY/IGNORE, the DNS server must send the partial response to the client if available. The Deny/Ignore will apply only for that FQDN or zone.
I think the results are expected.
Kumar Ashutosh [I designed DNS Server Policies]
So, here's how my case went with Microsoft.
Eventually, it made its way internally to the developer (who posted an answer on this question), and so the official response is "this is how it was designed."
I'm personally not at all satisfied with that answer, as this behavior is not documented, and makes no intuitive sense, but there it is.
I was told that to go any further with the issue, we would have to open a Premier support case (we don't have premier support). Given that this took many months, and my company no longer needs this feature, that won't be happening.