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
d10c946e1b
commit
68105b257d
@ -986,7 +986,9 @@ abstract class DnsResolveContext<T> {
|
|||||||
|
|
||||||
private DnsServerAddressStream getNameServers(String hostname) {
|
private DnsServerAddressStream getNameServers(String hostname) {
|
||||||
DnsServerAddressStream stream = getNameServersFromCache(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,
|
private void followCname(DnsQuestion question, String cname, DnsQueryLifecycleObserver queryLifecycleObserver,
|
||||||
|
@ -2974,4 +2974,80 @@ public class DnsNameResolverTest {
|
|||||||
}
|
}
|
||||||
assertThat(isQuerySentToSecondServer.get(), is(false));
|
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