Examples 

Key features of the Firewall extension:

  • Integration of the Phirewall package (see Phirewall)
  • Management of static block patterns in the backend
  • Support for various pattern types (IP, CIDR, path, header, user agent, regex)
  • Expiration date for patterns (expiresAt)

Configuration overview 

  • Core Phirewall configuration: config/system/phirewall.php
  • Static custom patterns managed by the firewall backend module: config/system/phirewall.patterns.php

Usage Examples 

Below are practical examples of configuring the firewall in a TYPO3 context.

Blocking common scanner requests and known bot IPs 

This example blocks requests from known bad IP addresses and certain paths or query strings. It uses InMemoryCache, which is fine for simple blocklists (no rate limiting).

<?php
use Flowd\Phirewall\Config;
use Flowd\Phirewall\Store\InMemoryCache;
use Psr\EventDispatcher\EventDispatcherInterface;

return fn (EventDispatcherInterface $eventDispatcher) =>
    (new Config(new InMemoryCache(), $eventDispatcher))
        ->blocklist(
            name: 'evil-bot-ips',
            callback: fn(ServerRequestInterface $request) => in_array($request->getServerParams()['REMOTE_ADDR'] ?? '', [
                '176.65.149.61',
                '45.13.214.201',
            ], true)
        )
        ->blocklist(
            name: 'blocked-uri-paths',
            callback: fn(ServerRequestInterface $request) => str_starts_with(strtolower($request->getUri()->getPath()), '/wp_admin')
        )
        ->blocklist(
            name: 'blocked-uri-query-strings',
            callback: fn(ServerRequestInterface $request) => str_contains(strtolower($request->getUri()->getQuery()), 'xdebug')
                || str_contains(strtolower($request->getUri()->getQuery()), 'option=com_')
        );
Copied!

Temporary blocking after repeated abuse (Fail2Ban) 

This example blocks users for 1 minute if they access /search more than 5 times in 10 seconds. Requires a persistent cache backend like APCu or Redis.

<?php
use Flowd\Phirewall\Config;
use Flowd\Phirewall\KeyExtractors;
use Flowd\Phirewall\Store\ApcuCache;
use Psr\EventDispatcher\EventDispatcherInterface;

return fn (EventDispatcherInterface $eventDispatcher) =>
    (new Config(new ApcuCache(), $eventDispatcher))
        ->fail2ban(
            name: 'search-page-scrapers',
            threshold: 5,
            period: 10,
            ban: 60,
            filter: fn($request) => str_starts_with($request->getUri()->getPath(), '/search'),
            key: KeyExtractors::ip()
        );
Copied!

Rate limiting with clear client feedback 

This example limits users to 10 requests every 10 seconds (per IP) and sends rate limit headers. Requires a persistent cache backend like APCu or Redis.

<?php
use Flowd\Phirewall\Config;
use Flowd\Phirewall\KeyExtractors;
use Flowd\Phirewall\Store\ApcuCache;
use Psr\EventDispatcher\EventDispatcherInterface;

return fn (EventDispatcherInterface $eventDispatcher) =>
    (new Config(new ApcuCache(), $eventDispatcher))
        ->throttle(
            name: 'slow-down-to-10-requests-in-10-seconds',
            limit: 10,
            period: 10,
            key: KeyExtractors::ip()
        )
        ->enableRateLimitHeaders();
Copied!

Using APCu as a cache backend 

This example shows how to use APCu as a cache backend. Use this for single-server setups.

<?php
use Flowd\Phirewall\Config;
use Flowd\Phirewall\Store\ApcuCache;
use Psr\EventDispatcher\EventDispatcherInterface;

return fn (EventDispatcherInterface $eventDispatcher) =>
    (new Config(new ApcuCache(), $eventDispatcher))
        ->blocklist(
            name: 'blocked-uri-paths',
            callback: fn($request) => str_starts_with(strtolower($request->getUri()->getPath()), '/wp_admin')
        );
Copied!

Using Redis as a cache backend 

This example uses Redis for the cache backend, which is recommended for production and multi-server setups.

<?php
use Flowd\Phirewall\Config;
use Flowd\Phirewall\Store\RedisCache;
use Predis\Client;
use Psr\EventDispatcher\EventDispatcherInterface;

return fn (EventDispatcherInterface $eventDispatcher) =>
    (new Config(new RedisCache(new Client('redis://localhost:6379')), $eventDispatcher))
        ->blocklist(
            name: 'blocked-uri-paths',
            callback: fn($request) => str_starts_with(strtolower($request->getUri()->getPath()), '/wp_admin')
        );
Copied!

Using a custom response for blocked requests 

This example shows how to return a custom message and status code when a request is blocked.

<?php
use Flowd\Phirewall\Config;
use Flowd\Phirewall\Store\ApcuCache;
use Psr\EventDispatcher\EventDispatcherInterface;
use TYPO3\CMS\Core\Http\ResponseFactory;
use TYPO3\CMS\Core\Http\StreamFactory;

return fn (EventDispatcherInterface $eventDispatcher) =>
    (new Config(new ApcuCache(), $eventDispatcher))
        ->blocklist(
            name: 'blocked-uri-paths',
            callback: fn($request) => str_starts_with(strtolower($request->getUri()->getPath()), '/wp_admin')
        )
        ->blocklistedResponse(function ($rule, $type, $request) {
            return (new ResponseFactory())
                ->createResponse()
                ->withBody((new StreamFactory())->createStream('Access denied by firewall rule: ' . $rule . ' (type: ' . $type . ')'))
                ->withHeader('Content-Type', 'text/plain')
                ->withStatus(403);
        });
Copied!