ai-chatbot/lib/security/request-monitor.ts
Your Name a9236cdc3b
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
fix: 修复正常网页访问被误判为可疑请求的问题
- 排除正常的应用路径(/api/admin/, /api/, /chat/, /gallery/, /settings/等)
- 避免正常的网页访问被标记为可疑请求
- 只对真正可疑的路径(如/.env, /wp-admin等)进行标记
2025-12-29 16:28:17 +08:00

141 lines
3.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 请求监控和安全日志
* 用于记录可疑请求和异常行为
*/
interface SuspiciousRequest {
ip: string | null;
pathname: string;
method: string;
userAgent: string | null;
timestamp: Date;
reason: string;
}
// 可疑请求关键词
const SUSPICIOUS_PATTERNS = [
/wget|curl|nc |netcat|mkfifo|bash -i|sh -i/i,
/\.update|\.sh|\.py|\.pl|\.rb/i,
/exec|eval|system|shell|command/i,
/193\.142\.147\.209|94\.154\.35\.154/i, // 已知攻击者IP
];
// 可疑路径
const SUSPICIOUS_PATHS = [
"/.env",
"/.git/config",
"/admin",
"/wp-admin",
"/phpmyadmin",
"/.update",
"/tmp/",
];
/**
* 检查请求是否可疑
*/
export function isSuspiciousRequest(request: Request): {
suspicious: boolean;
reason?: string;
} {
const url = new URL(request.url);
const pathname = url.pathname;
const method = request.method;
// 排除正常的应用路径(避免误报)
const allowedPaths = [
"/api/admin/", // 管理后台API(正常功能)
"/api/", // 所有API路径(正常功能)
"/chat/", // 聊天页面
"/gallery/", // 相册页面
"/settings/", // 设置页面
"/login", // 登录页面
"/register", // 注册页面
];
// 如果是正常的应用路径,不标记为可疑
const isAllowedPath = allowedPaths.some(allowed => pathname.startsWith(allowed));
if (isAllowedPath) {
return { suspicious: false };
}
// 检查可疑路径
for (const pattern of SUSPICIOUS_PATHS) {
if (pathname.includes(pattern)) {
return {
suspicious: true,
reason: `Suspicious path: ${pathname}`,
};
}
}
// 检查请求体中的可疑内容(仅对POST请求)
if (method === "POST") {
// 注意:这里不能直接读取body,因为body只能读取一次
// 实际检查应该在API路由中进行
}
// 检查User-Agent
const userAgent = request.headers.get("user-agent") || "";
for (const pattern of SUSPICIOUS_PATTERNS) {
if (pattern.test(userAgent)) {
return {
suspicious: true,
reason: `Suspicious User-Agent: ${userAgent.substring(0, 100)}`,
};
}
}
return { suspicious: false };
}
/**
* 记录可疑请求
*/
export function logSuspiciousRequest(
request: Request,
reason: string
): void {
const clientIP = request.headers.get("x-forwarded-for")?.split(",")[0] ||
request.headers.get("x-real-ip") ||
"unknown";
const url = new URL(request.url);
const logEntry: SuspiciousRequest = {
ip: clientIP,
pathname: url.pathname,
method: request.method,
userAgent: request.headers.get("user-agent"),
timestamp: new Date(),
reason,
};
console.warn("[Security Alert] Suspicious request detected:", logEntry);
// 在生产环境中,这里可以发送到监控系统或日志服务
// 例如:发送到Sentry、LogRocket、或自定义日志服务
}
/**
* 验证请求体是否包含可疑内容
*/
export async function validateRequestBody(
body: string
): Promise<{ valid: boolean; reason?: string }> {
// 检查是否包含命令执行相关的关键词
for (const pattern of SUSPICIOUS_PATTERNS) {
if (pattern.test(body)) {
return {
valid: false,
reason: `Suspicious content detected in request body: ${pattern}`,
};
}
}
return { valid: true };
}