Download the PHP package kanopi/firewall without Composer

On this page you can find all versions of the php package kanopi/firewall. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package firewall

Lite Firewall

Lite Firewall is a powerful, extensible request-evaluation library for PHP-based systems. It provides comprehensive protection by analyzing HTTP requests and applying configurable rules to either allow or block access based on IP addresses, geolocation, user agents, URLs, ASN (Autonomous System Numbers), and rate limits. The library is designed to work seamlessly with popular frameworks like Drupal, WordPress, Symfony, or any standalone PHP application.

Table of Contents

Features

Requirements

Installation

Install via Composer:

Quick Start

Basic Implementation

Place the following code in your application's entry point (e.g., index.php, wp-config.php, or Drupal's settings.php):

⚠️ Important: Configure trusted proxies before calling Firewall::create()

Every plugin in this library evaluates $request->getClientIp(). Symfony only honors X-Forwarded-For / Forwarded / X-Real-IP when the integrator has called Symfony\Component\HttpFoundation\Request::setTrustedProxies(...). If your application sits behind a load balancer, CDN, or reverse proxy and you skip this step, attackers can spoof their source IP via X-Forwarded-For and bypass IP/CIDR allow-lists, block-lists, and per-IP rate limits.

When trusted proxies are not configured, Firewall::create() logs a warning to the configured logger. To make a missing trusted-proxies setup a hard startup failure instead, set global.require_trusted_proxies: true in your config β€” the library will then throw ConfigurationException rather than start in a spoofable state.

Minimal Configuration Example

Create a config/firewall.yml file:

Test Drive

Follow these steps to quickly test Lite Firewall locally in a clean environment:

πŸ§ͺ Quick Test Drive Setup

  1. Create a temporary folder

  2. Install Lite Firewall via Composer

  3. Create a basic firewall.yml configuration

  4. Create an index.php file

  5. Start a PHP built-in web server

  6. Open your browser and test

This simple example demonstrates how the firewall intercepts requests using YAML configuration and shows how easy it is to add rule-based blocking.

To start over empty the contents of the Storage file

Configuration Overview

The firewall configuration consists of five main sections:

Section Purpose Required
global Defines global configuration settings No
storage Defines where blocked IP addresses are persisted Yes
plugins Ordered list of plugin entries that allow (response: allow), challenge (response: challenge), or block (response: block) traffic No
challenge Settings for the interstitial flow (provider, HMAC secret, cookie / header names). Required iff any plugin uses response: challenge. See Challenge Response Type. Conditional
logger Monolog handlers for logging firewall events No

Legacy formats bypass: / block: are still accepted and auto-normalized into plugins: entries at load time. See Legacy format (deprecated) at the end of this document. New configs should use the plugins: array.

Configuration Loading & Includes

The firewall supports modular configuration via a top‑level configs: key in any YAML file. Paths listed under configs: are loaded and merged into the current file.

Rules & behavior

Remote Configuration Files

Configuration files can be loaded from remote URLs, which is useful for centralized management across multiple servers:

Remote files are cached locally to improve performance and reduce external dependencies. You can control caching behavior using PHP constants:

Example

In the example above, the log file and GeoIP database paths are relative to the YAML file (not the PHP current working directory). This makes configs portable regardless of where your app bootstraps from.

Environment Variables in YAML

You can reference OS environment variables inside YAML using Symfony‑style tokens: %env(NAME)%.

Variable Resolution with $_SERVER Fallback

The firewall checks environment variables in the following order:

  1. getenv() - PHP environment variables (set via putenv(), shell environment, or PHP-FPM/Apache configuration)
  2. $_SERVER - PHP superglobal (fallback when getenv() returns false)

This fallback behavior is particularly useful in web contexts (Drupal, WordPress, Symfony, Laravel) where configuration is often stored in $_SERVER by the web server or application framework.

Example use case: Nested Array Keys

Important: When extracting nested keys from JSON, you must chain key: processors for each level of nesting. For example, to access obj.a.b.c, use: json:key:a:key:b:key:c:VAR_NAME.

Priority: When a variable exists in both getenv() and $_SERVER, getenv() takes precedence. This allows you to override server-level configuration with environment-specific values.

Supported processors (can be chained left→right):

Examples

Path resolution for common keys

Some metadata values are commonly file paths. The loader automatically rewrites relative values to absolute when they exist on disk, using the YAML file's directory as the base. You can target keys with dot‑path patterns and lightweight alternation:

Useful patterns

With these patterns, paths like logs/app.log, geo/GeoLite2-ASN.mmdb, or limits/rate.yml will be resolved relative to the YAML file and stored as absolute paths at runtime.

Global Configuration

The global configuration allows for items like the default status code and the default block message template to be configured. More options to come.

Trusted Proxies

