mirror of
https://github.com/coollabsio/coolify.git
synced 2026-09-24 23:40:16 -05:00
fix(dns): fall back to system resolver (#11811)
This commit is contained in:
@@ -66,6 +66,7 @@ class CheckDomainDns
|
||||
}
|
||||
|
||||
$type = dnsRecordTypeForIp($expectedIp) === 'AAAA' ? DNSTypes::NAME_AAAA : DNSTypes::NAME_A;
|
||||
$receivedAddressRecord = false;
|
||||
|
||||
foreach ($dnsServers as $dnsServer) {
|
||||
$remainingNanoseconds = $deadline - hrtime(true);
|
||||
@@ -90,6 +91,7 @@ class CheckDomainDns
|
||||
continue;
|
||||
}
|
||||
|
||||
$receivedAddressRecord = true;
|
||||
if (isCloudflareIp($record->getData()) || ($expectedIp && $record->getData() === $expectedIp)) {
|
||||
return $this->result('ok', $this->successMessage($server, $expectedIp), $expectedIp);
|
||||
}
|
||||
@@ -99,9 +101,42 @@ class CheckDomainDns
|
||||
}
|
||||
}
|
||||
|
||||
if (! $receivedAddressRecord && hrtime(true) < $deadline) {
|
||||
foreach ($this->resolveWithSystemDns($host, $type) as $resolvedIp) {
|
||||
if (isCloudflareIp($resolvedIp) || ($expectedIp && $resolvedIp === $expectedIp)) {
|
||||
return $this->result('ok', $this->successMessage($server, $expectedIp), $expectedIp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->result('failed', dnsMismatchGuidanceMessage($expectedIp, $expectedIp), $expectedIp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
protected function resolveWithSystemDns(string $host, string $type): array
|
||||
{
|
||||
$recordType = $type === DNSTypes::NAME_AAAA ? DNS_AAAA : DNS_A;
|
||||
$addressKey = $type === DNSTypes::NAME_AAAA ? 'ipv6' : 'ip';
|
||||
|
||||
try {
|
||||
$records = @dns_get_record($host, $recordType);
|
||||
} catch (\Throwable) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (! is_array($records)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return collect($records)
|
||||
->pluck($addressKey)
|
||||
->filter(fn ($address) => is_string($address) && filter_var($address, FILTER_VALIDATE_IP) !== false)
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
private function successMessage(Server $server, ?string $expectedIp): string
|
||||
{
|
||||
if (
|
||||
|
||||
@@ -110,3 +110,81 @@ it('does not start another resolver query after the total dns budget is exhauste
|
||||
->and($result['example']['message'])->toBe('Could not validate DNS for this domain.')
|
||||
->and($queryCount)->toHaveCount(0);
|
||||
});
|
||||
|
||||
it('falls back to the system resolver when custom dns servers return no answers', function () {
|
||||
InstanceSettings::unguarded(fn () => InstanceSettings::query()->updateOrCreate(
|
||||
['id' => 0],
|
||||
[
|
||||
'is_dns_validation_enabled' => true,
|
||||
'custom_dns_servers' => '192.0.2.1',
|
||||
]
|
||||
));
|
||||
|
||||
app()->bind(DNSQuery::class, fn () => new class('192.0.2.1') extends DNSQuery
|
||||
{
|
||||
public function query(string $question, string $typeName = DNSTypes::NAME_A): false
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function hasError(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
$action = new class extends CheckDomainDns
|
||||
{
|
||||
protected function resolveWithSystemDns(string $host, string $type): array
|
||||
{
|
||||
return ['203.0.113.10'];
|
||||
}
|
||||
};
|
||||
|
||||
$result = $action->handle(
|
||||
['example' => 'https://example.com'],
|
||||
new Server(['ip' => '203.0.113.10']),
|
||||
'203.0.113.10',
|
||||
);
|
||||
|
||||
expect($result['example']['status'])->toBe('ok');
|
||||
});
|
||||
|
||||
it('does not use the system resolver after a custom dns server returns an address', function () {
|
||||
InstanceSettings::unguarded(fn () => InstanceSettings::query()->updateOrCreate(
|
||||
['id' => 0],
|
||||
[
|
||||
'is_dns_validation_enabled' => true,
|
||||
'custom_dns_servers' => '192.0.2.1',
|
||||
]
|
||||
));
|
||||
|
||||
app()->bind(DNSQuery::class, fn () => new class('192.0.2.1') extends DNSQuery
|
||||
{
|
||||
public function query(string $question, string $typeName = DNSTypes::NAME_A): array
|
||||
{
|
||||
return [new DNSResult($typeName, 1, 'IN', 60, '198.51.100.20', $question, '', [])];
|
||||
}
|
||||
|
||||
public function hasError(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$action = new class extends CheckDomainDns
|
||||
{
|
||||
protected function resolveWithSystemDns(string $host, string $type): array
|
||||
{
|
||||
throw new RuntimeException('The system resolver must not be used.');
|
||||
}
|
||||
};
|
||||
|
||||
$result = $action->handle(
|
||||
['example' => 'https://example.com'],
|
||||
new Server(['ip' => '203.0.113.10']),
|
||||
'203.0.113.10',
|
||||
);
|
||||
|
||||
expect($result['example']['status'])->toBe('failed');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user