# How to Configure WAF Rules for Web Application Security in Easegress

> Configure WAF rules for web application security effectively in Easegress. Learn to define WAFController objects and reference rule groups in your HTTP pipeline for robust protection.

- Repository: [MegaEase/easegress](https://github.com/megaease/easegress)
- Tags: how-to-guide
- Published: 2026-03-07

---

**To configure WAF rules for web application security in Easegress, define a global WAFController object containing rule groups with ModSecurity/Coraza syntax or OWASP CRS bundles, then reference the specific rule group name in a WAF filter within your HTTP pipeline.**

Easegress provides a production-grade Web Application Firewall (WAF) implementation that leverages the Coraza engine to inspect HTTP traffic. When you configure WAF rules for web application security in Easegress, you implement a two-tier architecture separating rule definitions from enforcement logic, enabling centralized rule management across multiple pipelines.

## Understanding the WAF Architecture in Easegress

The Easegress WAF implementation consists of two core components that work together to inspect and filter malicious traffic.

### WAFController: The Global Rule Engine

The **WAFController** is a singleton object defined in [`pkg/object/wafcontroller/wafcontroller.go`](https://github.com/megaease/easegress/blob/main/pkg/object/wafcontroller/wafcontroller.go) that manages one or more **rule groups**. Each rule group encapsulates a Coraza engine instance configured with specific security rules. The controller exposes a global handler via `GetGlobalWAFController()` that pipelines invoke to process requests.

Key responsibilities include:
- Parsing `RuleGroupSpec` configurations (custom ModSecurity rules, OWASP CRS bundles, IP/Geo blockers, rate limiters)
- Building and caching Coraza engines for each rule group
- Exposing the `Handle(ctx, ruleGroupName)` method that executes rule evaluation

### WAF Filter: Pipeline Integration

The **WAF filter** ([`pkg/filters/waf/waf.go`](https://github.com/megaease/easegress/blob/main/pkg/filters/waf/waf.go)) is a pipeline component that bridges HTTP traffic to the global controller. When processing a request, the filter:

1. Retrieves the singleton controller via `wafcontroller.GetGlobalWAFController()`
2. Invokes `handler.Handle(ctx, ruleGroupName)` using the `ruleGroup` specified in its configuration
3. Receives a result (`ok`, `blocked`, `ruleGroupNotFoundError`, or `noWAFControllerError`)
4. If `blocked`, terminates the request with HTTP 500 (or custom action defined in rules)

The filter's result list is dynamically assembled by appending controller results to the filter-specific `noWAFControllerError` value, as defined in lines 30-55 of [`waf.go`](https://github.com/megaease/easegress/blob/main/waf.go).

## Configuring WAF Rules in Easegress

Implementing WAF protection requires creating two YAML objects: a WAFController for rule definitions and a Pipeline containing a WAF filter for enforcement.

### Step 1: Define a WAFController with Rule Groups

Create a WAFController object that specifies one or more rule groups. Each group can combine multiple rule sources:

| Rule Source | Description | Configuration Field |
|-------------|-------------|---------------------|
| **Custom Rules** | Inline ModSecurity/Coraza syntax | `customRules` |
| **OWASP CRS Files** | Specific CRS rule files | `owaspRules` |
| **Full OWASP CRS** | Complete CRS bundle via `coraza-coreruleset` | `loadOwaspCrs: true` |
| **IP Blocker** | Whitelist/blacklist CIDR blocks | `ipBlocker` |
| **GeoIP Blocker** | Country-based filtering (requires MaxMind DB) | `geoIPBlocker` |
| **Rate Limiter** | Request throttling rules | `rateLimiter` |

### Step 2: Add the WAF Filter to Your Pipeline

Reference the rule group in a pipeline filter:

```yaml
filters:
  - name: waf
    kind: WAF
    ruleGroup: <rule-group-name>  # Must match name in WAFController

```

The filter must be positioned before the proxy or backend filters to inspect incoming requests.

## Practical WAF Configuration Examples

### SQL Injection Protection with OWASP CRS

This configuration loads specific OWASP CRS files to protect against SQL injection attacks:

```yaml
name: waf-controller
kind: WAFController
ruleGroups:
  - name: sql-protection
    rules:
      owaspRules:
        - REQUEST-901-INITIALIZATION.conf
        - REQUEST-942-APPLICATION-ATTACK-SQLI.conf
        - REQUEST-949-BLOCKING-EVALUATION.conf

```

```yaml
name: api-pipeline
kind: Pipeline
filters:
  - name: waf-sql
    kind: WAF
    ruleGroup: sql-protection
  - name: backend-proxy
    kind: Proxy
    pools:
      - servers:
          - url: http://127.0.0.1:9095
          - url: http://127.0.0.1:9096
          loadBalance:
            policy: roundRobin

```

The controller initializes a Coraza engine with these three CRS files, and the filter evaluates every request against SQL injection patterns before forwarding to the backend pool.

### Full OWASP CRS with Custom Rules

To load the complete OWASP Core Rule Set and append custom ModSecurity rules:

```yaml
name: waf-controller
kind: WAFController
ruleGroups:
  - name: full-crs-custom
    rules:
      loadOwaspCrs: true
      customRules: |
        SecRule REQUEST_METHOD "POST" "id:1000001,phase:1,block,log,msg:'Block all POST requests (phase 1)',severity:'CRITICAL'"
        SecRule REQUEST_METHOD "POST" "id:1000002,phase:2,block,log,msg:'Block all POST requests (phase 2)',severity:'CRITICAL'"

```

```yaml
name: protected-pipeline
kind: Pipeline
filters:
  - name: waf
    kind: WAF
    ruleGroup: full-crs-custom
  - name: proxy
    kind: Proxy
    pools:
      - servers:
          - url: http://backend:8080

```

Setting `loadOwaspCrs: true` pulls the official `coraza-coreruleset` package, while `customRules` appends organization-specific policies.

### IP and GeoIP Blocking

Restrict access based on source IP ranges or geographic location:

```yaml
name: waf-controller
kind: WAFController
ruleGroups:
  - name: ip-whitelist
    rules:
      ipBlocker:
        whitelist:
          - 192.168.1.0/24
          - 10.0.0.0/8
  - name: geo-restrict
    rules:
      geoIPBlocker:
        dbPath: /opt/geoip/GeoLite2-Country.mmdb
        deniedCountries:
          - CN
          - RU

```

```yaml
name: secure-pipeline
kind: Pipeline
filters:
  - name: waf-ip
    kind: WAF
    ruleGroup: ip-whitelist
  - name: waf-geo
    kind: WAF
    ruleGroup: geo-restrict
  - name: proxy
    kind: Proxy
    pools:
      - servers:
          - url: http://app:80

```

The `geoIPBlocker` requires a MaxMind GeoIP2 database file specified in `dbPath`.

## Monitoring WAF Metrics

The WAFController automatically exposes Prometheus metrics for observability. Key metrics include `waf_total_refused_requests`, which tracks blocked requests per rule group. These metrics are defined in [`pkg/object/wafcontroller/metrics/metrics.go`](https://github.com/megaease/easegress/blob/main/pkg/object/wafcontroller/metrics/metrics.go) and scraped from the standard Easegress metrics endpoint.

To monitor rule effectiveness, configure your Prometheus instance to scrape the Easegress instance and create alerts based on the `waf_*` metric family.

## Summary

- **Two-tier architecture**: Configure WAF rules for web application security in Easegress by creating a global **WAFController** (rule definitions) and pipeline **WAF filters** (enforcement).
- **Rule group flexibility**: Each rule group in [`pkg/object/wafcontroller/wafcontroller.go`](https://github.com/megaease/easegress/blob/main/pkg/object/wafcontroller/wafcontroller.go) supports custom ModSecurity rules, OWASP CRS files, full CRS bundles, IP blockers, GeoIP blockers, and rate limiters.
- **Pipeline integration**: The WAF filter in [`pkg/filters/waf/waf.go`](https://github.com/megaease/easegress/blob/main/pkg/filters/waf/waf.go) forwards requests to the global controller via `Handle(ctx, ruleGroupName)` and returns results (`ok`, `blocked`, `error`) that control request flow.
- **Observability**: Built-in Prometheus metrics in [`pkg/object/wafcontroller/metrics/metrics.go`](https://github.com/megaease/easegress/blob/main/pkg/object/wafcontroller/metrics/metrics.go) track refused requests and rule group performance.

## Frequently Asked Questions

### What rule formats does the Easegress WAF support?

Easegress WAF supports **ModSecurity/Coraza** syntax through the `customRules` field, allowing you to write inline SecRule directives. It also natively supports the **OWASP Core Rule Set (CRS)** via the `owaspRules` list for specific files or `loadOwaspCrs: true` for the complete bundle. Additionally, you can configure IP/CIDR blocking and GeoIP country filtering without writing ModSecurity rules.

### How do I troubleshoot blocked requests in Easegress WAF?

When the WAF filter blocks a request, it returns the `blocked` result and sets an HTTP 500 response with a JSON error body containing the rule message, as implemented in `setErrResponse` within [`pkg/filters/waf/waf.go`](https://github.com/megaease/easegress/blob/main/pkg/filters/waf/waf.go). To troubleshoot, check the Easegress logs for Coraza engine output and monitor the `waf_total_refused_requests` Prometheus metric exposed by [`pkg/object/wafcontroller/metrics/metrics.go`](https://github.com/megaease/easegress/blob/main/pkg/object/wafcontroller/metrics/metrics.go) to identify which rule groups are triggering blocks.

### Can I use multiple rule groups in a single pipeline?

Yes, you can chain multiple WAF filters in a single pipeline, each referencing a different rule group from the same WAFController. For example, you might place a filter using an `ipBlocker` rule group first, followed by a filter using an `owaspRules` group for application-layer attacks. Each filter independently calls `wafcontroller.GetGlobalWAFController().Handle()` with its specified `ruleGroup` parameter, allowing you to layer security policies.

### What is the performance impact of enabling WAF in Easegress?

The WAF filter introduces minimal overhead because it leverages the high-performance Coraza WAF engine written in Go. The `WAFController` caches compiled rule engines in memory, so [`pkg/object/wafcontroller/wafcontroller.go`](https://github.com/megaease/easegress/blob/main/pkg/object/wafcontroller/wafcontroller.go) does not re-parse rules on each request. However, complex ModSecurity rules with extensive regex patterns or large OWASP CRS bundles may increase latency slightly; monitor the `waf_total_refused_requests` and request duration metrics to assess impact in your specific deployment.