require_trusted_proxies controls how Firewall::create() reacts when Symfony\Component\HttpFoundation\Request::getTrustedProxies() is empty:

Value Behaviour
false (default) Logs a warning and continues. Suitable for development or when the application is reachable only directly.
true Throws Kanopi\Firewall\Exception\ConfigurationException and refuses to start. Recommended for production deployments behind a load balancer / CDN / reverse proxy.

See the trusted-proxies note in Basic Implementation for the Request::setTrustedProxies(...) call you need to add before Firewall::create().

Mode

The mode setting controls how the firewall responds when a request is matched by a blocking plugin. Defaults to block if not specified.

Mode Evaluates plugins? Writes to storage? Terminates request?
block Yes Yes Yes (sends HTTP response and exits)
log Yes No No (logs a warning and allows the request)
exception Yes Yes No (throws FirewallBlockedException)
disabled No No No (skips all evaluation)

Status Code

The status code of the default message can be defined here. By default, it sets it to 400 but can be set to something else if it is needed.

Banning Message

The banning message can be configured and dynamically replaced with placeholders. Examples of placeholders can be found below.

Multiple Offenses Defense

Some storage plugins can track multiple offenses from the same attacker over time. You can control how blocking escalates by using the blocking_escalation configuration setting.

Below is an example of how to configure it:

Each escalation rule includes the following:

This system lets you gradually increase penalties for repeat offenders, starting with temporary bans and escalating to permanent blocks if necessary.

Storage Configuration

Storage defines how the firewall persists blocked IP addresses across requests.

Available Storage Classes

1. In-Memory Storage

Non-persistent storage that resets with each request. Useful for testing.

2. File Storage

Persists blocked IPs to the filesystem.

3. Database Storage

Stores blocked IPs in a SQL database using Doctrine DBAL.

Plugin Architecture

Plugins are the core components that evaluate incoming requests. They are configured as an ordered list under the top-level plugins: key. Each entry declares one plugin instance and its response mode β€” either allow (let the request through), block (reject the request), or challenge (require the visitor to solve an interstitial before continuing).

Common Plugin Configuration

All plugin entries share the same shape:

The same class can appear multiple times in the list β€” each entry becomes its own plugin instance, so you can split rules across instances with different weights or response modes.

YAML Syntax Note: The plugin: value must be quoted with double backslashes:

This also applies to all type: declarations (storage backends, rate limit storage).

Plugin Execution Order

The firewall evaluates response: allow entries first (sorted by weight, lower runs first). If any allow plugin matches, the request is permitted immediately and no other plugins run. Otherwise:

  1. response: challenge entries run next. If one matches and the visitor does not already hold a valid pass token, an interstitial is served and the request is paused until the challenge is solved.
  2. response: block entries run last and the first match rejects the request.

A valid pass token (set by a previously solved challenge) short-circuits the challenge bucket but does not suppress block plugins. See Challenge Response Type below.

Suggested weight ranges:

Example: Layered Security

Challenge Response Type

response: challenge serves an interstitial (a CAPTCHA-style proof-of-effort page) when a plugin matches, instead of rejecting the request outright. A visitor who solves the challenge is issued an HMAC-signed pass token that short-circuits any future response: challenge plugin until the token expires.

The pass token is:

Minimum configuration

If any plugin uses response: challenge, challenge.secret is required. Startup fails fast with ConfigurationException when it is empty β€” the firewall will not silently fall back to plaintext tokens.

Built-in provider

The math provider asks "What is A + B?" with single-digit operands. It's a low-friction proof-of-effort, not a CAPTCHA. For stronger bot resistance, implement Kanopi\Firewall\Challenge\ChallengeProviderInterface (Turnstile, hCaptcha, reCAPTCHA, etc.) and set challenge.provider to its FQCN.

How dispatch interacts with allow / block

Visitor state Result
Matched by an allow plugin Allowed (challenge skipped).
Holds a valid pass token + matches challenge Allowed (challenge bucket skipped).
No token, matches a challenge plugin Interstitial served; original URL is remembered for the post-success redirect.
Matches a block plugin Blocked, even if a valid pass token is held.

Loading External Plugin Configuration

Plugins can load rules from external files (local or remote) using the metadata.config option. This is useful for managing large rule sets separately:

The external files use the same structure as the inline config section. Multiple files can be specified and will be merged in order. Both local file paths (relative or absolute) and remote URLs are supported.

Available Plugins

IP Address Plugin

Namespace: \Kanopi\Firewall\Plugins\IpAddress

Evaluates requests based on IP addresses, supporting IPv4, IPv6, CIDR blocks, and IP ranges.

Configuration Example

GeoLocation Plugin

Namespace: \Kanopi\Firewall\Plugins\GeoLocation

Evaluates requests based on geographic location using MaxMind GeoIP2 databases.

