167 lines
6.2 KiB
JavaScript
167 lines
6.2 KiB
JavaScript
const rateLimit = require('express-rate-limit');
|
|
const helmet = require('helmet');
|
|
const cors = require('cors');
|
|
const express = require('express');
|
|
const Ddos = require('ddos');
|
|
const sslify = require('express-sslify');
|
|
const cookieParser = require('cookie-parser');
|
|
const slowDown = require('express-slow-down');
|
|
const { logger } = require('./logger');
|
|
const validator = require('validator');
|
|
|
|
// Feature Toggle Booleans
|
|
const enableDdosProtection = true;
|
|
const enableRateLimiting = true;
|
|
const enableHelmet = true;
|
|
const enableCORS = true;
|
|
const enableHttpsRedirect = false;
|
|
const enableCookieSecurity = true;
|
|
const enableSlowDown = true;
|
|
|
|
// Initialize DDoS protection with default configuration
|
|
let ddos;
|
|
if (enableDdosProtection) {
|
|
try {
|
|
ddos = new Ddos({ burst: 10, limit: 15 });
|
|
logger.info({ message: 'DDoS protection initialized with burst: 10, limit: 15' });
|
|
} catch (error) {
|
|
logger.error({ message: 'Failed to initialize DDoS protection', error });
|
|
}
|
|
}
|
|
|
|
// Function to apply security middlewares to the app
|
|
const setupSecurity = (app) => {
|
|
|
|
app.set('trust proxy', 'loopback');
|
|
|
|
// Configure rate limiting
|
|
let limiter;
|
|
if (enableRateLimiting) {
|
|
try {
|
|
limiter = rateLimit({
|
|
windowMs: 5 * 60 * 1000, // 15 minutes
|
|
max: 300, // Limit each IP to 100 requests per windowMs
|
|
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
|
|
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
|
|
});
|
|
logger.info({ message: 'Rate limiting configured with windowMs: 15 minutes, max: 100 requests per windowMs' });
|
|
} catch (error) {
|
|
logger.error({ message: 'Failed to configure rate limiting', error });
|
|
}
|
|
}
|
|
// Apply HTTPS redirect if enabled
|
|
if (enableHttpsRedirect) {
|
|
try {
|
|
app.use(sslify.HTTPS({ trustProtoHeader: true }));
|
|
logger.info({ message: 'HTTPS redirect middleware applied' });
|
|
} catch (error) {
|
|
logger.error({ message: 'Failed to apply HTTPS redirect middleware', error });
|
|
}
|
|
} else {
|
|
logger.warn({ message: 'HTTPS redirect is disabled for testing purposes' });
|
|
}
|
|
|
|
// Apply Helmet to secure HTTP headers
|
|
if (enableHelmet) {
|
|
try {
|
|
app.use(helmet());
|
|
app.use(helmet.contentSecurityPolicy({
|
|
directives: {
|
|
defaultSrc: ["'self'"],
|
|
scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'"],
|
|
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
imgSrc: ["'self'", "data:", "https:"],
|
|
connectSrc: ["'self'"],
|
|
fontSrc: ["'self'"],
|
|
objectSrc: ["'none'"],
|
|
upgradeInsecureRequests: []
|
|
}
|
|
}));
|
|
app.use(helmet.frameguard({ action: 'deny' }));
|
|
app.use(helmet.xssFilter());
|
|
app.use(helmet.hsts({ maxAge: 31536000, includeSubDomains: true, preload: true }));
|
|
logger.info({ message: 'Helmet middleware applied with custom settings' });
|
|
} catch (error) {
|
|
logger.error({ message: 'Failed to apply Helmet middleware', error });
|
|
}
|
|
} else {
|
|
logger.warn({ message: 'Helmet security is disabled for testing purposes' });
|
|
}
|
|
|
|
// Apply CORS if enabled
|
|
if (enableCORS) {
|
|
try {
|
|
app.use(cors({
|
|
origin: ['https://ourdomain.co.za'],
|
|
methods: ['GET', 'POST'],
|
|
allowedHeaders: ['Content-Type', 'Authorization']
|
|
}));
|
|
logger.info({ message: 'CORS configured with specific settings' });
|
|
} catch (error) {
|
|
logger.error({ message: 'Failed to apply CORS settings', error });
|
|
}
|
|
} else {
|
|
logger.warn({ message: 'CORS is disabled for testing purposes' });
|
|
}
|
|
|
|
// Apply Cookie security if enabled
|
|
if (enableCookieSecurity) {
|
|
try {
|
|
app.use(cookieParser());
|
|
app.use((req, res, next) => {
|
|
res.cookie('name', 'value', { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'Strict' });
|
|
next();
|
|
});
|
|
logger.info({ message: 'Cookie security applied' });
|
|
} catch (error) {
|
|
logger.error({ message: 'Failed to apply cookie security', error });
|
|
}
|
|
} else {
|
|
logger.warn({ message: 'Cookie security is disabled for testing purposes' });
|
|
}
|
|
|
|
// Apply rate limiting if enabled
|
|
if (enableRateLimiting) {
|
|
try {
|
|
app.use(limiter);
|
|
logger.info({ message: 'Rate limiting middleware applied to all routes' });
|
|
} catch (error) {
|
|
logger.error({ message: 'Failed to apply rate limiting middleware', error });
|
|
}
|
|
} else {
|
|
logger.warn({ message: 'Rate limiting is disabled for testing purposes' });
|
|
}
|
|
|
|
// Apply DDoS protection if enabled
|
|
if (enableDdosProtection) {
|
|
try {
|
|
app.use(ddos.express);
|
|
logger.info({ message: 'DDoS protection middleware applied' });
|
|
} catch (error) {
|
|
logger.error({ message: 'Failed to apply DDoS protection middleware', error });
|
|
}
|
|
} else {
|
|
logger.warn({ message: 'DDoS protection is disabled for testing purposes' });
|
|
}
|
|
|
|
// Apply slow down protection if enabled
|
|
if (enableSlowDown) {
|
|
try {
|
|
app.use(slowDown({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
delayAfter: 100, // Delay after 100 requests
|
|
delayMs: () => 500 // Apply a fixed 500ms delay after exceeding the threshold
|
|
}));
|
|
logger.info({ message: 'Slow down protection applied' });
|
|
} catch (error) {
|
|
logger.error({ message: 'Failed to apply slow down protection', error });
|
|
}
|
|
} else {
|
|
logger.warn({ message: 'Slow down protection is disabled for testing purposes' });
|
|
}
|
|
|
|
|
|
};
|
|
|
|
module.exports = { setupSecurity };
|