Files
biiproject-kit-v1/app/Http/Middleware/IpAccessControl.php
T

100 lines
3.9 KiB
PHP

<?php
namespace App\Http\Middleware;
use App\Services\Notification\TelegramService;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\Response;
class IpAccessControl
{
/**
* Handle an incoming request.
*
* @param Closure(Request): (Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$ip = $request->ip();
// Batch get common settings to reduce function overhead
$settings = [
'blacklist' => get_setting('ip_blacklist', ''),
'whitelist_admin' => get_setting('ip_whitelist_admin', ''),
'auto_block' => get_setting('auto_block_ip', false),
'single_session' => get_setting('session_single_session', false),
'hsts' => get_setting('hsts_enabled', false),
];
// 1. GLOBAL BLACKLIST
$blacklistArr = array_filter(array_map('trim', explode(',', $settings['blacklist'])));
if (in_array($ip, $blacklistArr)) {
abort(403, 'Your IP address has been blocked.');
}
// 2. ADMIN WHITELIST (Protects specific routes)
// Check if current route is an admin/restricted route
if ($request->is('system-config*') || $request->is('users*') || $request->is('roles*') || $request->is('permissions*') || $request->is('backups*') || $request->is('admin/*')) {
$whitelistArr = array_filter(array_map('trim', explode(',', $settings['whitelist_admin'])));
if (! empty($whitelistArr) && ! in_array($ip, $whitelistArr)) {
abort(403, 'Access denied: Admin IP Whitelist restricted.');
}
}
// 3. RATE LIMITING & AUTO BLOCK
if ($settings['auto_block']) {
$cacheKey = "ip_block:{$ip}";
if (Cache::has($cacheKey)) {
abort(429, 'Your IP has been temporarily blocked due to excessive requests.');
}
$threshold = get_setting('threshold_auto_block', 100);
$hitKey = "ip_hits:{$ip}";
Cache::add($hitKey, 0, now()->addMinute());
$hits = Cache::increment($hitKey);
if ($hits > $threshold) {
Cache::put($cacheKey, true, now()->addHours(24));
// 🚨 Send Security Alert to Telegram
try {
$telegram = app(TelegramService::class);
$msg = "<b>[FIREWALL BLOCK]</b>\n\n";
$msg .= "IP Address: <code>{$ip}</code>\n";
$msg .= "Reason: <b>Excessive Requests</b> ({$hits} hits)\n";
$msg .= "Action: <b>Auto-Blocked (24h)</b>\n\n";
$msg .= "Check configuration: <a href='".url('/system-config')."'>Admin Panel</a>";
$telegram->sendMessage($msg);
} catch (\Exception $e) {
\Log::error('Firewall Telegram Alert Failed: '.$e->getMessage());
}
abort(429, 'Excessive requests detected. Your IP has been blocked for 24 hours.');
}
}
// 4. SINGLE SESSION ENFORCEMENT
// Skip check if we are currently impersonating to prevent logout
if ($request->user() && $settings['single_session'] && ! session()->has('impersonator_id')) {
if ($request->user()->last_session_id !== session()->getId()) {
Auth::logout();
return redirect()->route('login')->with('error', 'You have been logged out because another device logged into your account.');
}
}
$response = $next($request);
// 5. HSTS (Transport Security)
if ($request->isSecure() && $settings['hsts']) {
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
}
return $response;
}
}