How to Configure WAF Rules for Web Application Security in Easegress

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 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) 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.

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:

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:

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
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:

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'"
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:

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
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 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 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 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 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. 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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →