From 5a9415ae0c2ba36cb6f3f527b04c3058d90d84a2 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Tue, 9 Sep 2025 23:54:33 -0700 Subject: [PATCH] feat: bindAddress (#2766) so people can limit the server to only be reachable via 127.0.0.1 etc Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2766 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- config-vanilla.json | 1 + src/services/configService.ts | 15 ++++++++++++++ src/services/configWatcherService.ts | 14 +++++++++---- src/services/webService.ts | 31 +++++++++++++++------------- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/config-vanilla.json b/config-vanilla.json index 8ac9c564..1018a4b1 100644 --- a/config-vanilla.json +++ b/config-vanilla.json @@ -5,6 +5,7 @@ "level": "trace" }, "myAddress": "localhost", + "bindAddress": "0.0.0.0", "httpPort": 80, "httpsPort": 443, "administratorNames": [], diff --git a/src/services/configService.ts b/src/services/configService.ts index 2c7c9e01..79e653b6 100644 --- a/src/services/configService.ts +++ b/src/services/configService.ts @@ -12,6 +12,7 @@ export interface IConfig { level: string; // "fatal" | "error" | "warn" | "info" | "http" | "debug" | "trace"; }; myAddress: string; + bindAddress?: string; httpPort?: number; httpsPort?: number; ircAddress?: string; @@ -188,3 +189,17 @@ export const getReflexiveAddress = (request: Request): { myAddress: string; myUr } return { myAddress, myUrlBase }; }; + +export interface IBindings { + address: string; + httpPort: number; + httpsPort: number; +} + +export const configGetWebBindings = (): IBindings => { + return { + address: config.bindAddress || "0.0.0.0", + httpPort: config.httpPort || 80, + httpsPort: config.httpsPort || 443 + }; +}; diff --git a/src/services/configWatcherService.ts b/src/services/configWatcherService.ts index d0f72981..b33efd0a 100644 --- a/src/services/configWatcherService.ts +++ b/src/services/configWatcherService.ts @@ -2,6 +2,7 @@ import chokidar from "chokidar"; import { logger } from "../utils/logger.ts"; import { config, + configGetWebBindings, configPath, configRemovedOptionsKeys, loadConfig, @@ -9,7 +10,7 @@ import { type IConfig } from "./configService.ts"; import { saveConfig, shouldReloadConfig } from "./configWriterService.ts"; -import { getWebPorts, startWebServer, stopWebServer } from "./webService.ts"; +import { getWebBindings, startWebServer, stopWebServer } from "./webService.ts"; import { sendWsBroadcast } from "./wsService.ts"; import varzia from "../../static/fixed_responses/worldState/varzia.json" with { type: "json" }; @@ -25,9 +26,14 @@ chokidar.watch(configPath).on("change", () => { validateConfig(); syncConfigWithDatabase(); - const webPorts = getWebPorts(); - if (config.httpPort != webPorts.http || config.httpsPort != webPorts.https) { - logger.info(`Restarting web server to apply port changes.`); + const configBindings = configGetWebBindings(); + const bindings = getWebBindings(); + if ( + configBindings.address != bindings.address || + configBindings.httpPort != bindings.httpPort || + configBindings.httpsPort != bindings.httpsPort + ) { + logger.info(`Restarting web server to apply binding changes.`); // Tell webui clients to reload with new port sendWsBroadcast({ ports: { http: config.httpPort, https: config.httpsPort } }); diff --git a/src/services/webService.ts b/src/services/webService.ts index 6dd1a5dd..0954917a 100644 --- a/src/services/webService.ts +++ b/src/services/webService.ts @@ -1,7 +1,7 @@ import http from "http"; import https from "https"; import fs from "node:fs"; -import { config } from "./configService.ts"; +import { configGetWebBindings, type IBindings } from "./configService.ts"; import { logger } from "../utils/logger.ts"; import { app } from "../app.ts"; import type { AddressInfo } from "node:net"; @@ -17,33 +17,35 @@ const tlsOptions = { }; export const startWebServer = (): void => { - const httpPort = config.httpPort || 80; - const httpsPort = config.httpsPort || 443; + const bindings = configGetWebBindings(); // eslint-disable-next-line @typescript-eslint/no-misused-promises httpServer = http.createServer(app); - httpServer.listen(httpPort, () => { + httpServer.listen(bindings.httpPort, bindings.address, () => { startWsServer(httpServer!); - logger.info("HTTP server started on port " + httpPort); + logger.info(`HTTP server started on ${bindings.address}:${bindings.httpPort}`); // eslint-disable-next-line @typescript-eslint/no-misused-promises httpsServer = https.createServer(tlsOptions, app); - httpsServer.listen(httpsPort, () => { + httpsServer.listen(bindings.httpsPort, bindings.address, () => { startWssServer(httpsServer!); - logger.info("HTTPS server started on port " + httpsPort); + logger.info(`HTTPS server started on ${bindings.address}:${bindings.httpsPort}`); logger.info( - "Access the WebUI in your browser at http://localhost" + (httpPort == 80 ? "" : ":" + httpPort) + "Access the WebUI in your browser at http://localhost" + + (bindings.httpPort == 80 ? "" : ":" + bindings.httpPort) ); - void runWsSelfTest("wss", httpsPort).then(ok => { + void runWsSelfTest("wss", bindings.httpsPort).then(ok => { if (!ok) { - logger.warn(`WSS self-test failed. The server may not actually be reachable at port ${httpsPort}.`); + logger.warn( + `WSS self-test failed. The server may not be reachable locally on port ${bindings.httpsPort}.` + ); if (process.platform == "win32") { logger.warn( - `You can check who actually has that port via powershell: Get-Process -Id (Get-NetTCPConnection -LocalPort ${httpsPort}).OwningProcess` + `You can check who has that port via powershell: Get-Process -Id (Get-NetTCPConnection -LocalPort ${bindings.httpsPort}).OwningProcess` ); } } @@ -80,10 +82,11 @@ const runWsSelfTest = (protocol: "ws" | "wss", port: number): Promise = }); }; -export const getWebPorts = (): Record<"http" | "https", number | undefined> => { +export const getWebBindings = (): Partial => { return { - http: (httpServer?.address() as AddressInfo | undefined)?.port, - https: (httpsServer?.address() as AddressInfo | undefined)?.port + address: (httpServer?.address() as AddressInfo | undefined)?.address, + httpPort: (httpServer?.address() as AddressInfo | undefined)?.port, + httpsPort: (httpsServer?.address() as AddressInfo | undefined)?.port }; };