mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Resolve hostnames from whitelist
This commit is contained in:
@@ -42,6 +42,7 @@ enableForwardedWhitelist: true
|
||||
whitelist:
|
||||
- ::1
|
||||
- 127.0.0.1
|
||||
- host.docker.internal
|
||||
# Toggle basic authentication for endpoints
|
||||
basicAuthMode: false
|
||||
# Basic authentication credentials
|
||||
|
@@ -1,7 +1,9 @@
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import process from 'node:process';
|
||||
import dns from 'node:dns';
|
||||
import Handlebars from 'handlebars';
|
||||
import ipRegex from 'ip-regex';
|
||||
import ipMatching from 'ip-matching';
|
||||
|
||||
import { getIpFromRequest } from '../express-common.js';
|
||||
@@ -20,6 +22,8 @@ if (fs.existsSync(whitelistPath)) {
|
||||
}
|
||||
}
|
||||
|
||||
await resolveHostnames();
|
||||
|
||||
/**
|
||||
* Get the client IP address from the request headers.
|
||||
* @param {import('express').Request} req Express request object
|
||||
@@ -45,6 +49,65 @@ function getForwardedIp(req) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the IP addresses in the whitelist.
|
||||
* Hostnames are resolved to IP addresses.
|
||||
*/
|
||||
async function resolveHostnames() {
|
||||
for (let i = 0; i < whitelist.length; i++) {
|
||||
try {
|
||||
const entry = whitelist[i];
|
||||
|
||||
// Skip if entry appears to be an IP address, CIDR notation, or IP wildcard
|
||||
if (isIpFormat(entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isValidHostname(entry)) {
|
||||
const result = await dns.promises.lookup(entry);
|
||||
|
||||
if (result.address) {
|
||||
console.info('Resolved whitelist hostname', entry, 'to IP address', result.address);
|
||||
whitelist[i] = result.address;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Ignore errors when resolving hostnames
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a middleware function that checks if the client IP is in the whitelist.
|
||||
* @returns {import('express').RequestHandler} The middleware function
|
||||
|
Reference in New Issue
Block a user