Skip to content

Releases: flowd/phirewall

0.6.0

17 Jun 21:34
b504a8d

Choose a tag to compare

Phirewall 0.6.0

Warning

0.6.0 is a breaking release. It removes several APIs and extracts the OWASP CRS engine into a separate Composer package. Review the upgrade notes below before updating. Every breaking change is also documented in detail in the CHANGELOG.

⚠️ Breaking changes & upgrade notes

1. OWASP CRS engine moved to a companion package (#95)

The Flowd\Phirewall\Owasp\ namespace (SecRuleLoader, CoreRuleSet, CoreRuleSetMatcher, the operator/variable collectors) and the $config->blocklists->owasp() shortcut have been removed from core. OWASP CRS support now lives in flowd/phirewall-preset-owasp-crs, which ships the engine under Flowd\PhirewallPresetOwaspCrs\Engine\ plus ready-made per-paranoia-level presets.

composer require flowd/phirewall-preset-owasp-crs
// Option A - apply a ready-made CRS preset:
use Flowd\PhirewallPresetOwaspCrs\Presets;
use Flowd\PhirewallPresetOwaspCrs\ParanoiaLevel;

$config = $config->with(Presets::blocklist(ParanoiaLevel::Level1));

// Option B - register a rule set yourself (replaces $config->blocklists->owasp(...)):
use Flowd\Phirewall\Config\Rule\BlocklistRule;
use Flowd\PhirewallPresetOwaspCrs\Engine\CoreRuleSetMatcher;

$config->blocklists->addRule(new BlocklistRule('owasp', new CoreRuleSetMatcher($ruleSet)));

The OWASP diagnostics header (X-Phirewall-Owasp-Rule, enableOwaspDiagnosticsHeader()) stays in core and works unchanged with the companion engine.

2. Config composition unified behind Config::with(ConfigLayer ...) (#96)

Config::combine() and Config::mergedWith() have been removed and Config::compose() is now private. Both a live Config and a PortableConfig implement the new Flowd\Phirewall\ConfigLayer interface, so all layers compose through one call.

// Before:  $config->combine($portableA, $portableB);   /  $config->mergedWith($overlay);
// After:
$config = $config->with($layerA, $layerB);   // layers apply left to right, later wins by rule name

3. $config->safelists->trustedBots() removed (#97)

The reverse-DNS TrustedBotMatcher stays in core; wire it directly.

use Flowd\Phirewall\Config\Rule\SafelistRule;
use Flowd\Phirewall\Matchers\TrustedBotMatcher;

$config->safelists->addRule(new SafelistRule(
    'trusted-bots',
    new TrustedBotMatcher(ipResolver: $config->getIpResolver(), cache: $cache),
));

Pass ipResolver: $config->getIpResolver() to keep the proxy-aware behaviour trustedBots() had by default; omit it to key on REMOTE_ADDR. Wiring the matcher directly also lets you rate-limit verified bots instead of safelisting them.

4. Route-scoped apiRateLimiting() / loginProtection() presets removed (#85)

These presets and their constants (API_RATE_LIMITING, LOGIN_PROTECTION, API_PATH_PREFIX, LOGIN_PATH_PREFIX, LOGIN_FAILURE_RULE) hardcoded application routes (/api, /login) and have been removed. Build API rate limiting and login brute-force protection as plain Config instead (see examples/03-api-rate-limiting.php and examples/02-brute-force-protection.php). The remaining universal presets are scannerBlocking() and sensitivePathBlocking().

5. Behavioural: IP-aware matchers now late-bind the client-IP resolver (#99)

IpMatcher, TrustedBotMatcher, FileIpBlocklistMatcher, and SnapshotBlocklistMatcher now implement ClientIpResolverAware. When constructed without an explicit $ipResolver, they resolve the client IP through the Config they run under at request time - instead of the REMOTE_ADDR they captured at construction. This makes IP rules composition-correct, but it is a behavioural change: a matcher built with no explicit resolver inside a Config that has an IP resolver set now uses that resolver. Pass an explicit resolver to opt out. (SafelistSection/BlocklistSection also no longer take a Config back-reference.)


What's Changed

⚠️ Breaking changes

  • Drop the route-scoped apiRateLimiting and loginProtection presets by @sascha-egerer in #85
  • Unify config composition behind Config::with(ConfigLayer) by @sascha-egerer in #96
  • Extract the OWASP CRS engine into flowd/phirewall-preset-owasp-crs by @sascha-egerer in #95
  • Remove the safelists->trustedBots() convenience method by @sascha-egerer in #97
  • Late-bind the client-IP resolver into IP-aware matchers by @sascha-egerer in #99

Fixes & hardening

  • Validate file blocklist entries as IP or CIDR on write by @sascha-egerer in #92
  • Skip the htaccess rewrite when the blocked-IP set is unchanged by @sascha-egerer in #93
  • Reject line breaks in PatternEntry value and target by @sascha-egerer in #94
  • Flatten nested ARGS parameters when collecting OWASP variable values by @sascha-egerer in #89
  • Fix @rx evaluator to inspect oversized values and fail closed on engine errors by @sascha-egerer in #88
  • Store the ban registry as a native array so it round-trips on every cache backend by @sascha-egerer in #90

Documentation & examples

Internal & packaging

Full Changelog: 0.5.0...0.6.0

0.5.0

08 Jun 22:28
44c495b

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: 0.4.0...0.5.0

0.4.0

19 May 12:59
1c31b0a

Choose a tag to compare

What's Changed

Full Changelog: 0.3.0...0.4.0

0.3.0

08 Apr 13:16
a3a14f0

Choose a tag to compare

Phirewall 0.3.0

Phirewall is a PSR-15 middleware that protects PHP applications from brute force, DDoS, SQL injection, XSS, and bot
attacks.

This is a major feature release with 36 pull requests — new protection layers, a cleaner architecture, stronger security
defaults, and a brand-new documentation site.

Documentation

Full documentation is now available at phirewall.de — covering getting started, framework
integration (Laravel, Symfony, Slim, Mezzio, TYPO3), all features, advanced topics, common attack recipes, and FAQ.

Highlights

New Protection Layers

  • Allow2Ban — hard volume cap with auto-ban after threshold, complementing Fail2Ban
  • Known Scanner Blocker — block sqlmap, nikto, nmap, burp, and other attack tools by User-Agent
  • Trusted Bot Verification — safelist Googlebot, Bingbot, etc. via reverse DNS
  • Suspicious Headers Detection — block requests missing standard browser headers
  • IP/CIDR Matcher — safelist or block by IP range

Smarter Rate Limiting

  • Sliding window strategy for smoother throttling alongside fixed-window
  • Multi-window throttle — burst + sustained limits in a single rule (e.g., 5 req/s + 200 req/min)
  • Dynamic limits — vary limits per request via closure (e.g., by user plan)
  • Track with threshold — passive counting with optional alerting

New Storage Backend

  • PdoCache — SQL-backed persistence for MySQL, PostgreSQL, and SQLite

Security Hardening

  • Response headers are now opt-inX-Phirewall / X-Phirewall-Matched no longer leak information by default
    (breaking change)
  • ReDoS length guard — OWASP @rx operator skips values >8 KiB to prevent catastrophic regex backtracking
  • Path traversal prevention@pmFromFile operator blocks directory traversal
  • Redis failure visibilityRedisCache::increment() emits E_USER_WARNING instead of failing silently

Architecture

  • Evaluator classesFirewall::decide() refactored into dedicated per-rule-type evaluators (SRP)
  • PatternKind enum — string-backed enum replacing class constants
  • PSR-17 response factories — framework-native responses via standard factories
  • RequestContext — post-handler fail2ban signaling from your login handler
  • Fail-open/fail-closed — configurable middleware error handling (fail-open by default)

Observability

  • DiagnosticsCounters — lightweight in-memory event counters for all rule types including Allow2Ban
  • DiagnosticsDispatcher — observe events and forward to a real PSR-14 dispatcher

Breaking Changes

  • X-Phirewall and X-Phirewall-Matched response headers are no longer added by default. Call
    $config->enableResponseHeaders() to re-enable them.
  • Fail2Ban/Allow2Ban threshold semantics corrected: ban triggers after N failures, not on the Nth attempt.

Deprecated

  • Config::add*() / Config::get*() methods — use the section API instead ($config->safelists->add(),
    $config->blocklists->owasp(), etc.). Will be removed in 0.4.

Install / Upgrade

composer require flowd/phirewall:^0.3

What's Changed

  • Refactor Config into section objects with PSR-14 diagnostics by @sascha-egerer in #1
  • Add tests: InMemoryPatternBackend, benchmarks, edge cases, value objects by @sascha-egerer in #2
  • Fix broken REQUEST_REGEX matching and O(n²) pruning by @sascha-egerer in #3
  • Add KnownScannerMatcher and blocklists->knownScanners() by @sascha-egerer in #5
  • Add TrustedBotMatcher, SuspiciousHeadersMatcher, IpMatcher, and shared matcher utilities by @sascha-egerer in #6
  • Harden allow2ban: validation, security, performance, BanManager API by @sascha-egerer in #7
  • Add sliding window throttle with strategy pattern by @sascha-egerer in #8
  • Add multiThrottle, dynamic throttle limits, disable toggle, and discriminator normalizer by @sascha-egerer in #9
  • Add track threshold with optional limit parameter and thresholdReached flag by @sascha-egerer in #10
  • Add PdoCache storage backend, reset helpers, and database test infrastructure by @sascha-egerer in #11
  • Add fail-open/fail-closed middleware error handling by @sascha-egerer in #12
  • Add comprehensive infrastructure adapter tests with vfsStream by @sascha-egerer in #13
  • Add PSR-17 response factory support by @sascha-egerer in #14
  • Update documentation and examples to current API by @sascha-egerer in #15
  • Modernize examples and extract DecisionPath enum by @sascha-egerer in #16
  • Improve documentation: middleware ordering, TYPO3 example, terminology by @sascha-egerer in #17
  • Add consistent constructor validation across all rule types by @sascha-egerer in #18
  • Resolve discriminator normalizer once at top of decide() by @sascha-egerer in #21
  • Cache OWASP operator preprocessing and prevent @pmFromFile path traversal by @sascha-egerer in #20
  • Replace hardcoded credentials with getenv() in PdoCache example by @sascha-egerer in #19
  • Add request attribute API for post-handler fail2ban signaling by @sascha-egerer in #22
  • Replace local docs with links to phirewall.de by @sascha-egerer in #24
  • Make X-Phirewall/X-Phirewall-Matched response headers opt-in by @sascha-egerer in #25
  • Fix fail2ban/allow2ban threshold off-by-one: ban after N failures, not on Nth by @sascha-egerer in #26
  • Extract CoreRule operator and variable logic into strategy classes by @sascha-egerer in #28
  • Extract shared fail2ban increment-and-ban logic by @sascha-egerer in #29
  • Separate DiagnosticsCounters (observer) from event dispatching by @sascha-egerer in #30
  • Extract Firewall::decide() into dedicated evaluator classes per rule type by @sascha-egerer in #31
  • Refactor PatternKind to string-backed enum and deduplicate PatternEntry logic by @sascha-egerer in #32
  • Add Allow2BanBanned event tracking to DiagnosticsCounters by @sascha-egerer in #33
  • Add ReDoS length guard to RegexEvaluator (8 KiB limit) by @sascha-egerer in #34
  • Surface RedisCache::increment() failures via trigger_error() by @sascha-egerer in #35
  • Add CHANGELOG.md for 0.3.0 release by @sascha-egerer in #36

Full Changelog: 0.2.0...0.3.0

0.2.0

05 Feb 00:06
6a173a4

Choose a tag to compare

Add In-Memory-Pattern-Backend and improve documentation

Full Changelog: 0.1.1...0.2.0

Release Notes – Version 0.1.1

15 Dec 19:25
68aec62

Choose a tag to compare

  • Add proper error message if APCu is missing

Release Notes – Version 0.1.0

12 Dec 17:03
9651c9b

Choose a tag to compare

Snapshot

Phirewall ships as a lean PSR‑15 middleware firewall for PSR‑7 stacks, pairing safelists, blocklists, throttles, Fail2Ban, and telemetry hooks without extra runtime baggage.

What’s fresh

  • Drop‑in middleware: auto-discovers PSR‑17 factories and runs in Slim, Mezzio, Laminas, Symfony, or bespoke pipelines.
  • Composable controls: safelist bypasses, targeted blocklists, per-key throttles with Retry‑After, Fail2Ban bans, and observability-only track hooks.
  • Pattern sources: mix IP/CIDR, path, header, regex, OWASP CRS adapters, and plug them into file/Redis/DB loaders.
  • Signals & tracing: PSR‑14 events, optional X‑RateLimit headers, diagnostics counters, and ready-made Monolog plus OpenTelemetry recipes.
  • Storage freedom: in-memory, APCu, Redis, or any PSR‑16 cache with automatic key normalization and namespacing.
  • Infrastructure bridges: Apache .htaccess adapter, nonblocking runners, and extensible InfrastructureBlockerInterface targets.

Where to use it

  • Protect APIs with layered burst/sustained budgets per token, IP, or user.
  • Harden login/admin flows with combined track, throttle, and Fail2Ban policies.
  • Shield webhooks by blocking suspicious signatures while collecting counters for forensics.
  • Mirror application bans to server ACLs or feed structured events into SIEM pipelines.