mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Rewrite to only consider Docker
This commit is contained in:
@@ -42,7 +42,8 @@ enableForwardedWhitelist: true
|
|||||||
whitelist:
|
whitelist:
|
||||||
- ::1
|
- ::1
|
||||||
- 127.0.0.1
|
- 127.0.0.1
|
||||||
- gateway.docker.internal
|
# Automatically whitelist Docker host and gateway IPs
|
||||||
|
whitelistDockerHosts: true
|
||||||
# Toggle basic authentication for endpoints
|
# Toggle basic authentication for endpoints
|
||||||
basicAuthMode: false
|
basicAuthMode: false
|
||||||
# Basic authentication credentials
|
# Basic authentication credentials
|
||||||
|
@@ -3,14 +3,15 @@ import fs from 'node:fs';
|
|||||||
import process from 'node:process';
|
import process from 'node:process';
|
||||||
import dns from 'node:dns';
|
import dns from 'node:dns';
|
||||||
import Handlebars from 'handlebars';
|
import Handlebars from 'handlebars';
|
||||||
import ipRegex from 'ip-regex';
|
|
||||||
import ipMatching from 'ip-matching';
|
import ipMatching from 'ip-matching';
|
||||||
|
import isDocker from 'is-docker';
|
||||||
|
|
||||||
import { getIpFromRequest } from '../express-common.js';
|
import { getIpFromRequest } from '../express-common.js';
|
||||||
import { color, getConfigValue, safeReadFileSync } from '../util.js';
|
import { color, getConfigValue, safeReadFileSync } from '../util.js';
|
||||||
|
|
||||||
const whitelistPath = path.join(process.cwd(), './whitelist.txt');
|
const whitelistPath = path.join(process.cwd(), './whitelist.txt');
|
||||||
const enableForwardedWhitelist = getConfigValue('enableForwardedWhitelist', false, 'boolean');
|
const enableForwardedWhitelist = !!getConfigValue('enableForwardedWhitelist', false, 'boolean');
|
||||||
|
const whitelistDockerHosts = !!getConfigValue('whitelistDockerHosts', false, 'boolean');
|
||||||
/** @type {string[]} */
|
/** @type {string[]} */
|
||||||
let whitelist = getConfigValue('whitelist', []);
|
let whitelist = getConfigValue('whitelist', []);
|
||||||
|
|
||||||
@@ -48,69 +49,26 @@ function getForwardedIp(req) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a string is a valid hostname according to RFC 1123
|
|
||||||
* @param {string} hostname The string to test
|
|
||||||
* @returns {boolean} True if the string is a valid hostname
|
|
||||||
*/
|
|
||||||
function isValidHostname(hostname) {
|
|
||||||
const hostnameRegex = /^(([a-z0-9]|[a-z0-9][a-z0-9-]*[a-z0-9])\.)*([a-z0-9]|[a-z0-9][a-z0-9-]*[a-z0-9])$/i;
|
|
||||||
return hostnameRegex.test(hostname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a string is an IP address, CIDR notation, or IP wildcard
|
|
||||||
* @param {string} entry The string to test
|
|
||||||
* @returns {boolean} True if the string matches any IP format
|
|
||||||
*/
|
|
||||||
function isIpFormat(entry) {
|
|
||||||
// Match CIDR notation (e.g. 192.168.0.0/24)
|
|
||||||
if (entry.includes('/')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match exact IP address
|
|
||||||
if (ipRegex({ exact: true }).test(entry)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match IPv4 with wildcards (e.g. 192.168.*.* or 192.168.0.*)
|
|
||||||
const ipWildcardRegex = /^(\d{1,3}|\*)\.(\d{1,3}|\*)\.(\d{1,3}|\*)\.(\d{1,3}|\*)$/;
|
|
||||||
return ipWildcardRegex.test(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves hostnames in the whitelist to IP addresses.
|
* Resolves hostnames in the whitelist to IP addresses.
|
||||||
* This function will modify the whitelist array in place.
|
* This function will modify the whitelist array in place.
|
||||||
*/
|
*/
|
||||||
async function resolveHostnames() {
|
async function addDockerHostsToWhitelist() {
|
||||||
const resolvedWhitelist = [];
|
if (!whitelistDockerHosts || !isDocker()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const promises = whitelist.map(async (entry) => {
|
const whitelistHosts = ['host.docker.internal', 'gateway.docker.internal'];
|
||||||
if (!entry || typeof entry !== 'string') {
|
|
||||||
return;
|
for (const entry of whitelistHosts) {
|
||||||
|
try {
|
||||||
|
const result = await dns.promises.lookup(entry);
|
||||||
|
console.info(`Resolved whitelist hostname ${color.green(entry)} to IPv${result.family} address ${color.green(result.address)}`);
|
||||||
|
whitelist.push(result.address);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`Failed to resolve whitelist hostname ${color.red(entry)}: ${e.message}`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Skip if entry appears to be an IP address, CIDR notation, or IP wildcard
|
|
||||||
if (isIpFormat(entry)) {
|
|
||||||
resolvedWhitelist.push(entry);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isValidHostname(entry)) {
|
|
||||||
try {
|
|
||||||
const result = await dns.promises.lookup(entry);
|
|
||||||
console.info(`Resolved whitelist hostname ${color.green(entry)} to IPv${result.family} address ${color.green(result.address)}`);
|
|
||||||
resolvedWhitelist.push(result.address);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(`Failed to resolve whitelist hostname ${color.red(entry)}: ${e.message}`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
resolvedWhitelist.push(entry);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await Promise.allSettled(promises);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,7 +84,7 @@ export default async function getWhitelistMiddleware() {
|
|||||||
'/favicon.ico',
|
'/favicon.ico',
|
||||||
];
|
];
|
||||||
|
|
||||||
await resolveHostnames();
|
await addDockerHostsToWhitelist();
|
||||||
|
|
||||||
return function (req, res, next) {
|
return function (req, res, next) {
|
||||||
const clientIp = getIpFromRequest(req);
|
const clientIp = getIpFromRequest(req);
|
||||||
|
Reference in New Issue
Block a user