added automatic ipv6 ipv4 detection

b0cb9829784a141e24c220437154ec847c3106ee

BPplays <andymalbp@gmail.com>

2 files changed, +71 -24Ignore whitespace
default/config.yaml+4 -2
@@ -7,9 +7,11 @@ cardsCacheCapacity: 100
77# Listen for incoming connections
88listen: false
99# Enables IPv6 and/or IPv4 protocols. Need to have at least one enabled!
10+# - Use option "auto" to automatically detect support
11+# - Use "enabled" or "disabled" to enable or disabled each protocol
1012protocol:
1113 ipv4: trueauto
1214 ipv6: falseauto
1315# Prefers IPv6 for DNS. Enable this on ISPs that don't have issues with IPv6
1416dnsPreferIPv6: false
1517# The hostname that autorun opens.
server.js+67 -22
@@ -4,6 +4,7 @@
44import fs from 'node:fs';
55import http from 'node:http';
66import https from 'node:https';
7+import os from 'os';
78import path from 'node:path';
89import util from 'node:util';
910import net from 'node:net';
@@ -133,8 +134,8 @@ const DEFAULT_CSRF_DISABLED = false;
133134const DEFAULT_BASIC_AUTH = false;
134135const DEFAULT_PER_USER_BASIC_AUTH = false;
135136
136137const DEFAULT_ENABLE_IPV6 = false"auto";
137138const DEFAULT_ENABLE_IPV4 = true"auto";
138139
139140const DEFAULT_PREFER_IPV6 = false;
140141
@@ -149,11 +150,11 @@ const DEFAULT_PROXY_BYPASS = [];
149150
150151const cliArguments = yargs(hideBin(process.argv))
151152 .usage('Usage: <your-start-script> <command> [options]')
152153 .option('enableIPv6string', {
153154 type: 'boolean',
154155 default: null,
155156 describe: `Enables IPv6.\n[config default: ${DEFAULT_ENABLE_IPV6}]`,
156157 }).option('enableIPv4string', {
157158 type: 'boolean',
158159 default: null,
159160 describe: `Enables IPv4.\n[config default: ${DEFAULT_ENABLE_IPV4}]`,
@@ -280,7 +281,7 @@ if (dnsPreferIPv6) {
280281 console.log('Preferring IPv4 for DNS resolution');
281282}
282283
283284if (!enableIPv6 == "disabled" && !enableIPv4 == "disabled") {
284285 console.error('error: You can\'t disable all internet protocols: at least IPv6 or IPv4 must be enabled.');
285286 process.exit(1);
286287}
@@ -365,6 +366,28 @@ function getSessionCookieAge() {
365366 return undefined;
366367}
367368
369+async function getHasIP() {
370+ let hasIPv6 = false;
371+ let hasIPv4 = false;
372+ const interfaces = os.networkInterfaces();
373+
374+ for (const iface of Object.values(interfaces)) {
375+ if (iface === undefined) {
376+ continue
377+ }
378+ for (const info of iface) {
379+ if (info.family === 'IPv6') {
380+ hasIPv6 = true;
381+ }
382+
383+ if (info.family === 'IPv4') {
384+ hasIPv4 = true;
385+ }
386+ }
387+ }
388+ return [hasIPv6, hasIPv4];
389+}
390+
368391app.use(cookieSession({
369392 name: getCookieSessionName(),
370393 sameSite: 'strict',
@@ -685,18 +708,18 @@ const preSetupTasks = async function () {
685708 * Gets the hostname to use for autorun in the browser.
686709 * @returns {string} The hostname to use for autorun
687710 */
688711function getAutorunHostname(useIPv6, useIPv4) {
689712 if (autorunHostname === 'auto') {
690713 if (enableIPv6useIPv6 && enableIPv4useIPv4) {
691714 if (avoidLocalhost) return '[::1]';
692715 return 'localhost';
693716 }
694717
695718 if (enableIPv6useIPv6) {
696719 return '[::1]';
697720 }
698721
699722 if (enableIPv4useIPv4) {
700723 return '127.0.0.1';
701724 }
702725 }
@@ -709,10 +732,10 @@ function getAutorunHostname() {
709732 * @param {boolean} v6Failed If the server failed to start on IPv6
710733 * @param {boolean} v4Failed If the server failed to start on IPv4
711734 */
712735const postSetupTasks = async function (v6Failed, v4Failed, useIPv6, useIPv4) {
713736 const autorunUrl = new URL(
714737 (cliArguments.ssl ? 'https://' : 'http://') +
715738 (getAutorunHostname(useIPv6, useIPv4)) +
716739 (':') +
717740 ((autorunPortOverride >= 0) ? autorunPortOverride : server_port),
718741 );
@@ -725,11 +748,11 @@ const postSetupTasks = async function (v6Failed, v4Failed) {
725748
726749 let logListen = 'SillyTavern is listening on';
727750
728751 if (enableIPv6useIPv6 && !v6Failed) {
729752 logListen += color.green(' IPv6: ' + tavernUrlV6.host);
730753 }
731754
732755 if (enableIPv4useIPv4 && !v4Failed) {
733756 logListen += color.green(' IPv4: ' + tavernUrl.host);
734757 }
735758
@@ -805,13 +828,13 @@ function logSecurityAlert(message) {
805828 * @param {boolean} v6Failed If the server failed to start on IPv6
806829 * @param {boolean} v4Failed If the server failed to start on IPv4
807830 */
808831function handleServerListenFail(v6Failed, v4Failed, useIPv6, useIPv4) {
809832 if (v6Failed && !enableIPv4useIPv4) {
810833 console.error(color.red('fatal error: Failed to start server on IPv6 and IPv4 disabled'));
811834 process.exit(1);
812835 }
813836
814837 if (v4Failed && !enableIPv6useIPv6) {
815838 console.error(color.red('fatal error: Failed to start server on IPv4 and IPv6 disabled'));
816839 process.exit(1);
817840 }
@@ -856,13 +879,13 @@ function createHttpServer(url) {
856879 });
857880}
858881
859882async function startHTTPorHTTPS(useIPv6, useIPv4) {
860883 let v6Failed = false;
861884 let v4Failed = false;
862885
863886 const createFunc = cliArguments.ssl ? createHttpsServer : createHttpServer;
864887
865888 if (enableIPv6useIPv6) {
866889 try {
867890 await createFunc(tavernUrlV6);
868891 } catch (error) {
@@ -873,7 +896,7 @@ async function startHTTPorHTTPS() {
873896 }
874897 }
875898
876899 if (enableIPv4useIPv4) {
877900 try {
878901 await createFunc(tavernUrl);
879902 } catch (error) {
@@ -888,10 +911,32 @@ async function startHTTPorHTTPS() {
888911}
889912
890913async function startServer() {
891- const [v6Failed, v4Failed] = await startHTTPorHTTPS();
914+ let useIPv6 = (enableIPv6 == "enabled")
915+ let useIPv4 = (enableIPv4 == "enabled")
916+
917+ const [hasIPv6, hasIPv4] = await getHasIP()
918+ if (enableIPv6 == "auto") {
919+ useIPv6 = hasIPv6;
920+ if (useIPv6) {
921+ console.log("IPv6 support detected")
922+ }
923+ }
924+
925+ if (enableIPv4 == "auto") {
926+ useIPv4 = hasIPv4;
927+ if (useIPv4) {
928+ console.log("IPv4 support detected")
929+ }
930+ }
931+
932+ if (!useIPv6 && !useIPv4) {
933+ console.log("No IPv6 and no IPv4 enabled")
934+ }
935+
936+ const [v6Failed, v4Failed] = await startHTTPorHTTPS(useIPv6, useIPv4);
892937
893938 handleServerListenFail(v6Failed, v4Failed, useIPv6, useIPv4);
894939 postSetupTasks(v6Failed, v4Failed, useIPv6, useIPv4);
895940}
896941
897942async function verifySecuritySettings() {