m6web/firewall-bundle
Symfony bundle that adds a simple IP-based firewall to your app. Define whitelists of allowed addresses per path or host and return a custom response to blocked requests, keeping staging, admin, or private areas locked down with minimal configuration.
composer require m6web/firewall-bundle. If you are on an older Symfony and cannot migrate, pin explicitly to ^2 rather than floating.AppKernel::registerBundles() or config/bundles.php on Symfony 4+), then import its configuration under the bundle's root key. The README is the first place to look; the exact config schema is small and lives there. After upgrading to v3, diff your config against the README — do not assume key names survived the major bump./admin, staging environments, or a maintenance window by allow-listing office/VPN IPs.BlockIp / AllowIp middleware reading config/firewall.php gives you the same day-to-day capability with first-class Laravel support — and v3 being a Symfony-facing major release does not change that.127.0.0.1 in dev). Avoid one giant list; it becomes impossible to audit. This also makes a v3 config migration tractable, because you can diff rule by rule.access_control (or Laravel’s Gate/can middleware). The bundle is not an authentication or authorization system.config_dev/.env and strict rules in production. Local development should never be blocked by a production allow-list.403, a 404 (to avoid leaking that a path exists), or a redirect. Make this consistent across rules and test it. If v3 changed the default denial response, that is a silent behavior change for your users — assert it in a test.// app/Http/Middleware/Firewall.php
public function handle($request, Closure $next)
{
$ip = $request->ip();
foreach (config('firewall.rules', []) as $rule) {
if (! $this->matchesPath($request, $rule['paths'] ?? [])) {
continue;
}
if ($this->inList($ip, $rule['deny'] ?? [])) {
abort($rule['status'] ?? 403);
}
if (! empty($rule['allow']) && ! $this->inList($ip, $rule['allow'])) {
abort($rule['status'] ?? 403);
}
}
return $next($request);
}
REMOTE_ADDR (and X-Forwarded-For where relevant) and assert status codes for allowed and denied cases. Include at least one IPv6 case. Run this suite before and after any v3 upgrade; it is the cheapest regression net you have for a bundle with thin release notes.warning level. This is the fastest way to diagnose “why can’t I reach staging?” — and the fastest way to prove a post-upgrade rule is or isn’t matching.^2 and stay put.php artisan vendor:publish. Porting the concept is almost always cheaper than bridging the bundle, and a v3 major gives you no additional reason to bridge.REMOTE_ADDR will be your proxy, not the client. Configure trusted proxies correctly (Symfony TrustedProxies, Laravel TrustProxies middleware) before trusting any forwarded header. Never read X-Forwarded-For blindly — it is spoofable.IpUtils::checkIp) rather than in_array. If v3 rewrote matching, re-run your IPv6 tests specifically — that is exactly the code a refactor touches.bin/console cache:clear; in Laravel, php artisan config:clear). Stale cached config is a common “my rule isn’t applied” cause, and it is especially likely mid-upgrade when the schema changed underneath you.handle method plus a small CIDR helper is effectively the whole extension surface — keep it in one class and cover it with tests.debug:config or config('firewall')), confirm the client IP resolution path, then confirm listener/middleware ordering. After a major bump, add a fifth step: confirm your config keys still exist in the v3 schema. Most failures are one of those five.How can I help you explore Laravel packages today?