Configuration Example

Available Variables

URL Plugin

Namespace: \Kanopi\Firewall\Plugins\Url

Evaluates requests based on URL components and request parameters.

Configuration Example

Available Variables

User Agent Plugin

Namespace: \Kanopi\Firewall\Plugins\UserAgent

Analyzes user agent strings to identify bots, devices, browsers, and operating systems.

Configuration Example

Available Variables

ASN Plugin

Namespace: \Kanopi\Firewall\Plugins\Asn

Evaluates requests based on Autonomous System Numbers (ASN) using MaxMind's GeoIP2 ASN database.

Configuration Example

Available Variables

Rate Limit Plugin

Namespace: \Kanopi\Firewall\Plugins\RateLimit

Implements rate limiting to prevent abuse and DDoS attacks.

Configuration Example

Path Patterns

Vulnerability Score Plugin

Namespace: \Kanopi\Firewall\Plugins\VulnerabilityScore

Evaluates requests based on a comprehensive scoring system that combines multiple risk factors to determine if a request should be blocked. This plugin provides fine-grained control over security policies by assigning scores to various request characteristics and blocking based on cumulative risk levels.

Key Features

Configuration Example

Scoring Components

1. Method Scoring

Assigns scores based on HTTP methods, with higher scores for potentially dangerous operations.

2. Country Scoring

Uses GeoIP database to identify request origin and assign scores based on geographic risk assessment.

3. ASN Scoring

Evaluates the Autonomous System Number of the request origin, identifying datacenter, VPN, or residential connections.

4. Pattern Detection

Searches for malicious patterns in various parts of the request:

5. User Agent Analysis

Identifies and scores suspicious or malicious user agents, including security tools and bots.

Risk Levels

Each risk level can be configured with:

Advanced Usage Examples

Example 1: E-commerce Site Protection
Example 2: API Protection
Example 3: Geographic Restrictions with Exceptions

Integration with Other Plugins

The VulnerabilityScore plugin works well with other firewall plugins:

Performance Considerations

Debugging and Monitoring

The plugin logs detailed information about scoring decisions:

Log entries include:

CRS (OWASP Core Rule Set) Plugin

Namespace: \Kanopi\Firewall\Plugins\Crs

Evaluates each request against the OWASP Core Rule Set β€” the same ruleset that powers ModSecurity, Coraza, and most commercial WAFs. Detects SQL injection, XSS, LFI, RFI, RCE, PHP / Java injection, session fixation, protocol-level attacks, and known scanner traffic. Backed by the kanopi/crs-engine composer package, which parses CRS source files into a runtime-optimised cache and refreshes weekly from upstream.

Key Features

Configuration Example

Coverage

Currently the plugin handles request-side evaluation: every CRS rule in REQUEST-*.conf runs against the incoming request. Response-side rules (RESPONSE-* files β€” SQL error / stack-trace / PHP warning leakage detection) are tracked under issue #69 and will land as a follow-up.

The four CRS rules that rely on libinjection (@detectSQLi / @detectXSS β€” rules 941100, 941180, 942100, 942500) are parsed but not evaluated; the engine logs them as parser warnings in vendor/kanopi/crs-engine/rules/manifest.json. CRS's regex-based SQLi/XSS rules in the same files run normally and provide the bulk of the detection.

What gets logged

Blocked requests log at info level with full context:

Non-blocking matches (monitor mode, or rules whose action is pass) log at debug level.

Conditional Logic

The firewall supports three formats for defining conditions:

1. Simple Format

Quick and readable syntax for common conditions:

Supported Operators

2. Complex Format

Detailed configuration with full control:

3. Grouped Format

Combine multiple conditions with logical operators:

Logging Configuration

The firewall uses Monolog for flexible logging, so any Monolog handler can be wired up through the logger key. Each entry under logger is a separate handler β€” combine as many as you need (file + Slack + email is a common pattern).

Each handler entry accepts:

Log levels are passed as strings like Monolog\Level::Info (Debug, Info, Notice, Warning, Error, Critical, Alert, Emergency). Relative log file paths (e.g., args[0] for StreamHandler) are resolved relative to the YAML file that declares them.

Heads up: several Monolog handlers require additional PHP extensions or third-party packages. Slack/IFTTT/Pushover/Telegram need ext-curl; SendGridHandler and SymfonyMailerHandler may require composer require of the relevant transport package. See the Monolog handler docs for each handler's prerequisites.

File logging

Write every event to a flat file:

Rotating file logging

Rotate logs daily and keep the last seven days. Useful when StreamHandler files grow unbounded:

JSON-structured logging

Emit one JSON object per line β€” easy to ingest into Loki, ELK, Datadog, etc:

Syslog

Forward events to the host's syslog (handy on managed/cloud platforms that scrape syslog automatically):

