Node.js Güvenlik: Helmet ve CORS Yapılandırması

Node.js Güvenlik: Helmet ve CORS Yapılandırması
Web uygulaması güvenliği, geliştirme sürecinin her aşamasında dikkate alınması gereken kritik bir konudur. Node.js ve Express uygulamalarında Helmet ve CORS middleware'leri, en yaygın güvenlik tehditlerini engellemek için temel savunma katmanları oluşturur. Bu rehberde HTTP güvenlik başlıklarını, CORS politikalarını ve production-ready güvenlik yapılandırmalarını detaylı olarak inceleyeceğiz.
1. HTTP Güvenlik Başlıkları ve Tehditler
Modern web uygulamaları çeşitli güvenlik tehditleriyle karşı karşıyadır:
- XSS (Cross-Site Scripting): Kötü amaçlı JavaScript enjeksiyonu
- Clickjacking: Sayfa üzerinde görünmez iframe ile tıklama çalma
- MIME Sniffing: Tarayıcının dosya türünü yanlış yorumlaması
- Man-in-the-Middle: HTTPS olmadan veri dinleme
- CSRF: Kullanıcının haberi olmadan istek gönderilmesi
2. Helmet Kurulum ve Yapılandırma
Helmet, Express uygulamalarına güvenlik başlıkları ekleyen bir middleware koleksiyonudur. Tek satır ile 15'ten fazla güvenlik başlığı ayarlar.
# Kurulum
npm install helmet
const express = require('express');
const helmet = require('helmet');
const app = express();
// Varsayılan yapılandırma — tüm başlıkları etkinleştirir
app.use(helmet());
// Veya özelleştirilmiş yapılandırma
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.example.com"],
styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
imgSrc: ["'self'", "data:", "https:"],
fontSrc: ["'self'", "https://fonts.gstatic.com"],
connectSrc: ["'self'", "https://api.example.com"],
frameSrc: ["'none'"],
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
},
},
crossOriginEmbedderPolicy: true,
crossOriginOpenerPolicy: { policy: "same-origin" },
crossOriginResourcePolicy: { policy: "same-origin" },
hsts: { maxAge: 31536000, includeSubDomains: true, preload: true },
referrerPolicy: { policy: "strict-origin-when-cross-origin" },
}));
Helmet Başlıkları Detaylı
| Başlık | Koruduğu Tehdit | Varsayılan |
|---|---|---|
| Content-Security-Policy | XSS, veri enjeksiyonu | Aktif |
| X-Content-Type-Options | MIME sniffing | nosniff |
| X-Frame-Options | Clickjacking | SAMEORIGIN |
| Strict-Transport-Security | HTTP downgrade | Aktif |
| X-XSS-Protection | Eski tarayıcılarda XSS | 0 |
| Referrer-Policy | Bilgi sızıntısı | no-referrer |
| X-DNS-Prefetch-Control | DNS sızıntısı | off |
3. Content Security Policy (CSP) Detaylı
CSP, XSS saldırılarına karşı en güçlü savunma mekanizmalarından biridir.
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
// JavaScript kaynakları
scriptSrc: [
"'self'",
"'nonce-randomValue'", // Nonce tabanlı
"https://cdn.example.com",
],
// CSS kaynakları
styleSrc: [
"'self'",
"'unsafe-inline'", // Inline CSS'e izin (dikkatli kullanın)
"https://fonts.googleapis.com",
],
// Resim kaynakları
imgSrc: ["'self'", "data:", "https:", "blob:"],
// API bağlantıları
connectSrc: [
"'self'",
"https://api.example.com",
"wss://ws.example.com", // WebSocket
],
// Font kaynakları
fontSrc: ["'self'", "https://fonts.gstatic.com"],
// İframe kaynakları
frameSrc: ["https://www.youtube.com"],
// Form action hedefleri
formAction: ["'self'"],
// Base URI
baseUri: ["'self'"],
// Object/embed engelleme
objectSrc: ["'none'"],
},
// CSP ihlallerini raporla
reportOnly: false,
}));
// Nonce tabanlı CSP (her istek için benzersiz)
app.use((req, res, next) => {
const nonce = crypto.randomBytes(16).toString('base64');
res.locals.cspNonce = nonce;
next();
});
app.use(helmet.contentSecurityPolicy({
directives: {
scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.cspNonce}'`],
},
}));
reportOnly: true modunda çalıştırın. Bu sayede mevcut işlevselliği bozmadan hangi kaynakların engelleneceğini görebilirsiniz.
4. CORS Yapılandırması
CORS (Cross-Origin Resource Sharing), farklı domain'lerden gelen istekleri kontrol etmenizi sağlar.
# Kurulum
npm install cors
const cors = require('cors');
// Basit yapılandırma — tek origin
app.use(cors({
origin: 'https://www.example.com',
}));
// Çoklu origin desteği
const allowedOrigins = [
'https://www.example.com',
'https://admin.example.com',
'https://app.example.com',
];
app.use(cors({
origin: function(origin, callback) {
// origin undefined ise (Postman, curl gibi araçlar)
if (!origin) return callback(null, true);
if (allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('CORS politikası tarafından engellendi'));
}
},
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-Request-ID'],
exposedHeaders: ['X-Total-Count', 'X-Request-ID'],
credentials: true,
maxAge: 86400, // Preflight cache süresi (24 saat)
}));
Route-Specific CORS
// Sadece belirli route'lara CORS uygulama
const publicCors = cors({ origin: '*', methods: ['GET'] });
const privateCors = cors({
origin: allowedOrigins,
credentials: true,
});
// Public API — herkese açık
app.get('/api/public/data', publicCors, (req, res) => {
res.json({ data: 'public' });
});
// Private API — sadece izin verilen origin'ler
app.post('/api/private/data', privateCors, (req, res) => {
res.json({ data: 'private' });
});
5. Rate Limiting
# Kurulum
npm install express-rate-limit
const rateLimit = require('express-rate-limit');
// Genel rate limit
const generalLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 dakika
max: 100, // pencere başına 100 istek
standardHeaders: true,
legacyHeaders: false,
message: { error: 'Çok fazla istek. Lütfen daha sonra tekrar deneyin.' },
});
app.use('/api/', generalLimiter);
// Auth endpoint'leri için daha sıkı limit
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
message: { error: 'Çok fazla giriş denemesi.' },
});
app.use('/api/auth/', authLimiter);
6. Ek Güvenlik Middleware'leri
// Input sanitization
const mongoSanitize = require('express-mongo-sanitize');
app.use(mongoSanitize()); // NoSQL injection engelleme
// XSS temizleme
const xss = require('xss-clean');
app.use(xss());
// HPP (HTTP Parameter Pollution) koruması
const hpp = require('hpp');
app.use(hpp());
// Body boyut sınırlama
app.use(express.json({ limit: '10kb' }));
app.use(express.urlencoded({ extended: true, limit: '10kb' }));
7. Production Güvenlik Checklist
// Tüm güvenlik middleware'lerini birleştiren tam yapılandırma
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const app = express();
// 1. Helmet — güvenlik başlıkları
app.use(helmet());
// 2. CORS — cross-origin kontrol
app.use(cors({
origin: process.env.ALLOWED_ORIGINS?.split(',') || 'https://www.example.com',
credentials: true,
}));
// 3. Rate limiting
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));
// 4. Body parser sınırları
app.use(express.json({ limit: '10kb' }));
// 5. Trust proxy (reverse proxy arkasında)
app.set('trust proxy', 1);
// 6. X-Powered-By başlığını kaldır (helmet zaten yapar)
app.disable('x-powered-by');
// 7. Hata detaylarını gizle
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
res.status(statusCode).json({
error: process.env.NODE_ENV === 'production'
? 'Sunucu hatası'
: err.message,
});
});
cors({ origin: '*' }) ile credentials: true aynı anda kullanılamaz. Credentials kullanıyorsanız origin'i açıkça belirtmelisiniz.
Sonuç
Node.js uygulamalarında güvenlik, birden fazla katmanda uygulanmalıdır. Helmet ile HTTP güvenlik başlıklarını ayarlamak, CORS ile cross-origin erişimi kontrol etmek ve rate limiting ile kötüye kullanımı engellemek temel adımlardır. CSP politikası XSS saldırılarına karşı güçlü bir savunma sunar. Bu middleware'leri projenizin başlangıcında yapılandırmak, güvenlik açıklarını erken aşamada önlemenizi sağlar. Güvenlik sürekli bir süreçtir; bağımlılıklarınızı güncel tutun ve düzenli güvenlik denetimleri yapın.