webrium/xzeroprotect

GitHub: webrium/xzeroprotect

一款基于纯文件存储、零外部依赖的轻量级 PHP 8 防火墙,提供速率限制、恶意请求拦截和自动 IP 封禁功能。

Stars: 2 | Forks: 0


``` ██╗ ██╗███████╗███████╗██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ████████╗███████╗ ██████╗████████╗ ╚██╗██╔╝╚══███╔╝██╔════╝██╔══██╗██╔═══██╗██╔══██╗██╔══██╗██╔═══██╗╚══██╔══╝██╔════╝██╔════╝╚══██╔══╝ ╚███╔╝ ███╔╝ █████╗ ██████╔╝██║ ██║██████╔╝██████╔╝██║ ██║ ██║ █████╗ ██║ ██║ ██╔██╗ ███╔╝ ██╔══╝ ██╔══██╗██║ ██║██╔═══╝ ██╔══██╗██║ ██║ ██║ ██╔══╝ ██║ ██║ ██╔╝ ██╗███████╗███████╗██║ ██║╚██████╔╝██║ ██║ ██║╚██████╔╝ ██║ ███████╗╚██████╗ ██║ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ``` **一款面向现代 Web 的轻量级、基于文件的 PHP 防火墙。** 无需数据库。无需外部服务。绝不妥协。
[![PHP](https://img.shields.io/badge/PHP-%3E%3D%208.0-8892BF?style=flat-square&logo=php&logoColor=white)](https://php.net) [![Composer](https://img.shields.io/badge/Composer-webrium%2Fxzeroprotect-885630?style=flat-square&logo=composer&logoColor=white)](https://packagist.org/packages/webrium/xzeroprotect) [![License](https://img.shields.io/badge/License-MIT-22c55e?style=flat-square)](LICENSE) [![Zero Dependencies](https://img.shields.io/badge/Dependencies-Zero-f59e0b?style=flat-square)]()
## 为什么选择 xZeroProtect? 每天,都有机器人爬取你的应用程序,试图寻找暴露的 `.env` 文件、WordPress 管理后台、SQL 注入向量以及已知的 CVE 漏洞——即使你根本没有运行 WordPress。xZeroProtect 在 PHP 层拦截这些请求,它没有任何外部依赖,不需要数据库连接,并提供了简洁的 API,让你能在几分钟内完成配置调整。 - **基于文件** —— 所有数据均存储在磁盘上;不需要 MySQL、Redis 或 memcached - **零依赖** —— 纯 PHP 8.0+ 实现,无任何其他依赖 - **可组合** —— 每个检测模块都可以独立启用、禁用或扩展 - **学习模式** —— 仅记录威胁而不进行拦截,非常适合在正式上线前进行调整 - **感知 Apache** —— 可选将永久封禁的 IP 写入 `.htaccess`,以便 Apache 在 PHP 启动之前就拒绝这些连接 ## 安装 ``` composer require webrium/xzeroprotect ``` ## 快速开始 将这两行代码添加到你的 `index.php` 或引导文件的最顶部: ``` run(); ``` 就是这样。默认规则会立即生效。 ## 配置 每个选项都有合理的默认值。只需覆盖你需要的配置: ``` $firewall = XZeroProtect::init([ // 'production' → block & log | 'learning' → log only | 'off' → disabled 'mode' => 'production', // Where ban files, rate data, and logs are stored 'storage_path' => __DIR__ . '/storage/firewall', // --- Rate limiting --- 'rate_limit' => [ 'enabled' => true, 'max_requests' => 60, // requests per window 'per_seconds' => 60, // window size in seconds ], // --- Automatic banning --- 'auto_ban' => [ 'enabled' => true, 'violations_threshold' => 10, // violations before a ban is issued 'ban_duration' => 86400, // ban length in seconds (24 h) 'permanent_after_bans' => 3, // escalate to permanent after N bans ], // --- Apache integration --- 'apache_blocking' => false, 'htaccess_path' => __DIR__ . '/.htaccess', // --- Reverse proxies / CDNs (e.g. Cloudflare, Nginx, load balancers) --- // Leave empty to always use REMOTE_ADDR (safest if the server is // reachable directly). Add proxy IPs/CIDRs to read the real client IP // from CF-Connecting-IP / True-Client-IP / X-Real-IP / X-Forwarded-For // when the request comes from one of these proxies. Use ['*'] to trust // these headers regardless of REMOTE_ADDR (only if the server is NOT // directly reachable). 'trusted_proxies' => [], // --- Always-allow list --- 'whitelist' => [ 'ips' => ['127.0.0.1', '10.0.0.0/8'], 'paths' => ['/health', '/ping'], ], // --- Response sent to blocked clients --- 'block_response' => [ 'code' => 403, 'message' => 'Access Denied', ], // --- Toggle individual detection modules --- 'checks' => [ 'crawler_check' => true, // exempt verified crawlers from all checks 'rate_limit' => true, 'blocked_path' => true, 'user_agent' => true, 'payload' => true, 'custom_rules' => true, ], // --- Log settings --- 'log' => [ 'enabled' => true, 'max_file_size' => 10, // MB — auto-rotated when exceeded 'keep_days' => 30, ], ]); $firewall->run(); ``` ## 检测模块 ### 路径检测 拦截针对敏感路径或不存在路径的请求。由于现代基于路由的 PHP 应用在 URL 中不包含 `.php` 文件,你可以添加该模式以立即拒绝大量 `index.php?id=` 扫描器探针。 ``` // Add individual patterns $firewall->patterns->addPath('.php'); $firewall->patterns->addPath('/control-panel'); // Add many at once $firewall->patterns->addPaths(['.asp', '.jsp', '/backup', '/staging']); // Remove a default pattern you want to allow $firewall->patterns->removePath('xmlrpc'); ```
查看所有默认拦截的路径 | 类别 | 匹配模式 | |----------|----------| | CMS 面板 | `wp-admin`, `wp-login`, `wp-config`, `xmlrpc`, `administrator`, `typo3` | | 配置文件暴露 | `.env`, `.git`, `.svn`, `.htaccess`, `.htpasswd`, `web.config` | | 数据库工具 | `phpmyadmin`, `pma`, `adminer`, `dbadmin` | | 危险文件 | `.sql`, `.bak`, `.backup`, `.old`, `dump.sql` | | 路径遍历 | `../`, `..%2f`, `%2e%2e` | | Web Shell | `shell.php`, `c99.php`, `r57.php`, `webshell` | | 脚本扩展名 | `.asp`, `.aspx`, `.jsp`, `.cfm`, `.cgi` | | 信息泄露 | `phpinfo`, `server-status`, `server-info` | | 安装残留 | `setup.php`, `install.php`, `readme.html` |
### User-Agent 检测 识别并拦截已知的扫描器、暴力破解和漏洞利用工具特征。默认情况下,空的 User-Agent 字符串会被视为可疑请求。 ``` $firewall->patterns->addAgent('custom-bad-bot'); $firewall->patterns->removeAgent('curl'); // allow curl if your API clients use it ```
查看默认拦截的 Agent `sqlmap` · `nikto` · `nessus` · `acunetix` · `netsparker` · `masscan` · `nmap` · `zgrab` · `dirbuster` · `gobuster` · `feroxbuster` · `wfuzz` · `ffuf` · `hydra` · `metasploit` · `semrushbot` · `ahrefsbot` · `libwww-perl` · 以及更多
### Payload 检测 使用编译后的正则表达式扫描 GET 参数、POST 主体、原始输入和 Cookie 中的攻击特征。 ``` // Add a custom pattern $firewall->patterns->addPayload('/CUSTOM_EXPLOIT/i', 'my_label'); // Remove a built-in pattern $firewall->patterns->removePayload('sqli_union'); ```
查看默认的 payload 规则 | 标签 | 检测内容 | |-------|---------| | `sqli_union` | `UNION [ALL] SELECT` | | `sqli_select` | `SELECT ... FROM` | | `sqli_drop` | `DROP TABLE/DATABASE` | | `sqli_sleep` | `SLEEP(n)` 基于时间的盲注 | | `sqli_benchmark` | `BENCHMARK(...)` | | `sqli_comment` | `--`, `#`, `/* */` 注释符注入 | | `xss_script` | ` ### 频率限制 基于 IP 在磁盘上存储的滑动窗口计数器。无需 Redis。 ``` $firewall = XZeroProtect::init([ 'rate_limit' => [ 'max_requests' => 30, 'per_seconds' => 10, ], ]); ``` ## 爬虫检测 受信任的 Web 爬虫(Googlebot、Bingbot 等)会被识别并豁免所有防火墙检查——包括频率限制和自动封禁。这可以防止合法的机器人被意外拦截。 对于 Googlebot 和 Bingbot 等爬虫,在授予信任之前,会通过**双重 DNS 验证**确认其身份: 1. 通过反向 DNS 将访问者 IP 解析为主机名 2. 确认主机名以预期的后缀结尾(例如 `.googlebot.com`) 3. 将该主机名重新解析回 IP 4. 确认重新解析的 IP 与原始访问者 IP 相匹配 这是 Google 和 Bing 在其官方文档中推荐的验证方法。任何人都可以伪造 User-Agent——但 DNS 无法伪造。 社交网络爬虫(Twitterbot、LinkedInBot、Slackbot 等)仅通过 User-Agent 进行信任,因为它们没有发布可验证的 IP 范围或 rDNS 后缀。 ``` // Add a custom trusted crawler $firewall->crawlers->addCrawler( name: 'MyCrawler', uaContains: 'mycrawlerbot', verifyRdns: false ); // Remove a crawler from the trusted list $firewall->crawlers->removeCrawler('Googlebot'); // Disable crawler detection entirely $firewall->disableCheck('crawler_check'); ```
查看默认受信任的爬虫 | 爬虫 | UA 包含 | DNS 验证 | |---------|-------------|:------------:| | Googlebot | `googlebot` | ✅ `.googlebot.com` | | Google Other | `google` | ✅ `.google.com` | | Bingbot | `bingbot` | ✅ `.search.msn.com` | | Yahoo Slurp | `yahoo! slurp` | ✅ `.crawl.yahoo.net` | | DuckDuckBot | `duckduckbot` | — | | Yandex | `yandexbot` | ✅ `.yandex.com` | | Baidu | `baiduspider` | ✅ `.baidu.com` | | Applebot | `applebot` | ✅ `.applebot.apple.com` | | Facebook | `facebookexternalhit` | ✅ `.facebook.com` | | Twitterbot | `twitterbot` | — | | LinkedInBot | `linkedinbot` | — | | WhatsApp | `whatsapp` | — | | Telegram | `telegrambot` | — | | Slackbot | `slackbot` | — | | Discordbot | `discordbot` | — | | Uptimerobot | `uptimerobot` | — | | Pingdom | `pingdom` | — |
## IP 管理 ``` // Temporary ban (24 h default) $firewall->ip->ban('1.2.3.4'); $firewall->ip->ban('1.2.3.4', reason: 'manual review', duration: 3600); // Permanent ban $firewall->ip->banPermanent('1.2.3.4', reason: 'confirmed attacker'); // Remove a ban $firewall->ip->unban('1.2.3.4'); // Inspect $firewall->ip->isBanned('1.2.3.4'); // bool $firewall->ip->getBanInfo('1.2.3.4'); // array|null { ip, reason, banned_at, expires, bans_count } $firewall->ip->getAllBans(); // array of all active bans // Whitelist — supports exact IPs and CIDR notation (IPv4 & IPv6) $firewall->ip->whitelist('10.0.0.0/8'); $firewall->ip->whitelist('2001:db8::/32'); ``` ## 自定义规则 将你自己的逻辑注册为一等防火墙规则,并完全访问请求对象。 ``` use Webrium\XZeroProtect\RuleResult; // Block requests with a .php extension (for fully-routed apps) $firewall->rules->add('no-php-extension', function ($request) { if (str_ends_with($request->path(), '.php')) { return RuleResult::block('PHP extension not valid on this server'); } return RuleResult::pass(); }); // Log suspicious POST requests without logging a violation $firewall->rules->add('post-no-referer', function ($request) { if ($request->method === 'POST' && empty($request->referer)) { return RuleResult::log('POST without Referer header'); } return RuleResult::pass(); }, priority: 10); // lower = runs first // Manage rules at runtime $firewall->rules->disable('no-php-extension'); $firewall->rules->enable('no-php-extension'); $firewall->rules->remove('no-php-extension'); ``` **`RuleResult` 选项:** | 方法 | 效果 | |--------|--------| | `RuleResult::pass()` | 允许请求,继续检查 | | `RuleResult::block(reason: '...')` | 立即拦截并记录 | | `RuleResult::log(reason: '...')` | 仅记录不拦截 | ## Apache 集成 当启用 `apache_blocking` 时,永久封禁的 IP 将被写入 `.htaccess`。Apache 会在 PHP 启动之前丢弃这些连接——对于已知的恶意行为者,PHP 的开销为零。 ``` $firewall = XZeroProtect::init([ 'apache_blocking' => true, 'htaccess_path' => __DIR__ . '/.htaccess', ]); // Sync all current permanent bans to .htaccess $firewall->apache->sync(array_keys($firewall->ip->getAllBans())); // Block/unblock a single IP in .htaccess $firewall->apache->block('5.6.7.8'); $firewall->apache->unblock('5.6.7.8'); ``` 生成的 `.htaccess` 拦截区块: ``` # xZeroProtect:start # 由 xZeroProtect 自动生成 — 请勿手动编辑此区块 Require all granted Require not ip 1.2.3.4 Require not ip 5.6.7.8 # xZeroProtect:end ``` ## 日志 ``` // Read the most recent attack entries (newest first) $logs = $firewall->logger->recent(limit: 100); // Clean up rotated backup log files older than retention period $firewall->logger->cleanup(); ``` ### 在引导文件之外访问防火墙 由于 `init()` 将实例存储为单例,你可以从任何控制器、管理面板或 CLI 脚本中获取它,而无需将 `$firewall` 作为变量传递: ``` use Webrium\XZeroProtect\XZeroProtect; // In bootstrap / index.php XZeroProtect::init()->run(); // --- // In any other file (e.g. admin panel, dashboard controller) $firewall = XZeroProtect::getInstance(); $logs = $firewall->logger->recent(limit: 100); $bans = $firewall->ip->getAllBans(); $isBanned = $firewall->ip->isBanned('1.2.3.4'); ``` 如果在 `init()` 之前调用 `getInstance()`,它会抛出一个明确的 `RuntimeException`: ``` xZeroProtect has not been initialized. Call XZeroProtect::init() first. ``` 日志条目为纯文本,每行一条: ``` 2024-11-15 14:32:01 | ip=185.220.101.5 | type=sqli_union | uri=/search?q=1+UNION+SELECT | reason=Payload match: sqli_union | ua=sqlmap/1.7 ``` ## 禁用单项检查 ``` // At init time XZeroProtect::init([ 'checks' => [ 'user_agent' => false, // disable UA checking for this app ], ]); // Or at runtime $firewall->disableCheck('user_agent'); $firewall->enableCheck('user_agent'); ``` 可用的检查键名:`crawler_check` · `rate_limit` · `blocked_path` · `user_agent` · `payload` · `custom_rules` ## 学习模式 首先以学习模式部署。所有攻击都会被记录,但不会拦截任何请求。查看日志,调整你的规则,然后切换到生产模式。 ``` // During tuning XZeroProtect::init(['mode' => 'learning'])->run(); // Once satisfied XZeroProtect::init(['mode' => 'production'])->run(); ``` ## 访客追踪 在所有防火墙检查通过后,xZeroProtect 可以记录经过验证的真实访问——机器人、扫描器和可疑请求在运行此功能之前已被过滤掉。 追踪是**可选的**,且**默认禁用**。在调用 `run()` 之前,通过向 `enableTracking()` 传递一个闭包来启用它。该闭包接收一个 `VisitInfo` 对象;如何存储数据完全取决于你。 ``` use Webrium\XZeroProtect\XZeroProtect; use Webrium\XZeroProtect\VisitInfo; $firewall = XZeroProtect::init(); $firewall->enableTracking(function (VisitInfo $visit) { // Store in your database however you like $pdo->prepare(" INSERT INTO visits (ip, path, method, referer, user_agent, browser, browser_version, os, os_version, device_type, fingerprint, visited_at) VALUES (:ip, :path, :method, :referer, :user_agent, :browser, :browser_ver, :os, :os_ver, :device_type, :fingerprint, :visited_at) ")->execute([ ':ip' => $visit->ip, ':path' => $visit->path, ':method' => $visit->method, ':referer' => $visit->referer, ':user_agent' => $visit->userAgent, ':browser' => $visit->device->browser, ':browser_ver' => $visit->device->browserVersion, ':os' => $visit->device->os, ':os_ver' => $visit->device->osVersion, ':device_type' => $visit->device->type, ':fingerprint' => $visit->fingerprint, ':visited_at' => $visit->date(), ]); }); $firewall->run(); ``` ### VisitInfo 属性 | 属性 | 类型 | 描述 | |----------|------|-------------| | `$visit->ip` | `string` | 访客 IP 地址 | | `$visit->uri` | `string` | 包含查询字符串的完整 URI | | `$visit->path` | `string` | 不包含查询字符串的 URI 路径 | | `$visit->method` | `string` | HTTP 方法 (`GET`, `POST`, ...) | | `$visit->userAgent` | `string` | 原始 User-Agent 标头 | | `$visit->referer` | `string` | HTTP Referer 标头 | | `$visit->timestamp` | `int` | Unix 时间戳 | | `$visit->fingerprint` | `string` | SHA-256 唯一访客标识符(见下文) | | `$visit->device` | `DeviceInfo` | 解析后的浏览器、操作系统和设备类型 | | `$visit->date()` | `string` | 格式化的时间戳——默认为 `Y-m-d H:i:s` | | `$visit->toArray()` | `array` | 作为扁平数组的所有字段,可直接用于插入数据库 | ### DeviceInfo 属性 可通过 `$visit->device` 访问: | 属性 | 类型 | 示例 | |----------|------|---------| | `->browser` | `string` | `Chrome`, `Firefox`, `Safari`, `Edge`, `Opera` | | `->browserVersion` | `string` | `124.0.0.0` | | `->os` | `string` | `Windows`, `macOS`, `Android`, `iOS`, `Linux` | | `->osVersion` | `string` | `10/11`, `17.0`, `13` | | `->type` | `string` | `desktop`, `mobile`, `tablet` | | `->isDesktop` | `bool` | `true` / `false` | | `->isMobile` | `bool` | `true` / `false` | | `->isTablet` | `bool` | `true` / `false` | ### 唯一访客指纹 `$visit->fingerprint` 是基于访客 IP、User-Agent 和当前日期生成的 **SHA-256 哈希值**。这意味着: - 同一位访客在同一天总是会获得**相同的指纹**——这有助于将页面点击量去重为唯一的日访问量。 - 该指纹**会在第二天重置**——不会进行长期追踪。 - 原始 IP **绝不会存储在指纹中**——它是无法被反向破解的。 ``` // Count only unique visitors per day $firewall->enableTracking(function (VisitInfo $visit) use ($pdo) { $exists = $pdo->prepare("SELECT 1 FROM visits WHERE fingerprint = ? AND DATE(visited_at) = CURDATE()") ->execute([$visit->fingerprint]); if (!$exists->fetchColumn()) { // First visit of the day for this visitor $pdo->prepare("INSERT INTO visits ...")->execute($visit->toArray()); } }); ``` ### 在运行时管理追踪 ``` $firewall->disableTracking(); $firewall->isTrackingEnabled(); // bool ``` ## 架构 ``` xzeroprotect/ ├── src/ │ ├── XZeroProtect.php Main class & orchestrator │ ├── Request.php HTTP request context │ ├── Storage.php File-based persistence (bans, rate, violations, logs) │ ├── IPManager.php Ban/whitelist management with CIDR support │ ├── PatternDetector.php Path, User-Agent, and payload matching │ ├── RateLimiter.php Sliding-window rate limiter │ ├── RuleEngine.php Custom rule registration & execution │ ├── ApacheBlocker.php .htaccess read/write │ ├── CrawlerVerifier.php Trusted crawler detection with double-DNS │ ├── Logger.php Attack logging with rotation │ ├── VisitInfo.php Verified visit data object (tracking) │ └── DeviceInfo.php Browser, OS, and device type parser ├── config/ │ └── config.php Default configuration ├── rules/ │ ├── paths.php Default blocked path patterns │ ├── agents.php Default blocked User-Agent signatures │ ├── payloads.php Default attack payload patterns (PCRE) │ └── crawlers.php Trusted crawler definitions (UA + rDNS config) └── tests/ └── XZeroProtectTest.php PHPUnit test suite ``` ## 运行测试 ``` composer install composer test # 附带详细输出 ./vendor/bin/phpunit --testdox ``` ## 环境要求 - PHP **8.0** 或更高版本 - 对存储目录具有写入权限 ## 开源协议 基于 [MIT License](LICENSE) 发布。 由 [Webrium](https://github.com/webrium) 构建。
标签:AppImage, ffuf, IP封禁, OpenVAS, PHP, WAF, Web安全, Web应用防火墙, 蓝队分析, 限流