SkillAgentSearch skills...

Phirewall

Phirewall is a PHP based application firewall that provides a PSR-15 middleware.

Install / Use

/learn @flowd/Phirewall
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Phirewall

<img src="docs/assets/logo.svg" width="200" alt="Phirewall Logo" align="right">

Protect your PHP application from brute force, DDoS, SQL injection, XSS, and bot attacks with a single middleware.

Phirewall is a PSR-15 middleware that provides comprehensive application-layer protection. It's lightweight, framework-agnostic, and easy to configure.


Why Phirewall?

  • Simple Setup - Add protection in minutes with sensible defaults
  • Multiple Attack Vectors - Rate limiting, brute force protection, OWASP rules, bot detection
  • Framework Agnostic - Works with any PSR-15 compatible framework (Laravel, Symfony, Slim, Mezzio, etc.)
  • Production Ready - Redis support for multi-server deployments
  • Observable - PSR-14 events for logging, metrics, and alerting

Quick Start

composer require flowd/phirewall
use Flowd\Phirewall\Config;
use Flowd\Phirewall\Middleware;
use Flowd\Phirewall\KeyExtractors;
use Flowd\Phirewall\Store\InMemoryCache;

// Create the firewall
$config = new Config(new InMemoryCache());

// Allow health checks to bypass all rules
$config->safelists->add('health', fn($req) => $req->getUri()->getPath() === '/health');

// Block common scanner paths
$config->blocklists->add('scanners', fn($req) => str_starts_with($req->getUri()->getPath(), '/wp-admin'));

// Rate limit: 100 requests per minute per IP
$config->throttles->add('api', limit: 100, period: 60 /* seconds */, key: KeyExtractors::ip());

// Ban IP after 5 failed logins in 5 minutes
$config->fail2ban->add('login', threshold: 5, period: 300 /* seconds */, ban: 3600 /* seconds */,
    filter: fn($req) => $req->getHeaderLine('X-Login-Failed') === '1',
    key: KeyExtractors::ip()
);

// Add to your middleware stack
$middleware = new Middleware($config);
// The PSR-17 ResponseFactory is optional — Phirewall auto-detects installed factories.
// Pass one explicitly if needed: new Middleware($config, new Psr17Factory())

Add the middleware to your PSR-15 pipeline. All requests will be evaluated against your rules before reaching your application.

Try It Now

Run one of the included examples to see Phirewall in action:

# Basic setup demo
php examples/01-basic-setup.php

# See brute force protection
php examples/02-brute-force-protection.php

# Test SQL injection blocking
php examples/04-sql-injection-blocking.php

# Full production setup
php examples/08-comprehensive-protection.php

Examples

The examples/ folder contains runnable examples:

| # | Example | Description | |---|---------|-------------| | 01 | basic-setup | Minimal configuration to get started | | 02 | brute-force-protection | Fail2Ban-style login protection | | 03 | api-rate-limiting | Tiered rate limits for APIs | | 04 | sql-injection-blocking | OWASP-style SQLi detection | | 05 | xss-prevention | Cross-Site Scripting protection | | 06 | bot-detection | Scanner and malicious bot blocking | | 07 | ip-blocklist | File-backed IP/CIDR blocklists | | 08 | comprehensive-protection | Production-ready multi-layer setup | | 09 | observability-monolog | Event logging with Monolog | | 10 | observability-opentelemetry | Distributed tracing with OpenTelemetry | | 11 | redis-storage | Redis backend for multi-server deployments | | 12 | apache-htaccess | Apache .htaccess IP blocking | | 13 | benchmarks | Storage backend performance comparison | | 14 | owasp-crs-files | Loading OWASP CRS rules from files | | 15 | in-memory-pattern-backend | Configuration-based CIDR/IP blocklists | | 16 | allow2ban | Hard volume cap with auto-ban | | 17 | known-scanners | Block known attack tools and vulnerability scanners | | 18 | trusted-bots | Trusted bot verification via reverse DNS | | 19 | header-analysis | Suspicious headers detection | | 20 | rule-benchmarks | Firewall rule performance benchmarks | | 21 | sliding-window | Sliding window rate limiting | | 22 | multi-throttle | Multi-window burst + sustained rate limiting | | 23 | dynamic-limits | Role-based dynamic throttle limits | | 24 | pdo-storage | PdoCache with SQLite, MySQL, PostgreSQL | | 25 | track-threshold | Track with optional threshold and thresholdReached flag | | 26 | psr17-factories | PSR-17 response factory integration | | 27 | request-context | RequestContext API for post-handler fail2ban signaling |

