網站遭遇惡意刷新、掃描或 CC 攻擊時,若無現成 WAF 防護,可部署此 PHP 緊急腳本:記錄 IP 訪問頻率,超過閾值自動寫入 .htaccess 封鎖。屬權宜之計,長期仍需完善架構層面防禦。
$_SERVER['REMOTE_ADDR'] 獲取客戶端 IP.htaccess2 黑名單,命中直接 exit$allowtime 秒內 $allownum 次請求 → 記入臨時封鎖檔$allowRefresh 次 → 永久寫入 .htaccess2<?php
header('Content-type: text/html; charset=utf-8');
$ip = $_SERVER['REMOTE_ADDR'];
$logDir = './log/';
$htaccessFile = '.htaccess2';
$allowTime = 60; // 統計時間窗(秒)
$allowNum = 5; // 窗口內允許請求數
$allowRefresh = 120; // 觸發永久封鎖的臨時封鎖次數
// 初始化檔案
foreach ([$htaccessFile, $logDir.'ipdate.dat', $logDir.'forbidchk.dat'] as $f) {
if (!file_exists($f)) @file_put_contents($f, '');
}
if (!is_dir($logDir)) @mkdir($logDir, 0777);
// 檢查永久黑名單
$banList = @file($htaccessFile, FILE_IGNORE_NEW_LINES);
if (in_array($ip, $banList)) {
exit('警告:您的 IP 已被永久封鎖!');
}
$now = time();
// === 臨時封鎖檢查 ===
$forbidFile = $logDir . 'forbidchk.dat';
if (file_exists($forbidFile)) {
if ($now - filemtime($forbidFile) > 30) {
@unlink($forbidFile); // 過期清理
} else {
$arr = @file($forbidFile, FILE_IGNORE_NEW_LINES);
if ($arr[0] === $ip) {
if ($now - $arr[1] > 120) {
@unlink($forbidFile);
} elseif ($arr[2] > $allowRefresh) {
file_put_contents($htaccessFile, $ip . PHP_EOL, FILE_APPEND);
@unlink($forbidFile);
} else {
$arr[2]++; file_put_contents($forbidFile, implode(PHP_EOL, $arr));
}
}
}
}
// === 頻率統計與限制 ===
$ipFile = $logDir . 'ipdate.dat';
$records = @file($ipFile, FILE_IGNORE_NEW_LINES);
$newRecords = [];
$allow = true;
foreach ($records as $line) {
[$recIp, $recUri, $recTime, $recCount] = [
substr($line, 0, 32),
substr($line, 32, 32),
(int)substr($line, 64, 10),
(int)substr($line, 74)
];
if ($now - $recTime < $allowTime) {
if ($recIp === md5($ip)) {
$allow = false;
$uriHash = md5($_SERVER['REQUEST_URI']);
if ($recUri !== $uriHash) {
$newRecords[] = $recIp . $uriHash . $now . "\n";
} elseif ($recCount < $allowNum) {
$newRecords[] = $recIp . $recUri . $recTime . ($recCount + 1) . "\n";
} else {
// 觸發臨時封鎖
if (!file_exists($forbidFile)) {
file_put_contents($forbidFile, "$ip\n$now\n1\n");
}
file_put_contents($logDir . 'forbided_ip.log', "$ip--" . date('Y-m-d H:i:s') . "--{$_SERVER['REQUEST_URI']}\n", FILE_APPEND);
exit('警告:請勿頻繁刷新!');
}
} else {
$newRecords[] = $line . "\n";
}
}
// 過期記錄自動捨棄
}
if ($allow) {
$newRecords[] = md5($ip) . md5($_SERVER['REQUEST_URI']) . $now . "1\n";
}
file_put_contents($ipFile, implode('', $newRecords));
| 參數 | 預設值 | 調整建議 |
|---|---|---|
| $allowTime | 60 秒 | 靜態資源多則調大,API 介面調小 |
| $allowNum | 5 次 | 正常瀏覽約 10-30 次/分,視業務調整 |
| $allowRefresh | 120 次 | 誤傷風險與防禦強度的平衡點 |
flock 可能成為瓶頸,建議改用 Redis 原子計數器此腳本適用於「被攻擊當下、無現成防護、需快速上線」的緊急場景。長期請部署專業 WAF(如 ModSecurity)、CDN 防護(Cloudflare 等)並建立完整監控告警體系。