diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php
index 0c5828af3..ab16f64d7 100644
--- a/app/Livewire/Project/Application/General.php
+++ b/app/Livewire/Project/Application/General.php
@@ -209,7 +209,7 @@ class General extends Component
public function updatedApplicationFqdn()
{
$this->resetDefaultLabels(false);
- $this->dispatch('success', 'Labels reset to default!');
+ // $this->dispatch('success', 'Labels reset to default!');
}
public function submit($showToaster = true)
{
@@ -235,9 +235,16 @@ class General extends Component
]);
}
if (data_get($this->application, 'fqdn')) {
- $domains = Str::of($this->application->fqdn)->trim()->explode(',')->map(function ($domain) {
- return Str::of($domain)->trim()->lower();
+ $this->application->fqdn = str($this->application->fqdn)->replaceEnd(',', '')->trim();
+ $domains = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) {
+ return str($domain)->trim()->lower();
});
+ $domains = $domains->unique();
+ foreach ($domains as $domain) {
+ if (!validate_dns_entry($domain, $this->application->destination->server)) {
+ $showToaster && $this->dispatch('error', "Validating DNS settings for: $domain failed.
Make sure you have added the DNS records correctly.
Check this documentation for further help.");
+ }
+ }
$this->application->fqdn = $domains->implode(',');
}
diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php
index 466ca5472..d832c83d8 100644
--- a/app/Livewire/Server/Form.php
+++ b/app/Livewire/Server/Form.php
@@ -76,7 +76,7 @@ class Form extends Component
$this->server->settings->is_usable = true;
$this->server->settings->save();
} else {
- $this->dispatch('error', 'Server is not reachable.
Please validate your configuration and connection. See this documentation.');
+ $this->dispatch('error', 'Server is not reachable.
Please validate your configuration and connection.
Check this documentation for further help.');
return;
}
}
@@ -85,7 +85,7 @@ class Form extends Component
try {
$uptime = $this->server->validateConnection();
if (!$uptime) {
- $install && $this->dispatch('error', 'Server is not reachable.
Please validate your configuration and connection. See this documentation.');
+ $install && $this->dispatch('error', 'Server is not reachable.
Please validate your configuration and connection.
Check this documentation for further help.');
return;
}
$supported_os_type = $this->server->validateOS();
diff --git a/app/Livewire/Server/ShowPrivateKey.php b/app/Livewire/Server/ShowPrivateKey.php
index a39765c71..0834866c1 100644
--- a/app/Livewire/Server/ShowPrivateKey.php
+++ b/app/Livewire/Server/ShowPrivateKey.php
@@ -39,7 +39,7 @@ class ShowPrivateKey extends Component
if ($uptime) {
$this->dispatch('success', 'Server is reachable.');
} else {
- $this->dispatch('error', 'Server is not reachable.
Please validate your configuration and connection. See this documentation.');
+ $this->dispatch('error', 'Server is not reachable.
Please validate your configuration and connection.
Check this documentation for further help.');
return;
}
} catch (\Throwable $e) {
diff --git a/app/Livewire/Settings/Configuration.php b/app/Livewire/Settings/Configuration.php
index 43f4afb7a..bafc82447 100644
--- a/app/Livewire/Settings/Configuration.php
+++ b/app/Livewire/Settings/Configuration.php
@@ -15,6 +15,7 @@ class Configuration extends Component
public bool $do_not_track;
public bool $is_auto_update_enabled;
public bool $is_registration_enabled;
+ public bool $is_dns_validation_enabled;
public bool $next_channel;
protected string $dynamic_config_path = '/data/coolify/proxy/dynamic';
protected Server $server;
@@ -24,12 +25,14 @@ class Configuration extends Component
'settings.resale_license' => 'nullable',
'settings.public_port_min' => 'required',
'settings.public_port_max' => 'required',
+ 'settings.custom_dns_servers' => 'nullable',
];
protected $validationAttributes = [
'settings.fqdn' => 'FQDN',
'settings.resale_license' => 'Resale License',
'settings.public_port_min' => 'Public port min',
'settings.public_port_max' => 'Public port max',
+ 'settings.custom_dns_servers' => 'Custom DNS servers',
];
public function mount()
@@ -38,6 +41,7 @@ class Configuration extends Component
$this->is_auto_update_enabled = $this->settings->is_auto_update_enabled;
$this->is_registration_enabled = $this->settings->is_registration_enabled;
$this->next_channel = $this->settings->next_channel;
+ $this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled;
}
public function instantSave()
@@ -45,6 +49,7 @@ class Configuration extends Component
$this->settings->do_not_track = $this->do_not_track;
$this->settings->is_auto_update_enabled = $this->is_auto_update_enabled;
$this->settings->is_registration_enabled = $this->is_registration_enabled;
+ $this->settings->is_dns_validation_enabled = $this->is_dns_validation_enabled;
if ($this->next_channel) {
$this->settings->next_channel = false;
$this->next_channel = false;
@@ -63,6 +68,14 @@ class Configuration extends Component
return;
}
$this->validate();
+
+ $this->settings->custom_dns_servers = str($this->settings->custom_dns_servers)->replaceEnd(',', '')->trim();
+ $this->settings->custom_dns_servers = str($this->settings->custom_dns_servers)->trim()->explode(',')->map(function ($dns) {
+ return str($dns)->trim()->lower();
+ });
+ $this->settings->custom_dns_servers = $this->settings->custom_dns_servers->unique();
+ $this->settings->custom_dns_servers = $this->settings->custom_dns_servers->implode(',');
+
$this->settings->save();
$this->server = Server::findOrFail(0);
$this->setup_instance_fqdn();
diff --git a/bootstrap/helpers/proxy.php b/bootstrap/helpers/proxy.php
index 1c419afbf..80eebe1a6 100644
--- a/bootstrap/helpers/proxy.php
+++ b/bootstrap/helpers/proxy.php
@@ -288,7 +288,7 @@ function setup_dynamic_configuration()
], $server);
if (config('app.env') == 'local') {
- ray($yaml);
+ // ray($yaml);
}
}
}
diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php
index 87a850fe4..ce51745db 100644
--- a/bootstrap/helpers/shared.php
+++ b/bootstrap/helpers/shared.php
@@ -22,14 +22,11 @@ use App\Notifications\Channels\EmailChannel;
use App\Notifications\Channels\TelegramChannel;
use App\Notifications\Internal\GeneralNotification;
use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
-use Illuminate\Database\QueryException;
use Illuminate\Mail\Message;
use Illuminate\Notifications\Messages\MailMessage;
-use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
-use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Route;
@@ -40,6 +37,7 @@ use Visus\Cuid2\Cuid2;
use phpseclib3\Crypt\RSA;
use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml;
+use PurplePixie\PhpDns\DNSQuery;
function base_configuration_dir(): string
{
@@ -1592,3 +1590,50 @@ function getRealtime()
return $envDefined;
}
}
+
+function validate_dns_entry(string $fqdn, Server $server)
+{
+ $url = Url::fromString($fqdn);
+ $host = $url->getHost();
+ if (str($host)->contains('sslip.io')) {
+ return true;
+ }
+ $settings = InstanceSettings::get();
+ $is_dns_validation_enabled = data_get($settings, 'is_dns_validation_enabled');
+ if (!$is_dns_validation_enabled) {
+ return true;
+ }
+ $dnsServers = data_get($settings, 'custom_dns_servers');
+ $dnsServers = str($dnsServers)->explode(',');
+ if ($server->id === 0) {
+ $ip = data_get($settings, 'public_ipv4') || data_get($settings, 'public_ipv6') || $server->ip;
+ } else {
+ $ip = $server->ip;
+ }
+ $foundMatch = false;
+ $type = \PurplePixie\PhpDns\DNSTypes::NAME_A;
+ foreach ($dnsServers as $dnsServer) {
+ try {
+ ray("Checking $host on $dnsServer");
+ $query = new DNSQuery($dnsServer);
+ $results = $query->query($host, $type);
+ if ($results === false || $query->hasError()) {
+ ray("Error: " . $query->getLasterror());
+ } else {
+ foreach ($results as $result) {
+ if ($result->getType() == $type) {
+ if ($result->getData() === $ip) {
+ ray($host . " has IP address " . $result->getData());
+ ray($result->getString());
+ $foundMatch = true;
+ break;
+ }
+ }
+ }
+ }
+ } catch (\Exception $e) {
+ }
+ }
+ ray("Found match: $foundMatch");
+ return $foundMatch;
+}
diff --git a/composer.json b/composer.json
index 5a7f39844..e9cf53d10 100644
--- a/composer.json
+++ b/composer.json
@@ -28,6 +28,7 @@
"nubs/random-name-generator": "^2.2",
"phpseclib/phpseclib": "~3.0",
"poliander/cron": "^3.0",
+ "purplepixie/phpdns": "^2.1",
"pusher/pusher-php-server": "^7.2",
"resend/resend-laravel": "^0.5.0",
"sentry/sentry-laravel": "^3.4",
diff --git a/composer.lock b/composer.lock
index 82bed2c82..8d0e9da81 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "44337ff4ff1d9c435d9776fec01ebe9c",
+ "content-hash": "de3b59fade9b132d2582a40dcf3c00f9",
"packages": [
{
"name": "amphp/amp",
@@ -6287,6 +6287,54 @@
},
"time": "2023-10-14T21:56:36+00:00"
},
+ {
+ "name": "purplepixie/phpdns",
+ "version": "2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/purplepixie/phpdns.git",
+ "reference": "e1e4f18a60d01947e2aac7157325a9e2e7755bf7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/purplepixie/phpdns/zipball/e1e4f18a60d01947e2aac7157325a9e2e7755bf7",
+ "reference": "e1e4f18a60d01947e2aac7157325a9e2e7755bf7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "PurplePixie": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-3.0-only"
+ ],
+ "authors": [
+ {
+ "name": "David Cutting",
+ "email": "dcutting@purplepixie.org"
+ }
+ ],
+ "description": "PHP DNS Direct Query Module",
+ "support": {
+ "issues": "https://github.com/purplepixie/phpdns/issues",
+ "source": "https://github.com/purplepixie/phpdns/tree/2.1.0"
+ },
+ "time": "2023-11-06T15:37:19+00:00"
+ },
{
"name": "pusher/pusher-php-server",
"version": "7.2.4",
diff --git a/database/migrations/2024_01_15_084609_add_custom_dns_server.php b/database/migrations/2024_01_15_084609_add_custom_dns_server.php
new file mode 100644
index 000000000..24d288d02
--- /dev/null
+++ b/database/migrations/2024_01_15_084609_add_custom_dns_server.php
@@ -0,0 +1,30 @@
+boolean('is_dns_validation_enabled')->default(true);
+ $table->string('custom_dns_servers')->nullable()->default('1.1.1.1');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('instance_settings', function (Blueprint $table) {
+ $table->dropColumn('is_dns_validation_enabled');
+ $table->dropColumn('custom_dns_servers');
+ });
+ }
+};
diff --git a/resources/views/livewire/settings/configuration.blade.php b/resources/views/livewire/settings/configuration.blade.php
index 4abdbf600..091a07dbb 100644
--- a/resources/views/livewire/settings/configuration.blade.php
+++ b/resources/views/livewire/settings/configuration.blade.php
@@ -9,8 +9,10 @@