fixes various bugs for Tor service

This commit is contained in:
Shahrad Elahi
2024-02-12 13:05:46 +03:30
parent 0d9128cfab
commit b3b9beddf3
9 changed files with 78 additions and 41 deletions

View File

@@ -1,5 +1,4 @@
import { execa } from 'execa';
import logger from '$lib/logger';
import { ip } from 'node-netkit';
export default class Network {
@@ -18,7 +17,6 @@ export default class Network {
const { stdout: o } = await execa(`ip link show | grep ${inet}`, { shell: true });
return o.trim() !== '';
} catch (e) {
logger.debug('Interface does not exist:', inet);
return false;
}
}

View File

@@ -11,6 +11,7 @@ import { sha256 } from '$lib/hash';
import { fsAccess } from '$lib/fs-extra';
import { client } from '$lib/storage';
import { execa } from 'execa';
import { ip } from 'node-netkit';
export class WGServer {
readonly id: string;
@@ -32,12 +33,16 @@ export class WGServer {
static exists(id: string): boolean {
const serverIds = getServers().map((s) => s.id);
logger.debug({
message: `WGServer:Exists: checking for server with id: ${id}`,
servers: serverIds,
});
const exists = serverIds.includes(id);
return serverIds.includes(id);
if (!exists) {
logger.debug({
message: `WGServer: Exists: server by id of ${id} does not exists`,
servers: serverIds,
});
}
return exists;
}
async get(): Promise<WgServer> {
@@ -62,11 +67,16 @@ export class WGServer {
async stop(): Promise<boolean> {
const server = await this.get();
if (await Network.interfaceExists(`wg${server.confId}`)) {
await execa(`wg-quick down wg${server.confId}`, { shell: true });
const iface = `wg${server.confId}`;
if (await Network.interfaceExists(iface)) {
await execa(`wg-quick down ${iface}`, { shell: true });
}
await this.update({ status: 'down' });
// TODO: Drop any iptables rules related the interface
return true;
}
@@ -79,7 +89,6 @@ export class WGServer {
}
const isAlreadyUp = await this.isUp();
logger.debug('WGServer:Start: isAlreadyUp:', isAlreadyUp);
if (isAlreadyUp) {
logger.debug('WGServer:Start: interface already up... taking down');
await execa(`wg-quick down wg${server.confId}`, { shell: true });
@@ -121,9 +130,6 @@ export class WGServer {
return true;
}
console.log('WGServer:Update: updating server at index:', index);
console.log(client.lrange(WG_SEVER_PATH, 0, -1));
client.lset(
WG_SEVER_PATH,
index,
@@ -703,15 +709,23 @@ export async function findServer(
export async function makeWgIptables(s: WgServer): Promise<{ up: string; down: string }> {
const source = `${s.address}/24`;
const route = await ip.route.defaultRoute();
const wg_inet = `wg${s.confId}`;
if (!route) {
throw new Error('No default route found');
}
const { stdout: inet_address } = await execa(`hostname -i | awk '{print $1}'`, { shell: true });
if (s.tor) {
const up = dynaJoin([
`iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT`,
`iptables -A INPUT -i ${wg_inet} -s ${source} -m state --state NEW -j ACCEPT`,
`iptables -t nat -A PREROUTING -i ${wg_inet} -p udp -s ${source} --dport 53 -j DNAT --to-destination 127.0.0.1:53530`,
`iptables -t nat -A PREROUTING -i ${wg_inet} -p tcp -s ${source} -j DNAT --to-destination 127.0.0.1:59040`,
`iptables -t nat -A PREROUTING -i ${wg_inet} -p udp -s ${source} -j DNAT --to-destination 127.0.0.1:59040`,
`iptables -t nat -A PREROUTING -i ${wg_inet} -p udp -s ${source} --dport 53 -j DNAT --to-destination ${inet_address}:53530`,
`iptables -t nat -A PREROUTING -i ${wg_inet} -p tcp -s ${source} -j DNAT --to-destination ${inet_address}:59040`,
`iptables -t nat -A PREROUTING -i ${wg_inet} -p udp -s ${source} -j DNAT --to-destination ${inet_address}:59040`,
`iptables -t nat -A OUTPUT -o lo -j RETURN`,
`iptables -A OUTPUT -m conntrack --ctstate INVALID -j DROP`,
`iptables -A OUTPUT -m state --state INVALID -j DROP`,
@@ -720,9 +734,8 @@ export async function makeWgIptables(s: WgServer): Promise<{ up: string; down: s
return { up, down: up.replace(/-A/g, '-D') };
}
const inet = await Network.defaultInterface();
const up = dynaJoin([
`iptables -t nat -A POSTROUTING -s ${source} -o ${inet} -j MASQUERADE`,
`iptables -t nat -A POSTROUTING -s ${source} -o ${route.dev} -j MASQUERADE`,
`iptables -A INPUT -p udp -m udp --dport ${s.listen} -j ACCEPT`,
`iptables -A INPUT -p tcp -m tcp --dport ${s.listen} -j ACCEPT`,
`iptables -A FORWARD -i ${wg_inet} -j ACCEPT`,

View File

@@ -2,8 +2,12 @@ import { json, type RequestHandler } from '@sveltejs/kit';
import { execa } from 'execa';
export const GET: RequestHandler = async ({ params }) => {
const { stdout } = await execa('screen', ['-ls'], { shell: true });
const isRunning = stdout.includes(params.serviceName!);
try {
const { stdout } = await execa('screen', ['-ls'], { shell: true });
const isRunning = stdout.includes(params.serviceName!);
return json({ healthy: isRunning });
return json({ healthy: isRunning });
} catch (e) {
return json({ healthy: false });
}
};

View File

@@ -8,24 +8,18 @@ const services: Record<string, Service> = {
tor: {
name: 'Tor',
command: {
restart: 'screen -L -Logfile /var/vlogs/tor -dmS "tor" tor -f /etc/tor/torrc',
start: 'screen -L -Logfile /var/vlogs/tor -dmS "tor" tor -f /etc/tor/torrc',
stop: 'pkill tor',
logs: 'logs tor',
},
},
redis: {
name: 'Redis',
command: {
restart:
'screen -L -Logfile /var/vlogs/redis -dmS "redis" bash -c "redis-server --port 6479 --daemonize no --dir /data --appendonly yes"',
logs: 'logs redis',
},
},
};
interface Service {
name: string;
command: {
restart: string;
start: string;
stop: string;
logs: string;
};
}
@@ -41,6 +35,25 @@ export const load: PageServerLoad = async ({ params }) => {
};
};
function restartService(serviceName: string) {
// Stop
const { exitCode: stopExitCode } = execa(services[serviceName].command.stop, { shell: true });
// Start
const { exitCode: startExitCode } = execa(services[serviceName].command.start, { shell: true });
logger.info({
message: `Restarted ${serviceName} service`,
stopExitCode,
startExitCode,
});
return {
stopExitCode,
startExitCode,
};
}
export const actions: Actions = {
clearLogs: async ({ request, params }) => {
const { serviceName } = params;
@@ -68,8 +81,8 @@ export const actions: Actions = {
const { serviceName } = params;
try {
await execa(services[serviceName!].command.restart, { shell: true });
return {};
const { stopExitCode, startExitCode } = restartService(serviceName!);
return { stopExitCode, startExitCode };
} catch (e) {
logger.error(e);
throw error(500, 'Unhandled Exception');

View File

@@ -73,7 +73,7 @@
<CardTitle>Logs</CardTitle>
</CardHeader>
<CardContent class="relative">
<textarea class="w-full h-64 p-2 bg-gray-100" readonly bind:value={logs} />
<textarea class="w-full h-80 p-2 bg-gray-100" readonly bind:value={logs} />
{#if !logs}
<div class="absolute inset-0 flex items-center justify-center">
<i class="text-4xl animate-spin fas fa-circle-notch"></i>