Select correct nameserver for CNAME (#10272)
Motivation: The nameserver that should / must be used to resolve a CNAME may be different then the nameserver that was selected for the hostname to resolve. Failing to select the correct nameserver may result in problems during resolution. Modifications: Use the correct DnsServerAddressStream for CNAMEs Result: Always use the correct DnsServerAddressStream for CNAMEs and so fix resolution failures which could accour when CNAMEs are in the mix that use a different domain then the original hostname that we try to resolve
This commit is contained in:
parent
f3a97f4f7b
commit
b40ae95044
@ -968,7 +968,9 @@ abstract class DnsResolveContext<T> {
|
||||
|
||||
private DnsServerAddressStream getNameServers(String hostname) {
|
||||
DnsServerAddressStream stream = getNameServersFromCache(hostname);
|
||||
return stream == null ? nameServerAddrs.duplicate() : stream;
|
||||
// We need to obtain a new stream from the parent DnsNameResolver as the hostname may not be the same as the
|
||||
// one used for the original query (for example we may follow CNAMEs).
|
||||
return stream == null ? parent.newNameServerAddressStream(hostname) : stream;
|
||||
}
|
||||
|
||||
private void followCname(DnsQuestion question, String cname, DnsQueryLifecycleObserver queryLifecycleObserver,
|
||||
|
@ -2932,4 +2932,80 @@ public class DnsNameResolverTest {
|
||||
}
|
||||
assertThat(isQuerySentToSecondServer.get(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCNAMERecursiveResolveDifferentNameServersForDomains() throws IOException {
|
||||
final String firstName = "firstname.com";
|
||||
final String secondName = "secondname.com";
|
||||
final String lastName = "lastname.com";
|
||||
final String ipv4Addr = "1.2.3.4";
|
||||
final TestDnsServer dnsServer2 = new TestDnsServer(new RecordStore() {
|
||||
@Override
|
||||
public Set<ResourceRecord> getRecords(QuestionRecord question) {
|
||||
ResourceRecordModifier rm = new ResourceRecordModifier();
|
||||
rm.setDnsClass(RecordClass.IN);
|
||||
rm.setDnsName(question.getDomainName());
|
||||
rm.setDnsTtl(100);
|
||||
|
||||
if (question.getDomainName().equals(firstName)) {
|
||||
rm.setDnsType(RecordType.CNAME);
|
||||
rm.put(DnsAttribute.DOMAIN_NAME, secondName);
|
||||
} else if (question.getDomainName().equals(lastName)) {
|
||||
rm.setDnsType(question.getRecordType());
|
||||
rm.put(DnsAttribute.IP_ADDRESS, ipv4Addr);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return Collections.singleton(rm.getEntry());
|
||||
}
|
||||
});
|
||||
dnsServer2.start();
|
||||
final TestDnsServer dnsServer3 = new TestDnsServer(new RecordStore() {
|
||||
@Override
|
||||
public Set<ResourceRecord> getRecords(QuestionRecord question) {
|
||||
if (question.getDomainName().equals(secondName)) {
|
||||
ResourceRecordModifier rm = new ResourceRecordModifier();
|
||||
rm.setDnsClass(RecordClass.IN);
|
||||
rm.setDnsName(question.getDomainName());
|
||||
rm.setDnsTtl(100);
|
||||
rm.setDnsType(RecordType.CNAME);
|
||||
rm.put(DnsAttribute.DOMAIN_NAME, lastName);
|
||||
return Collections.singleton(rm.getEntry());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
dnsServer3.start();
|
||||
DnsNameResolver resolver = null;
|
||||
try {
|
||||
resolver = newResolver()
|
||||
.resolveCache(NoopDnsCache.INSTANCE)
|
||||
.cnameCache(NoopDnsCnameCache.INSTANCE)
|
||||
.recursionDesired(true)
|
||||
.maxQueriesPerResolve(16)
|
||||
.nameServerProvider(new DnsServerAddressStreamProvider() {
|
||||
@Override
|
||||
public DnsServerAddressStream nameServerAddressStream(String hostname) {
|
||||
if (hostname.equals(secondName + '.')) {
|
||||
return DnsServerAddresses.singleton(dnsServer3.localAddress()).stream();
|
||||
}
|
||||
return DnsServerAddresses.singleton(dnsServer2.localAddress()).stream();
|
||||
}
|
||||
})
|
||||
.resolvedAddressTypes(ResolvedAddressTypes.IPV4_PREFERRED).build();
|
||||
|
||||
assertResolvedAddress(resolver.resolve(firstName).syncUninterruptibly().getNow(), ipv4Addr, firstName);
|
||||
} finally {
|
||||
dnsServer2.stop();
|
||||
dnsServer3.stop();
|
||||
if (resolver != null) {
|
||||
resolver.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertResolvedAddress(InetAddress resolvedAddress, String ipAddr, String hostname) {
|
||||
assertEquals(ipAddr, resolvedAddress.getHostAddress());
|
||||
assertEquals(hostname, resolvedAddress.getHostName());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user