Skip to content

Commit

Permalink
Refactor DNS handling to improve validation and connection management
Browse files Browse the repository at this point in the history
  • Loading branch information
micthiesen committed Oct 26, 2024
1 parent c4da010 commit 0e174f9
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 24 deletions.
31 changes: 24 additions & 7 deletions src/dns.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import env from "./env";
import { getSshConnection, type SNodeSSH } from "./ssh";
import { parseDnsServers } from "./parsing";
import { withSshConnection, type SNodeSSH } from "./ssh";
import { arrayItemsEqual } from "./utils";

let timeoutId: NodeJS.Timeout | null = null;
const RESTORE_DELAY = 1000 * 60 * 2;
Expand All @@ -14,15 +16,30 @@ export async function toggleDns(ssh: SNodeSSH) {
console.log(`Scheduled restore in ${RESTORE_DELAY}ms`);
}

export async function validateDns(ssh: SNodeSSH): Promise<string> {
console.log("Validating DNS servers...");
const currentDnsServers = await getDnsServers(ssh);
console.log(`DNS servers are set to ${currentDnsServers}`);

if (arrayItemsEqual(currentDnsServers, env.PRIMARY_DNS_SERVERS)) {
return "DNS servers are valid";
} else {
await setDnsServers(ssh, env.PRIMARY_DNS_SERVERS);
console.log(`DNS servers restored to ${env.PRIMARY_DNS_SERVERS}`);
return "DNS servers restored";
}
}

async function restoreDnsServers() {
console.log("Restoring original DNS servers...");
let ssh: SNodeSSH | undefined;
try {
ssh = await getSshConnection();
await withSshConnection(async (ssh) => {
await setDnsServers(ssh, env.PRIMARY_DNS_SERVERS);
} finally {
if (ssh) ssh.dispose();
}
});
}

async function getDnsServers(ssh: SNodeSSH) {
const dnsServers = await ssh.execSafe("cat /config/config.boot | grep 'name-server'");
return parseDnsServers(dnsServers);
}

async function setDnsServers(ssh: SNodeSSH, dns: [string, string]) {
Expand Down
34 changes: 19 additions & 15 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { type HttpBindings, serve } from "@hono/node-server";
import { Hono } from "hono";
import { toggleDns } from "./dns";
import { getSshConnection, type SNodeSSH } from "./ssh";
import { logger } from "hono/logger";
import { timeout } from "hono/timeout";
import { toggleDns, validateDns } from "./dns";
import { withSshConnection } from "./ssh";

const app = new Hono<{ Bindings: HttpBindings }>();
app.use(logger(), timeout(10000));
app.onError(async (err, ctx) => {
return ctx.text(`Error: ${err.message}`);
});

app.get("/toggle-dns", async (c) => {
console.log(`${c.env.incoming.method} ${c.env.incoming.url}`);

let ssh: SNodeSSH | undefined;
try {
ssh = await getSshConnection();
app.get("/dns/toggle", async (ctx) => {
return withSshConnection(async (ssh) => {
await toggleDns(ssh);
return c.text("DNS servers toggled");
} catch (err: any) {
console.warn(err.message);
return c.text(`Error: ${err.message}`);
} finally {
if (ssh) ssh.dispose();
}
return ctx.text("DNS servers toggled");
});
});

app.get("/dns/validate", async (ctx) => {
return withSshConnection(async (ssh) => {
const dnsServers = await validateDns(ssh);
return ctx.text(dnsServers.toString());
});
});

serve({ fetch: app.fetch, port: 5888 }, (info) => {
Expand Down
2 changes: 1 addition & 1 deletion src/parsing.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { z } from "zod";

const dnsRegex = /dns-server\s+([\d.]+)/g;
const dnsRegex = /(?:dns|name)-server\s+([\d.]+)/g;
const dnsSchema = z
.string()
.transform((text) => Array.from(text.matchAll(dnsRegex)).map((match) => match[1]))
Expand Down
14 changes: 13 additions & 1 deletion src/ssh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,19 @@ export type SNodeSSH = NodeSSH & {
configure: (commands: string[]) => Promise<string>;
};

export async function getSshConnection(): Promise<SNodeSSH> {
export async function withSshConnection<T>(
fn: (ssh: SNodeSSH) => Promise<T>,
): Promise<T> {
let ssh: SNodeSSH | undefined;
try {
ssh = await getSshConnection();
return await fn(ssh);
} finally {
if (ssh) ssh.dispose();
}
}

async function getSshConnection(): Promise<SNodeSSH> {
const ssh = new NodeSSH() as SNodeSSH;
await ssh.connect({
host: env.ROUTER_HOSTNAME,
Expand Down
6 changes: 6 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function arrayItemsEqual<T extends number | string>(a: T[], b: T[]): boolean {
for (const i of a) {
if (b.indexOf(i) === -1) return false;
}
return a.length === b.length;
}

0 comments on commit 0e174f9

Please sign in to comment.