SyslogHandler accepts a facility name (string) such as user, daemon, mail, auth, local0–local7. The PHP LOG_* constants are integers that YAML cannot reference; passing the literal string LOG_USER triggers UnexpectedValueException. Stick to the lowercase names above.

PHP error log

Pipe firewall events into the configured PHP error_log β€” useful in shared hosting or when you don't control filesystem paths:

Email alerts

Send an email when something critical happens. NativeMailerHandler uses PHP's mail() β€” no extra package required:

For higher-volume alerting via SendGrid (requires ext-curl):

Slack alerts

Post directly to a Slack channel through an Incoming Webhook. Requires ext-curl:

If you prefer the Slack Web API (legacy token-based handler):

Pushover (push notifications)

Send mobile push notifications via Pushover:

IFTTT webhooks

Trigger an IFTTT Maker applet β€” useful for chaining custom automations (SMS, smart lights, voice assistants, etc.):

IFTTT receives three values: value1 = channel, value2 = level name, value3 = message.

Telegram bot

Send messages to a Telegram channel or chat via a bot token:

Per-handler severity thresholds

Each handler entry has its own level argument, so you can tune verbosity per destination. The pattern below writes every Info-and-above event to file but only escalates Critical events to email:

Handlers that wrap other handlers (e.g. FingersCrossedHandler, BufferHandler, FilterHandler, GroupHandler) take a HandlerInterface as a constructor argument, which the YAML loader cannot construct recursively. To use those, build the logger programmatically with Monolog\Logger and inject it via LoggingFactory::setLogger() before calling Firewall::create().

Combining multiple handlers

You can stack any number of handlers β€” each entry under logger is independent. A common production setup tees everything to a file, surfaces warnings to syslog, and pages humans via Slack/Pushover only on critical events:

For the full catalogue of available handlers (Telegram, Mandrill, Loggly, Elasticsearch, Sentry via PSR, etc.), see the Monolog handlers reference.

Dynamic Configuration Overrides

For dynamic environments (Docker, multi-site installations), you can override YAML configuration with PHP arrays. Override paths target the source YAML shape (before plugin normalization runs), so the right path depends on how your YAML is written.

Overriding entries written in the plugins: array β€” the path includes the list index (0, 1, 2, …) in declaration order:

Overriding entries written in the legacy block: / bypass: format β€” paths still address the plugin by class name (legacy format is normalized after overrides are merged, so this continues to work):

Platform Integration

Drupal

Add to settings.php before the container configuration:

WordPress

Add to wp-config.php after ABSPATH is defined but before wp-settings.php:

Symfony

Add to public/index.php before the kernel boot:

Laravel

Add to public/index.php after the autoloader:

Advanced Examples

Multi-layered Security Configuration

Custom Plugin Implementation

Create a custom plugin to implement specific business logic:

Register the custom plugin in your configuration:

Testing

The firewall includes a comprehensive test suite. Run tests with:

Example Test Case

Legacy format (deprecated)

Earlier versions of this library configured plugins in two separate top-level sections (bypass: and block:), each keyed by the plugin class name. This format is still accepted β€” Kanopi\Firewall\Utility\PluginConfigNormalizer rewrites it into the plugins: array shape at load time β€” but it will be removed in a future major release. New configs should use the plugins: array described above.

Side-by-side

Legacy (deprecated) New (plugins: array)
bypass: section entry with response: allow
block: section entry with response: block
keyed by plugin class plugin: "..." field on each entry
priority: weight:
one instance per class per section multiple instances per class allowed
deep-merges by class across configs: includes appends entries across includes

Same config in both shapes

You can also mix both formats in the same config during migration β€” legacy entries are normalized first, then appended to whatever is already in plugins:.

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

  1. Clone the repository
  2. Install dependencies: composer install
  3. Run tests: composer test
  4. Check code style: composer cs
  5. Run static analysis: composer stan

License

This project is licensed under the MIT License. See the LICENSE file for details.

Support

Credits

Lite Firewall is developed and maintained by Kanopi Studios.

Special thanks to:


All versions of firewall with dependencies

PHP Build Version
Package Version
Requires php Version >=8.1
amphp/dns Version ^2.4
doctrine/dbal Version ^4.2
geoip2/geoip2 Version ~2 || ^3
guzzlehttp/guzzle Version ^7.9
matomo/device-detector Version ^6.4
monolog/monolog Version ^3.9
symfony/cache Version ~6.4 || ~7.3
symfony/http-foundation Version ~6.4 || ~7.3
symfony/property-access Version ~6.4 || ~7.3
symfony/uid Version ~6.4 || ~7.3
symfony/yaml Version ~6.4 || ~7.3
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package kanopi/firewall contains the following files

Loading the files please wait ...