fix: Better DNS check to prevent errors

This commit is contained in:
Andras Bacsai
2022-05-06 11:41:39 +02:00
parent b0eae8cfe9
commit 7ceb8f1537
7 changed files with 229 additions and 148 deletions

View File

@@ -1,11 +1,31 @@
import { dev } from '$app/env';
import { asyncExecShell, getDomain, getEngine, getUserDetails } from '$lib/common';
import { checkDomainsIsValidInDNS, getDomain, getUserDetails, isDNSValid } from '$lib/common';
import * as db from '$lib/database';
import { ErrorHandler } from '$lib/database';
import { t } from '$lib/translations';
import { promises as dns } from 'dns';
import type { RequestHandler } from '@sveltejs/kit';
import { isIP } from 'is-ip';
export const get: RequestHandler = async (event) => {
const { status, body } = await getUserDetails(event);
if (status === 401) return { status, body };
const domain = event.url.searchParams.get('domain');
if (!domain) {
return {
status: 500,
body: {
message: t.get('application.domain_required')
}
};
}
try {
await isDNSValid(event, domain);
return {
status: 200
};
} catch (error) {
return ErrorHandler(error);
}
};
export const post: RequestHandler = async (event) => {
const { status, body } = await getUserDetails(event);
@@ -14,11 +34,9 @@ export const post: RequestHandler = async (event) => {
let { fqdn, forceSave, dualCerts, isDNSCheckEnabled } = await event.request.json();
if (fqdn) fqdn = fqdn.toLowerCase();
try {
const domain = getDomain(fqdn);
const domainDualCert = domain.includes('www.') ? domain.replace('www.', '') : `www.${domain}`;
const found = await db.isDomainConfigured({ id, fqdn });
console.log(found);
if (found) {
throw {
message: t.get('application.domain_already_in_use', {
@@ -26,111 +44,9 @@ export const post: RequestHandler = async (event) => {
})
};
}
if (isDNSCheckEnabled) {
if (!forceSave) {
dns.setServers(['1.1.1.1', '8.8.8.8']);
if (dualCerts) {
try {
const ipDomain = await dns.resolve4(domain);
const ipDomainDualCert = await dns.resolve4(domainDualCert);
console.log({ ipDomain, ipDomainDualCert });
// TODO: Check if ipDomain and ipDomainDualCert are the same, but not like this
if (
ipDomain.length === ipDomainDualCert.length &&
ipDomain.every((v) => ipDomainDualCert.indexOf(v) >= 0)
) {
let resolves = [];
if (isIP(event.url.hostname)) {
resolves = [event.url.hostname];
} else {
resolves = await dns.resolve4(event.url.hostname);
}
console.log({ resolves });
for (const ip of ipDomain) {
if (resolves.includes(ip)) {
return {
status: 200
};
}
}
for (const ip of ipDomainDualCert) {
if (resolves.includes(ip)) {
return {
status: 200
};
}
}
throw false;
} else {
throw false;
}
} catch (error) {
console.log(error);
throw {
message: t.get('application.dns_not_set_error', { domain })
};
}
} else {
let resolves = [];
try {
const ipDomain = await dns.resolve4(domain);
console.log({ ipDomain });
if (isIP(event.url.hostname)) {
resolves = [event.url.hostname];
} else {
resolves = await dns.resolve4(event.url.hostname);
}
console.log({ resolves });
for (const ip of ipDomain) {
if (resolves.includes(ip)) {
return {
status: 200
};
}
}
throw false;
} catch (error) {
console.log(error);
throw {
message: t.get('application.dns_not_set_error', { domain })
};
}
}
// let localReverseDomains = [];
// let newIps = [];
// let newIpsWWW = [];
// let localIps = [];
// try {
// localReverseDomains = await dns.reverse(event.url.hostname)
// } catch (error) { }
// try {
// localIps = await dns.resolve4(event.url.hostname);
// } catch (error) { }
// try {
// newIps = await dns.resolve4(domain);
// if (dualCerts) {
// newIpsWWW = await dns.resolve4(`${isWWW ? nonWWW : domain}`)
// }
// console.log(newIps)
// } catch (error) { }
// console.log({ localIps, newIps, localReverseDomains, dualCerts, isWWW, nonWWW })
// if (localReverseDomains?.length > 0) {
// if ((newIps?.length === 0 || !newIps.includes(event.url.hostname)) || (dualCerts && newIpsWWW?.length === 0 && !newIpsWWW.includes(`${isWWW ? nonWWW : domain}`))) {
// throw {
// message: t.get('application.dns_not_set_error', { domain })
// };
// }
// }
// if (localIps?.length > 0) {
// if (newIps?.length === 0 || !localIps.includes(newIps[0])) {
// throw {
// message: t.get('application.dns_not_set_error', { domain })
// };
// }
// }
}
if (isDNSCheckEnabled && !forceSave) {
return await checkDomainsIsValidInDNS({ event, fqdn, dualCerts });
}
return {
status: 200
};

View File

@@ -31,7 +31,7 @@
import Setting from '$lib/components/Setting.svelte';
import Explainer from '$lib/components/Explainer.svelte';
import { errorNotification } from '$lib/form';
import { del, post } from '$lib/api';
import { del, get, post } from '$lib/api';
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { browser } from '$app/env';
import { getDomain } from '$lib/components/common';
@@ -49,6 +49,7 @@
let forceSave = false;
let fqdn = settings.fqdn;
let nonWWWDomain = fqdn && getDomain(fqdn).replace(/^www\./, '');
let isFqdnSet = !!settings.fqdn;
let loading = {
save: false,
@@ -96,6 +97,7 @@
async function handleSubmit() {
try {
loading.save = true;
nonWWWDomain = fqdn && getDomain(fqdn).replace(/^www\./, '');
if (fqdn !== settings.fqdn) {
await post(`/settings/check.json`, { fqdn, forceSave, dualCerts, isDNSCheckEnabled });
await post(`/settings.json`, { fqdn });
@@ -106,6 +108,7 @@
settings.minPort = minPort;
settings.maxPort = maxPort;
}
forceSave = false;
} catch ({ error }) {
if (error?.startsWith($t('application.dns_not_set_partial_error'))) {
forceSave = true;
@@ -123,6 +126,14 @@
return errorNotification(error);
}
}
async function isDNSValid(domain) {
try {
await get(`/settings/check.json?domain=${domain}`);
toast.push('Domain is valid in DNS.');
} catch ({ error }) {
return errorNotification(error);
}
}
</script>
<div class="flex space-x-1 p-6 font-bold">
@@ -176,6 +187,23 @@
pattern="^https?://([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{'{'}2,{'}'}$"
placeholder="{$t('forms.eg')}: https://coolify.io"
/>
{#if forceSave}
<div class="pt-4">
<button
class="bg-coollabs hover:bg-coollabs-100"
on:click|preventDefault={() => isDNSValid(getDomain(nonWWWDomain))}
>Check {nonWWWDomain} DNS Record</button
>
{#if dualCerts}
<button
class="bg-coollabs hover:bg-coollabs-100"
on:click|preventDefault={() => isDNSValid(getDomain(`www.${nonWWWDomain}`))}
>Check www.{nonWWWDomain} DNS Record</button
>
{/if}
</div>
{/if}
</div>
</div>
<div class="grid grid-cols-2 items-start py-6">