fix(dns): time out validation queries after five seconds (#11378)

This commit is contained in:
Andras Bacsai
2026-08-18 23:40:59 +02:00
committed by GitHub
parent 1cb9f001f8
commit 45d0ec7518
3 changed files with 79 additions and 3 deletions
+12 -3
View File
@@ -2068,7 +2068,7 @@ function validateDNSEntry(string $fqdn, Server $server)
$type = dnsRecordTypeForIp($ip) === 'AAAA' ? DNSTypes::NAME_AAAA : DNSTypes::NAME_A;
foreach ($dns_servers as $dns_server) {
try {
$query = new DNSQuery($dns_server);
$query = createDnsQuery($dns_server);
$results = $query->query($host, $type);
if ($results === false || $query->hasError()) {
} else {
@@ -2076,11 +2076,11 @@ function validateDNSEntry(string $fqdn, Server $server)
if ($result->getType() == $type) {
if (isCloudflareIp($result->getData())) {
$found_matching_ip = true;
break;
break 2;
}
if ($ip && $result->getData() === $ip) {
$found_matching_ip = true;
break;
break 2;
}
}
}
@@ -2092,6 +2092,15 @@ function validateDNSEntry(string $fqdn, Server $server)
return $found_matching_ip;
}
function createDnsQuery(string $dnsServer): DNSQuery
{
return app()->make(DNSQuery::class, [
'server' => $dnsServer,
'port' => 53,
'timeout' => 5,
]);
}
function isCloudflareIp(string $ip): bool
{
// https://www.cloudflare.com/ips/
+57
View File
@@ -0,0 +1,57 @@
<?php
use App\Models\InstanceSettings;
use App\Models\Server;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PurplePixie\PhpDns\DNSQuery;
use PurplePixie\PhpDns\DNSResult;
use PurplePixie\PhpDns\DNSTypes;
uses(RefreshDatabase::class);
it('stops querying DNS servers after finding a matching IP', function (string $resolvedIp) {
InstanceSettings::unguarded(fn () => InstanceSettings::query()->updateOrCreate(
['id' => 0],
[
'is_dns_validation_enabled' => true,
'custom_dns_servers' => '192.0.2.1,192.0.2.2',
]
));
$queriedServers = new ArrayObject;
$targetIp = '203.0.113.10';
app()->bind(DNSQuery::class, function ($app, array $parameters) use ($queriedServers, $resolvedIp) {
return new class($parameters['server'], $queriedServers, $resolvedIp) extends DNSQuery
{
public function __construct(
private readonly string $dnsServer,
private readonly ArrayObject $queriedServers,
private readonly string $resolvedIp,
) {
parent::__construct($dnsServer);
}
public function query(string $question, string $typeName = DNSTypes::NAME_A)
{
$this->queriedServers->append($this->dnsServer);
return [new DNSResult($typeName, 1, 'IN', 60, $this->resolvedIp, $question, '', [])];
}
public function hasError(): bool
{
return false;
}
};
});
$server = new Server(['ip' => $targetIp]);
$server->id = 1;
expect(validateDNSEntry('https://example.com', $server))->toBeTrue()
->and($queriedServers->getArrayCopy())->toBe(['192.0.2.1']);
})->with([
'target server IP' => '203.0.113.10',
'Cloudflare IP' => '104.16.0.1',
]);
+10
View File
@@ -0,0 +1,10 @@
<?php
use PurplePixie\PhpDns\DNSQuery;
it('limits direct DNS queries to five seconds', function () {
$query = createDnsQuery('1.1.1.1');
$timeout = (new ReflectionClass(DNSQuery::class))->getProperty('timeout')->getValue($query);
expect($timeout)->toBe(5);
});