Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Route Blocker Laravel Package

skydiver/laravel-route-blocker

Block routes in Laravel with a simple, configurable middleware layer. Restrict access by IP, environment, or custom rules, and return clean 403 responses. Lightweight and easy to drop into any Laravel app.

View on GitHub
Deep Wiki
Context7

Getting Started

Pull the package in and publish its config — that config file is the entire control surface of this package, so read it before you write any code:

composer require skydiver/laravel-route-blocker
php artisan vendor:publish --tag=route-blocker   # or --provider="Skydiver\LaravelRouteBlocker\...ServiceProvider"

Then open config/route-blocker.php first. It ships as a set of lists — blocked/whitelisted IPs, route patterns, and HTTP verbs — plus a response definition (abort code, redirect, view, or JSON body). The service provider auto-registers a global middleware, so once the config has entries the package is already active on every request; you don't need to touch routes/*.php for the common case. On Laravel 11+ verify the provider is discovered (or registered in bootstrap/providers.php) and that the global middleware is appended in bootstrap/app.php if you've customised the middleware stack.

A good first use case: you're seeing a scraper hammer /login and /search from one IP, and you want it gone in two minutes without touching nginx or Cloudflare:

'blocked' => [
    'ips'   => ['203.0.113.42'],
    'routes'=> [],
    'verbs' => [],
],

Confirm it works from outside your machine (curl --resolve or a VPN), not from 127.0.0.1 — see the gotchas below for why.

Implementation Patterns

Deny-list the whole app. Populate blocked.ips for bad actors. This is the highest-value, lowest-effort use: it runs as a global middleware before your controllers, so abuse never reaches your app code, queue dispatches, or DB.

Allow-list a sensitive area. The more interesting pattern is scoping a whitelist to a route prefix — /admin/*, /horizon*, /telescope*, /api/internal/* reachable only from office/VPN IPs. This is exactly what this package is for, and it complements (doesn't replace) the auth layer: a stolen session cookie from a non-office IP still gets stopped.

Verb blocking as a maintenance lever. Blocking post, put, patch, delete app-wide is a cheap "read-only mode" while you run a migration, better than a full down page because browsing still works.

Layer it with dynamic logic. Keep the package for static, deploy-time rules and write a small custom middleware for anything DB- or cache-driven (abuse scores, temporary bans). Cache the DB lookup; a middleware that hits the database on every request is a footgun. Register your middleware before the blocker so temporary bans and config bans both apply.

Environment-drive the config. Wrap the lists in env() inside the config file so staging can be fully locked down while production is open:

'blocked' => [
    'ips' => array_filter(explode(',', env('BLOCKED_IPS', ''))),
],

Test it like any other middleware. Feature tests should set the client IP explicitly:

$this->withServerVariables(['REMOTE_ADDR' => '203.0.113.42'])
     ->get('/admin')
     ->assertForbidden();

If you're behind a proxy in the test, withHeaders(['X-Forwarded-For' => ...]) only works once TrustProxies accepts that header.

Choose the response deliberately. abort(403) for internal tooling, a rendered 403 view for customer-facing routes, and a JSON body for /api/* — returning an HTML error page to an API client is a common sloppy outcome.

Gotchas and Tips

  • Proxy IPs are the #1 failure mode. The package resolves the client IP via the request, which means behind a load balancer or Cloudflare you'll see the proxy's address. Without a correct TrustProxies configuration you will either block everyone or block no one, and it will look like the package is broken. Verify with a temporary Log::info($request->ip()) before trusting any rules.
  • 127.0.0.1 in the blocked list locks you out of local development. Gate the whole thing behind an enabled env flag (the config exposes one) and keep it false in .env.example/testing, true in production.
  • Config caching. Production edits do nothing until php artisan config:cache runs. Put the cache rebuild in your deploy script, and never call env() outside config files or it will silently return null under a cached config.
  • Route patterns match URI paths, not route names. admin/* won't match admin itself, and /admin vs admin matters. Test the exact patterns against real URLs rather than assuming glob semantics.
  • Assume exact-IP matching only. Don't expect CIDR (203.0.113.0/24) support; if you need ranges, handle it in your own middleware or at the edge. Same for IPv6 — write addresses in the form $request->ip() actually returns.
  • It's defense in depth, not a security boundary. An IP check is trivially bypassed by a proxy, so never let it be the only gate in front of authorization logic. Keep auth/can middleware exactly where it was.
  • Whitelist precedence is worth verifying once. Before you rely on "blocked post globally, but allow the webhook path", write a test that proves the whitelist wins — the behaviour is config-order dependent and easy to misremember during an incident.
  • Add your own logging. These packages tend to abort silently; wrap or subclass the middleware to emit a log line with IP, path, and rule matched. During an incident, "why is this customer getting a 403" is unanswerable otherwise.
  • Debugging checklist: config('route-blocker') in tinker to confirm what's actually loaded, php artisan route:list to confirm the URI shape, and a curl -i from the offending network to confirm it isn't nginx or a WAF doing the blocking instead.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator