Download the PHP package petecoop/protec without Composer
On this page you can find all versions of the php package petecoop/protec. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download petecoop/protec
More information about petecoop/protec
Files in petecoop/protec
Package protec
Short Description Extensible suspicious activity detection and temporary IP blocks for Laravel and Livewire.
License MIT
Informations about the package protec
Introduction
petecoop/protec detects suspicious requests to your Laravel application and applies temporary or permanent IP blocks. It uses Laravel's rate limiter, stores blocks in an Eloquent model, and includes some optional Livewire protections.
Why
Once something is publicly accessible on the internet vulnerability scanners are inevitable. I've found that with Livewire the scanners seem to discover what components are accessible and attempt to send malicious payloads often resulting in a CorruptComponentPayloadException or CannotUpdateLockedPropertyException, it'd be very rare for a real user to trigger these errors and so this package allows you to start blocking IP's that trigger these.
Installation
To customize the defaults:
Usage
Detectors identify suspicious activity, such as scanner probes or invalid Livewire payloads. Each detector has a policy array that sets how many matches to allow and how long to block the client's IP. Configure them under detectors in config/protec.php.
Protec counts matches for each IP, detector, and reason. The shared options are:
attempts: the number of matches that triggers a block.within: the counting window.block_for: the block duration; usenullfor a permanent block.reject_with: an optional HTTP error status to return for each match before the block threshold.
Durations accept integer seconds or strings, such as 30s, 10m, 8h, 7d, 2w, or 1h 30m. This applies to policy durations, escalation, and retention. Values must resolve to whole seconds.
For example, these settings block after 10 matches within 60 seconds, for one hour:
The threshold request and subsequent blocked requests receive an empty 429. reject_with controls the response before the block threshold. Further requests do not extend an active block. Set a detector entry to false to disable it.
Blocks
Set block_for to null to permanently block the IP address given the matching rule. To immediately block on the first request set the attempts to 1.
You can also block an IP directly:
Each block has its own database row. An explicit block creates a new record, including when the IP already has an active block. Manual blocks have no detector; the reason is optional. Exemptions still apply when enforcing blocks; remove AuthenticatedRequests from exemptions to include signed-in users.
Unblock an IP:
Unblocking lifts all active blocks for the IP by setting unblocked_at, preserving their original expiry and history.
Allowed IPs
Allow trusted scanners or other clients using IP addresses or CIDR ranges:
Querying an IP
Repeat offenders
Add an escalation array inside a detector's config entry to escalate a repeating offender:
Counts are separate for each detector and IP, using block creation times within a rolling window, including the new block. Retained automatic blocks count even if escalation was disabled when they were created or they were manually unblocked. Set that detector's escalation to false to disable it. Requests during an active block and manual blocks do not add offences. Escalation never shortens the original block duration.
Blocking Scanners
ScannerProbe detects requests for common scanner targets, including WordPress paths, exposed configuration files, database tools, and framework debugging endpoints. It only counts matching 404 responses; successful routes and query strings do not count.
It is enabled by default and blocks for one hour after 10 matches within 60 seconds. Its patterns list accepts built-in sets and custom strings, with exclusions under except:
Add or remove entries in patterns to select the sets you need.
Patterns match decoded paths without a leading slash, case-insensitively, with * wildcards..
Livewire
Livewire protection works automatically on its update route.
Corrupt payloads
CorruptLivewirePayload detects invalid snapshot checksums, attempts to change locked properties, and calls to unavailable component methods.. Configure its entry under detectors using the shared policy settings:
The report option allows suppressing error reports to Nightwatch / Sentry etc.
Guest component restrictions
GuestLivewireComponents restricts which components guests may update. Livewire has strong protections but this is intended to add a layer of protection from accidentally exposing sensitive data, and to catch and block scanners trying to exploit. It is disabled by default. Enable its entry under detectors after listing the components guests need:
These options reject each disallowed request with 401, then block for 10 minutes after 20 matches within 10 minutes. Disallowed component requests are always rejected; omitting reject_with keeps the default 401. Set it to another HTTP error status to change the initial rejection.
components accepts component names, classes, or preset arrays. An empty guest list rejects all guest component updates when the detector is enabled.
Guest restrictions remain guest-only even if you remove AuthenticatedRequests from exemptions to apply scanner detection, tampering detection, and IP blocks to signed-in users.
Filament
Filament panels use their own middleware stack. Add ProtectRequests to each panel's existing middleware() list in its panel provider:
To enable guest component restrictions, set GuestLivewireComponents to enabled => true and use the Filament preset in that detector's components list:
The preset allows Filament's built-in login, registration, password-reset, and notification components. Add any custom guest components, including replacements for Filament's authentication pages, to the list.
Additional information
Events
The following events are dispatched which can be used for further logging if required. Prefix the Petecoop\Protec\Events\ namespace.
ActivityDetected— dispatched whenever suspicious activity increments an IP's attempt counter, including the match that triggers a block. Exempt requests and requests from an already-blocked IP do not trigger it.IpBlocked— dispatched when a new automatic block or manual block is created. Subsequent requests rejected by an existing block do not trigger it again.IpUnblocked— dispatched for each active block manually lifted throughProtec::unblock()orprotec:unblock. Natural expiration does not trigger this event.
Pruning IP Blocks
Records are retained for retention ('30d' by default) after expiry or manual unblocking, and at least the longest enabled detector escalation window from creation. Active blocks are never pruned.
Schedule within Laravel:
Customisation
This package is designed to be easy to customise. Implement the interfaces in Petecoop\Protec\Contracts to create your own detectors and exemptions and add them to the config. Extend the Petecoop\Models\IpBlock model and set the model option in the config to override it. Protec can be overriden / extended in Laravel's container.
Cache
The cache_store option defaults to 'default', which uses the application's default cache store. Set it to a store name from config/cache.php to use a different store:
If the selected store's driver is database, Protec queries the block table directly. With other drivers, a cache miss allows the IP without a database lookup. Blocking writes an entry until expiry (forever for permanent blocks); unblocking removes it. Cache updates happen after the database transaction commits. Laravel's rate-limiter store remains configured through cache.limiter.
Use a persistent cache shared by your application workers. Flushing, evicting, or changing the cache can stop enforcement of recorded blocks. Database history and Protec::ip() summaries remain available, but request checks do not repopulate missing entries from the database.
Refill the cache from active database blocks after clearing or changing the cache store:
Or call Protec::warmCache() in your application. This fills the selected store, processes unique IPs in batches, preserves their original expiry, and excludes expired or manually unblocked records. It does nothing when the selected store's driver is database.
Proxies
Client IPs come from Laravel's $request->ip() and are normalized for IPv4/IPv6. Configure Laravel's trusted proxies for your ingress so the client is identified correctly. Untrusted forwarded headers are ignored.
All versions of protec with dependencies
illuminate/cache Version ^12.0|^13.0
illuminate/console Version ^12.0|^13.0
illuminate/database Version ^12.0|^13.0
illuminate/http Version ^12.0|^13.0
illuminate/support Version ^12.0|^13.0