node와 typescript로 waf 웹 방화벽 개발 2편

server.ts
import express, { Request, Response, NextFunction } from express;
import http from http;
import { Server as SocketIOServer, Socket } from socket.io;
import {
checkForSQLInjection, checkForXSS, checkForCSRF, checkForPathTraversal,
preventSessionFixation, checkUserAgent, checkHTTPMethods, checkForHTTPResponseSplitting,
checkForDirectoryListing, preventClickjacking, checkForUnvalidatedRedirect,
preventHTTPRequestSmuggling, checkForCommandInjection, checkForLDAPInjection,
checkForOpenRedirect, checkForFileUpload, checkForBufferOverflow, enforceHTTPS,
preventSessionHijacking, preventXSSI, preventXXE, checkForHostHeaderInjection,
checkRateLimiter, checkIPBlacklist, checkIPWhitelist
} from ./middleware/firewallMiddleware;
import connection from ./models/database;
import { RowDataPacket } from mysql2;
import session from express-session;
import cookieParser from cookie-parser;
import multer from multer;
import dotenv from dotenv;
import path from path;
import http from http;
import { Server as SocketIOServer, Socket } from socket.io;
import {
checkForSQLInjection, checkForXSS, checkForCSRF, checkForPathTraversal,
preventSessionFixation, checkUserAgent, checkHTTPMethods, checkForHTTPResponseSplitting,
checkForDirectoryListing, preventClickjacking, checkForUnvalidatedRedirect,
preventHTTPRequestSmuggling, checkForCommandInjection, checkForLDAPInjection,
checkForOpenRedirect, checkForFileUpload, checkForBufferOverflow, enforceHTTPS,
preventSessionHijacking, preventXSSI, preventXXE, checkForHostHeaderInjection,
checkRateLimiter, checkIPBlacklist, checkIPWhitelist
} from ./middleware/firewallMiddleware;
import connection from ./models/database;
import { RowDataPacket } from mysql2;
import session from express-session;
import cookieParser from cookie-parser;
import multer from multer;
import dotenv from dotenv;
import path from path;
dotenv.config();
const app = express();
const server = http.createServer(app);
const io = new SocketIOServer(server);
// multer 설정: 파일 업로드 디렉터리
const upload = multer({ dest: uploads/ });
const app = express();
const server = http.createServer(app);
const io = new SocketIOServer(server);
// multer 설정: 파일 업로드 디렉터리
const upload = multer({ dest: uploads/ });
// trust proxy 설정
app.set(trust proxy, true);
// 미들웨어 설정
app.use(express.static(path.join(__dirname, public)));
app.use(express.json());
app.use(cookieParser());
app.use(session({
secret: waf-secret-key,
resave: false,
saveUninitialized: true,
cookie: { secure: false }
}));
// 응답 전송 여부 확인 미들웨어
app.use((req: Request, res: Response, next: NextFunction): void => {
if (res.headersSent) return next();
next();
});
// 방어용 미들웨어
app.use(checkRateLimiter);
app.use(checkIPBlacklist);
app.use(checkIPWhitelist);
app.use(checkForSQLInjection);
app.use(checkForXSS);
app.use(checkForCSRF);
app.use(checkForPathTraversal);
app.use(preventSessionFixation);
app.use(checkUserAgent);
app.use(checkHTTPMethods);
app.use(checkForHTTPResponseSplitting);
app.use(checkForDirectoryListing);
app.use(preventClickjacking);
app.use(checkForUnvalidatedRedirect);
app.use(preventHTTPRequestSmuggling);
app.use(checkForCommandInjection);
app.use(checkForLDAPInjection);
app.use(checkForOpenRedirect);
app.use(checkForFileUpload);
app.use(checkForBufferOverflow);
app.use(enforceHTTPS);
app.use(preventSessionHijacking);
app.use(preventXSSI);
app.use(preventXXE);
app.use(checkForHostHeaderInjection);
app.set(trust proxy, true);
// 미들웨어 설정
app.use(express.static(path.join(__dirname, public)));
app.use(express.json());
app.use(cookieParser());
app.use(session({
secret: waf-secret-key,
resave: false,
saveUninitialized: true,
cookie: { secure: false }
}));
// 응답 전송 여부 확인 미들웨어
app.use((req: Request, res: Response, next: NextFunction): void => {
if (res.headersSent) return next();
next();
});
// 방어용 미들웨어
app.use(checkRateLimiter);
app.use(checkIPBlacklist);
app.use(checkIPWhitelist);
app.use(checkForSQLInjection);
app.use(checkForXSS);
app.use(checkForCSRF);
app.use(checkForPathTraversal);
app.use(preventSessionFixation);
app.use(checkUserAgent);
app.use(checkHTTPMethods);
app.use(checkForHTTPResponseSplitting);
app.use(checkForDirectoryListing);
app.use(preventClickjacking);
app.use(checkForUnvalidatedRedirect);
app.use(preventHTTPRequestSmuggling);
app.use(checkForCommandInjection);
app.use(checkForLDAPInjection);
app.use(checkForOpenRedirect);
app.use(checkForFileUpload);
app.use(checkForBufferOverflow);
app.use(enforceHTTPS);
app.use(preventSessionHijacking);
app.use(preventXSSI);
app.use(preventXXE);
app.use(checkForHostHeaderInjection);
// API - 공격 로그 조회
app.get(/api/logs, (req: Request, res: Response) => {
connection.query(SELECT * FROM attack_logs ORDER BY timestamp DESC LIMIT 10, (err, results) => {
if (err) {
res.status(500).json({ error: 로그 조회 실패 });
} else {
res.json(results);
}
});
});
connection.query(SELECT * FROM attack_logs ORDER BY timestamp DESC LIMIT 10, (err, results) => {
if (err) {
res.status(500).json({ error: 로그 조회 실패 });
} else {
res.json(results);
}
});
});
// 대시보드 페이지
app.get(/dashboard, (req: Request, res: Response) => {
res.sendFile(path.join(__dirname, public, dashboard.html));
});
res.sendFile(path.join(__dirname, public, dashboard.html));
});
// 실시간 로그 전송
io.on(connection, (socket: Socket) => {
console.log(새로운 클라이언트가 연결되었습니다.);
let lastSentLogId: string | null = null;
connection.query(SELECT * FROM attack_logs ORDER BY timestamp DESC LIMIT 10, (err, results) => {
if (err) {
console.error(MySQL 쿼리 오류:, err);
return;
}
if (Array.isArray(results) && results.length > 0) {
const latestLog = results[0] as RowDataPacket;
if (!lastSentLogId || latestLog.id !== lastSentLogId) {
socket.emit(newLog, latestLog);
lastSentLogId = latestLog.id;
}
}
});
console.log(새로운 클라이언트가 연결되었습니다.);
let lastSentLogId: string | null = null;
connection.query(SELECT * FROM attack_logs ORDER BY timestamp DESC LIMIT 10, (err, results) => {
if (err) {
console.error(MySQL 쿼리 오류:, err);
return;
}
if (Array.isArray(results) && results.length > 0) {
const latestLog = results[0] as RowDataPacket;
if (!lastSentLogId || latestLog.id !== lastSentLogId) {
socket.emit(newLog, latestLog);
lastSentLogId = latestLog.id;
}
}
});
socket.on(logInserted, () => {
connection.query(SELECT * FROM attack_logs ORDER BY timestamp DESC LIMIT 1, (err, results) => {
if (err) {
console.error(로그 조회 오류:, err);
return;
}
if (Array.isArray(results) && results.length > 0) {
const latestLog = results[0] as RowDataPacket;
if (!lastSentLogId || latestLog.id !== lastSentLogId) {
socket.emit(newLog, latestLog);
lastSentLogId = latestLog.id;
}
}
});
});
});
connection.query(SELECT * FROM attack_logs ORDER BY timestamp DESC LIMIT 1, (err, results) => {
if (err) {
console.error(로그 조회 오류:, err);
return;
}
if (Array.isArray(results) && results.length > 0) {
const latestLog = results[0] as RowDataPacket;
if (!lastSentLogId || latestLog.id !== lastSentLogId) {
socket.emit(newLog, latestLog);
lastSentLogId = latestLog.id;
}
}
});
});
});
// 서버 시작
server.listen(3000, () => {
console.log(서버가 3000번 포트에서 실행 중입니다.);
});
console.log(서버가 3000번 포트에서 실행 중입니다.);
});