Features

Protection Layers

| Feature | Description | |---------|-------------| | Safelists | Bypass all checks for trusted requests (health checks, internal IPs) | | Blocklists | Immediately deny suspicious requests (403) | | Throttling | Fixed and sliding window rate limiting by IP, user, API key, or custom key (429) with dynamic limits and multiThrottle | | Fail2Ban | Auto-ban after repeated failures | | Allow2Ban | Hard volume cap -- ban after too many total requests | | Track with Threshold | Passive counting with optional alert threshold | | OWASP CRS | SQL injection, XSS, and PHP injection detection | | Pattern Backends | File/Redis-backed blocklists with IP, CIDR, path, and header patterns |

Matchers

| Matcher | Description | |---------|-------------| | Known Scanners | Block sqlmap, nikto, nmap, and other scanner User-Agents | | Trusted Bots | Safelist Googlebot, Bingbot, etc. via reverse DNS verification | | Suspicious Headers | Block requests missing standard browser headers | | IP Matcher | Safelist or block by IP/CIDR range |

Observability

  • PSR-14 Events - SafelistMatched, BlocklistMatched, ThrottleExceeded, Fail2BanBanned, Allow2BanBanned, TrackHit, FirewallError
  • Fail-Open by Default - Cache outages don't take down the application; errors dispatched via PSR-14
  • Diagnostics Counters - Per-rule statistics for monitoring
  • Standard Headers - X-RateLimit-*, Retry-After, X-Phirewall-*

Storage Backends

| Backend | Use Case | |---------|----------| | InMemoryCache | Development, testing, single requests | | ApcuCache | Single-server production | | RedisCache | Multi-server production | | PdoCache | SQL-backed persistence (MySQL, PostgreSQL, SQLite) |

Documentation

Full documentation is available at phirewall.de:

  • Getting Started - Installation & quick start guide
  • Framework Integration - PSR-15, Laravel, Symfony, Slim, Mezzio
  • Features - Safelists, blocklists, rate limiting, fail2ban, bot detection, OWASP rules
  • Advanced - Dynamic throttles, observability, infrastructure adapters
  • Common Attacks - Protection recipes for 10+ attack types
  • FAQ - Frequently asked questions

Installation

composer require flowd/phirewall

Optional Dependencies

# For Redis-backed distributed counters (multi-server)
composer require predis/predis

# For Monolog logging integration
composer require monolog/monolog

APCu: Enable the PHP extension and set apc.enable_cli=1 for CLI testing.

Response Headers

Phirewall can add diagnostic headers to the response when a request is blocked or safelisted. These diagnostic headers are opt-in and disabled by default:

$config->enableResponseHeaders(); // Enable X-Phirewall, X-Phirewall-Matched, and X-Phirewall-Safelist headers

| Header | Description | Opt-in required | |--------|-------------|-----------------| | X-Phirewall | Block type: blocklist, throttle, fail2ban, allow2ban | Yes | | X-Phirewall-Matched | Rule name that triggered | Yes | | X-Phirewall-Safelist | Safelist rule that matched (on allowed requests) | Yes | | Retry-After | Seconds until the client may retry (throttles and allow2ban bans) | No (always present) |

Note: Retry-After is always included on responses where a retry delay applies (429 throttles and allow2ban bans), regardless of enableResponseHeaders().

Enable $config->enableRateLimitHeaders() for standard X-RateLimit-* headers.

Client IP Behind Proxies

When behind load balancers or CDNs, use TrustedProxyResolver:

use Flowd\Phirewall\Http\TrustedProxyResolver;
use Flowd\Phirewall\KeyExtractors;

$resolver = new TrustedProxyResolver([
    '10.0.0.0/8',      // Internal network
    '172.16.0.0/12',   // Docker
]);

$config->throttles->add('api', limit: 100, period: 60,
    key: KeyExtractors::clientIp($resolver)
);

Custom Responses

Customize blocked responses while keeping standard headers:

use Flowd\Phirewall\Config\Response\ClosureBlocklistedResponseFactory;
use Flowd\Phirewall\Config\Response\ClosureThrottledResponseFactory;

$config->blocklistedResponseFactory = new ClosureBlocklistedResponseFactory(
    function (string $rule, string $type, $req) {
        return new Response(403, ['Content-Type' => 'applicati

Related Skills

View on GitHub
GitHub Stars13
CategoryDevelopment
Updated2d ago
Forks0

Languages

PHP

Security Score

75/100

Audited on Apr 8, 2026

No findings