Production hardening: host-aware install, ownership contracts, firewall safety
This commit is contained in:
@@ -1,8 +1,32 @@
|
||||
import type { InstallContext } from "../types/context";
|
||||
import { readText, renderTemplate, writeText } from "../lib/fs";
|
||||
import { info } from "../lib/log";
|
||||
import { exists, readText, renderTemplate, writeText } from "../lib/fs";
|
||||
import { fail, info } from "../lib/log";
|
||||
import { runVisible } from "../lib/process";
|
||||
|
||||
function stripNftComments(content: string): string {
|
||||
return content
|
||||
.split(/\r?\n/)
|
||||
.map((line) => line.replace(/#.*/, "").trim())
|
||||
.filter(Boolean)
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
function isSafeNftablesEntrypoint(content: string): boolean {
|
||||
if (content.includes("HY2XS-MANAGED")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const effective = stripNftComments(content)
|
||||
.replace(/^#!\/usr\/sbin\/nft\s+-f\s*/m, "")
|
||||
.trim();
|
||||
|
||||
if (!effective) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return effective === "flush ruleset";
|
||||
}
|
||||
|
||||
export async function applyFirewall(context: InstallContext): Promise<void> {
|
||||
if (context.options.skipFirewall || !context.config.firewallEnabled) {
|
||||
info("firewall skipped by flag");
|
||||
@@ -17,11 +41,17 @@ export async function applyFirewall(context: InstallContext): Promise<void> {
|
||||
const rendered = renderTemplate(await readText(`${context.options.packageDir}/templates/nftables/hy2xs.nft.tpl`), {
|
||||
SSH_PORT: context.config.sshPort,
|
||||
HYSTERIA_PORT: context.config.hysteriaPort,
|
||||
UI_PORT: context.config.uiPort,
|
||||
UI_BIND_HOST: context.config.uiBindHost,
|
||||
ACME_RULE: acmeRule
|
||||
});
|
||||
|
||||
const existing = await exists("/etc/nftables.conf")
|
||||
? await readText("/etc/nftables.conf")
|
||||
: "";
|
||||
|
||||
if (existing && !isSafeNftablesEntrypoint(existing) && !context.config.firewallAllowTakeover) {
|
||||
fail("existing non-HY2XS nftables.conf found; set HY2XS_FIREWALL_ALLOW_TAKEOVER=true or HY2XS_FIREWALL_ENABLED=false");
|
||||
}
|
||||
|
||||
await runVisible`cp -a /etc/nftables.conf /etc/nftables.conf.hy2xs.bak 2>/dev/null || true`;
|
||||
await runVisible`cp -a /etc/nftables.d/hy2xs.nft /etc/nftables.d/hy2xs.nft.bak 2>/dev/null || true`;
|
||||
await runVisible`test -f /etc/nftables.d/hy2xs.nft && echo 1 > /etc/nftables.d/hy2xs.nft.existed || rm -f /etc/nftables.d/hy2xs.nft.existed`;
|
||||
@@ -30,6 +60,9 @@ export async function applyFirewall(context: InstallContext): Promise<void> {
|
||||
await runVisible`nft -c -f /etc/nftables.d/hy2xs.nft.candidate`;
|
||||
|
||||
const nftablesConf = `#!/usr/sbin/nft -f
|
||||
# HY2XS-MANAGED: root nftables entrypoint
|
||||
# Generated by hy2xs-orchestrator. Do not edit manually; edit /etc/hy2xs/hy2xs.env and run reconfigure.
|
||||
|
||||
flush ruleset
|
||||
|
||||
include "/etc/nftables.d/hy2xs.nft"
|
||||
|
||||
Reference in New Issue
Block a user