route-eyes
Version:
Express middleware to detect and optionally block suspicious or malicious route access attempts.
220 lines (206 loc) • 6.82 kB
JavaScript
const fs = require("fs");
const path = require("path");
const paths = [
"/admin.php",
"/admin/admin.php",
"/admin/function.php",
"/admin/index.php",
"/adminfuns.php",
"/akc.php",
"/al.php",
"/alfa.php",
"/as.php",
"/asasx.php",
"/assets/images/doc.php",
"/atomlib.php",
"/auth.php",
"/autoload_classmap.php",
"/autoload_classmap/function.php",
"/b.php",
"/blog/fw.php",
"/bugz.php",
"/byp.php",
"/cc.php",
"/chosen.php",
"/class.php",
"/classwithtostring.php",
"/composer.php",
"/css.php",
"/dropdown.php",
"/edit.php",
"/f35.php",
"/file.php",
"/file2.php",
"/filemanager.php",
"/files/index.php",
"/fix.php",
"/fm.php",
"/flower.php",
"/fox.php",
"/function/function.php",
"/g.php",
"/gecko.php",
"/gel4y.php",
"/gelay.php",
"/gg.php",
"/goat.php",
"/goods.php",
"/h.php",
"/images/admin.php",
"/images/class-config.php",
"/inc.php",
"/index.bak.php",
"/index/function.php",
"/info.php",
"/infos.php",
"/ioxi-o.php",
"/k.php",
"/m.php",
"/mar.php",
"/mini",
"/mini.php",
"/mm.php",
"/ms-edit.php",
"/ms-themes.php",
"/options-general.php",
"/options-reading.php",
"/options-writing.php",
"/ova.php",
"/pages.php",
"/php.php",
"/php8.php",
"/pinfo.php",
"/radio.php",
"/robots.php",
"/rt.php",
"/s.php",
"/setup.php",
"/simple.php",
"/sts.php",
"/system_log.php",
"/test1.php",
"/themes/zMousse/otuz1.php",
"/tinyfilemanager.php",
"/ty.php",
"/users.php",
"/w.php",
"/wp-aa.php",
"/wp-admin/",
"/wp-admin/admin.php",
"/wp-admin/classwithtostring.php",
"/wp-admin/css/colors/blue/index.php",
"/wp-admin/css/colors/ectoplasm/about.php",
"/wp-admin/css/colors/light/wp-login.php",
"/wp-admin/images/moon.php",
"/wp-admin/includes/colour.php",
"/wp-admin/includes/header.php",
"/wp-admin/includes/index.php",
"/wp-admin/install.php",
"/wp-admin/js/autoload_classmap.php",
"/wp-admin/js/index.php",
"/wp-admin/js/widgets/cloud.php",
"/wp-admin/js/widgets/index.php",
"/wp-admin/mah.php",
"/wp-admin/maint/about.php",
"/wp-admin/network/network.php",
"/wp-admin/wp-admins.php",
"/wp-admin/wp-login.php",
"/wp-admin/wp.php",
"/wp-api.php",
"/wp-comments.php",
"/wp-content/1.php",
"/wp-content/about.php",
"/wp-content/autoload_classmap.php",
"/wp-content/classwithtostring.php",
"/wp-content/click.php",
"/wp-content/index.php",
"/wp-content/languages/autoload_classmap.php",
"/wp-content/plugin.php",
"/wp-content/plugins/WordPressCore/include.php",
"/wp-content/plugins/autoload_classmap.php",
"/wp-content/plugins/ioxi/ioxi/dropdown.php",
"/wp-content/plugins/pwnd/as.php",
"/wp-content/plugins/revslider/includes/external/page/index.php",
"/wp-content/plugins/up/main.php",
"/wp-content/themes/admin.php",
"/wp-content/uploads/chosen.php",
"/wp-content/uploads/de_fb_uploads/b.php",
"/wp-content/uploads/json.php",
"/wp-content/wp.php",
"/wp-error.php",
"/wp-includes/ALFA_DATA/alfacgiapi/perl.alfa",
"/wp-includes/IXR/autoload_classmap.php",
"/wp-includes/IXR/chosen.php",
"/wp-includes/PHPMailer/file.php",
"/wp-includes/SimplePie/chosen.php",
"/wp-includes/about.php",
"/wp-includes/blocks/about.php",
"/wp-includes/blocks/calendar/index.php",
"/wp-includes/certificates/chosen.php",
"/wp-includes/css/autoload_classmap.php",
"/wp-includes/fonts/admin.php",
"/wp-includes/fonts/autoload_classmap.php",
"/wp-includes/fonts/index.php",
"/wp-includes/html-api/about.php",
"/wp-includes/js/tinymce/langs/about.php",
"/wp-includes/rest-api/index.php",
"/wp-includes/style-engine/autoload_classmap.php",
"/wp-includes/widgets/autoload_classmap.php",
"/wp-includes/wp-class.php",
"/wp-includes/wp_class_datlib.php",
"/wp-l0gin.php"
];
function routeEyes({ block = false, onDetect, log = true, banFile = "banned_ips.json" } = {}) {
const banFilePath = path.resolve(banFile);
// 벤 리스트 불러오기
let bannedIps = [];
if (fs.existsSync(banFilePath)) {
try {
bannedIps = JSON.parse(fs.readFileSync(banFilePath, "utf-8"));
} catch (err) {
console.error("[route-eyes] Failed to read ban file:", err);
bannedIps = [];
}
}
// IP 벤 저장 함수
function saveBanList() {
try {
fs.writeFileSync(banFilePath, JSON.stringify(bannedIps, null, 2));
} catch (err) {
console.error("[route-eyes] Failed to save ban file:", err);
}
}
return function (req, res, next) {
// 1. 이미 벤된 IP인지 확인
if (bannedIps.includes(req.ip)) {
if (log) {
console.warn(`[route-eyes] Blocked banned IP: ${req.ip}`);
}
return res.status(403).send("Forbidden");
}
// 2. 경로 매칭 확인
const matched = paths.some(p => {
if (typeof p === "string") return req.path === p;
if (p instanceof RegExp) return p.test(req.path);
return false;
});
if (matched) {
if (log) {
console.warn(`[route-eyes] Detected suspicious access: ${req.path} from IP ${req.ip}`);
}
if (typeof onDetect === "function") {
onDetect(req, res);
}
// 3. 벤 IP 목록에 추가
if (!bannedIps.includes(req.ip)) {
bannedIps.push(req.ip);
saveBanList();
}
if (block) {
return res.status(403).send("Forbidden");
}
}
next();
};
}
module.exports = routeEyes;