sy / src /middleware /hostWhitelist.js
吴松泽
main
c120a1c
import path from 'node:path';
import { color, getConfigValue, safeReadFileSync } from '../util.js';
import { serverDirectory } from '../server-directory.js';
import { isHostAllowed, hostValidationMiddleware } from 'host-validation-middleware';
const knownHosts = new Set();
const maxKnownHosts = 1000;
const hostWhitelistEnabled = !!getConfigValue('hostWhitelist.enabled', false);
const hostWhitelist = Object.freeze(getConfigValue('hostWhitelist.hosts', []));
const hostWhitelistScan = !!getConfigValue('hostWhitelist.scan', false, 'boolean');
const hostNotAllowedHtml = safeReadFileSync(path.join(serverDirectory, 'public/error/host-not-allowed.html'))?.toString() ?? '';
const validationMiddleware = hostValidationMiddleware({
allowedHosts: hostWhitelist,
generateErrorMessage: () => hostNotAllowedHtml,
errorResponseContentType: 'text/html',
});
/**
* Middleware to validate remote hosts.
* Useful to protect against DNS rebinding attacks.
* @param {import('express').Request} req Request
* @param {import('express').Response} res Response
* @param {import('express').NextFunction} next Next middleware
*/
export default function hostWhitelistMiddleware(req, res, next) {
const hostValue = req.headers.host;
if (hostWhitelistScan && !isHostAllowed(hostValue, hostWhitelist) && !knownHosts.has(hostValue) && knownHosts.size < maxKnownHosts) {
const isFirstWarning = knownHosts.size === 0;
console.warn(color.red('Request from untrusted host:'), hostValue);
console.warn(`If you trust this host, you can add it to ${color.yellow('hostWhitelist.hosts')} in config.yaml`);
if (!hostWhitelistEnabled && isFirstWarning) {
console.warn(`To protect against host spoofing, consider setting ${color.yellow('hostWhitelist.enabled')} to true`);
}
if (isFirstWarning) {
console.warn(`To disable this warning, set ${color.yellow('hostWhitelist.scan')} to false`);
}
knownHosts.add(hostValue);
}
if (!hostWhitelistEnabled) {
return next();
}
return validationMiddleware(req, res, next);
}