Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
471d1f9
[enhancement] add controller fw
LokiWager Aug 4, 2025
984b77f
[enhancement] imp some methods
LokiWager Aug 4, 2025
db4b362
[enhancement] WIP fw
LokiWager Aug 5, 2025
0448be9
[enhancement] all flow can work with test case
LokiWager Aug 5, 2025
37f5cdb
introduce owasp coreruleset, refactor rules and rulegroup
suchen-sci Aug 6, 2025
7ea8fd8
support waf control without coraza
suchen-sci Aug 6, 2025
c3b7027
[enhancement] refactor
LokiWager Aug 6, 2025
acc3789
[enhancement] add api
LokiWager Aug 6, 2025
165a3a5
add waf process reqesut part
suchen-sci Aug 7, 2025
904526d
fix waf process body bug
suchen-sci Aug 7, 2025
7d1057e
add tests for sql injection and fix waf bugs
suchen-sci Aug 7, 2025
c7ce5b6
add tests for xss attack
suchen-sci Aug 8, 2025
6830615
add tests for remote code exec (RCE) attack
suchen-sci Aug 8, 2025
ca177c3
remove unused codes, add comments
suchen-sci Aug 8, 2025
ea73ba4
add test for protocol attacks
suchen-sci Aug 12, 2025
b6c9909
support ip block for wafcontroller
suchen-sci Aug 12, 2025
a663765
[enhancement] finish api & metrics collection
LokiWager Aug 12, 2025
96f5cfb
add test for bot detection
suchen-sci Aug 13, 2025
e93a706
update ip blocker logic make it more reasonable
suchen-sci Aug 13, 2025
45ae557
refactor rule related codes
suchen-sci Aug 13, 2025
822cff7
add basic logic of geoip blocker
suchen-sci Aug 13, 2025
93366da
[enhancement] add filter
LokiWager Aug 13, 2025
858d793
merge to main
suchen-sci Aug 25, 2025
13129fe
[testing] add basic test case for filter & controller
LokiWager Aug 18, 2025
0d7c2b7
[testing] test case for custom settings
LokiWager Aug 19, 2025
f592d62
test upload file attacks with multipart
suchen-sci Aug 19, 2025
0424c70
[testing] test case for ip blocker
LokiWager Aug 19, 2025
5edaf9f
test local file inclusion attack
suchen-sci Aug 19, 2025
f897732
test generic attacks for waf
suchen-sci Aug 19, 2025
e238637
[testing] test case for geo ip
LokiWager Aug 20, 2025
d0d8e04
add WAF doc of introdution, wafcontroller, waffilter and custom spec
suchen-sci Aug 20, 2025
5feacdd
[testing] refactor
LokiWager Aug 21, 2025
8773a9b
simplify waf setup conf
suchen-sci Aug 21, 2025
f7a40b0
add more docs
suchen-sci Aug 21, 2025
b42754b
add doc for wafcontroller and waf filter
suchen-sci Aug 22, 2025
9555e20
[testing] remove unused conf
LokiWager Aug 25, 2025
137b632
fix race condition in testing
suchen-sci Aug 25, 2025
5bac7ac
fix go version
suchen-sci Aug 25, 2025
d9000b3
fix go mod
suchen-sci Aug 25, 2025
acdda75
try to fix windows path error
suchen-sci Aug 25, 2025
4fa06d7
skip some test on windows since coraza crs not support windows for now
suchen-sci Aug 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 260 additions & 0 deletions docs/03.Advanced-Cookbook/3.14.WAF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
# Web Application Firewall <!-- omit from toc -->


- [Introduction](#introduction)
- [Configuring Web Application Firewall](#configuring-web-application-firewall)
- [Custom](#custom)
- [OWASP Core Rule Set](#owasp-core-rule-set)
- [IP Blocker](#ip-blocker)
- [Whitelist Mode](#whitelist-mode)
- [Blacklist Mode](#blacklist-mode)
- [Combined Mode (Whitelist \& Blacklist)](#combined-mode-whitelist--blacklist)
- [GEO IP Blocker](#geo-ip-blocker)
- [Whitelist Mode (allowedCountries)](#whitelist-mode-allowedcountries)
- [Blacklist Mode (deniedCountries)](#blacklist-mode-deniedcountries)
- [Rate Limiter](#rate-limiter)
- [Observability](#observability)


## Introduction

The Web Application Firewall (WAF) protects your apps by inspecting HTTP(S) traffic and blocking malicious requests at the application layer. It supports standard rule sets like OWASP CRS and flexible custom policies.

Beyond basic request filtering, the WAF includes IP/Geo access control, rate limiting, and rich observability for tuning and incident response. This ensures strong protection with low false positives and clear operational insight.

## Configuring Web Application Firewall

Here is a simple example shows how to configure Easegress to protect your backend using a WAF with a minimal subset of the OWASP Core Rule Set (CRS) focused on SQL Injection (SQLi) detection.

```yaml
name: waf-controller
kind: WAFController
ruleGroups:
- name: sqlinjection
rules:
customRules: |
// https://github.com/corazawaf/coraza-coreruleset/blob/main/rules/%40crs-setup.conf.example
// check coraza core rule set recommend setup file
owaspRules:
- REQUEST-901-INITIALIZATION.conf
- REQUEST-942-APPLICATION-ATTACK-SQLI.conf
- REQUEST-949-BLOCKING-EVALUATION.conf

------

name: waf-server
kind: HTTPServer
port: 10080
rules:
- paths:
- pathPrefix: /
backend: waf-pipeline

-----

name: waf-pipeline
kind: Pipeline
filters:
- name: waf-filter
kind: WAF
ruleGroup: sqlinjection
- name: proxy
kind: Proxy
pools:
- servers:
- url: http://127.0.0.1:9095
- url: http://127.0.0.1:9096
loadBalance:
policy: roundRobin
```

It will do following things:

1. Loads a minimal, SQLi-focused subset of the OWASP CRS:
- 901: Initialization and variable setup
- 942: SQL Injection detection
- 949: Final blocking evaluation
2. Routes traffic to port 10080 through the waf-pipeline, where the WAF filter evaluates requests against the sqlinjection rule group before proxying to your backend pool.

### Custom

This example shows how to load the full OWASP Core Rule Set (CRS) and add your own custom Coraza/ModSecurity rules in Easegress. The example below blocks all POST requests at both `phase 1` and `phase 2` for demonstration purposes.

```yaml
name: waf-controller
kind: WAFController
ruleGroups:
- name: sqlinjection
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'"
```

What this does:

- `loadOwaspCrs`: true loads the full OWASP CRS bundle. You can includes them as you needed. For full rule set, please check: [here](https://github.com/corazawaf/coraza-coreruleset/tree/main/rules/%40owasp_crs).
- `customRules` adds two rules that explicitly block all POST requests. They run in different phases to illustrate the request processing lifecycle. For more details about Coraza/Modsecurity rules please check: [here](https://coraza.io/docs/seclang/)

Feel free to add your own rules as needed.

### OWASP Core Rule Set

This example shows how to use the corazawaf/coraza-coreruleset package to protect your applications. This package provides a straightforward way to embed the official OWASP Core Rule Set (CRS) directly into a Go application using the Coraza Web Application Firewall (WAF).

To effectively use the CRS, a proper setup is essential. This involves including foundational configuration files that define the behavior of both the Coraza engine and the rule set itself.

Coraza Configuration [@coraza.conf-recommended](https://github.com/corazawaf/coraza-coreruleset/blob/main/rules/%40coraza.conf-recommended): This file provides the recommended base settings for the Coraza WAF engine.

CRS Setup [@crs-setup.conf.example](https://github.com/corazawaf/coraza-coreruleset/blob/main/rules/%40crs-setup.conf.example): This file is crucial for customizing the Core Rule Set. Here, you can configure paranoia levels, anomaly score thresholds, and other CRS-specific behaviors. You should copy this file and tailor it to your application's needs.

```yaml
name: waf-controller
kind: WAFController
ruleGroups:
- name: sqlinjection
rules:
customRules: |
// https://github.com/corazawaf/coraza-coreruleset/blob/main/rules/%40crs-setup.conf.example
// The crs-setup.conf file is required for CRS to function.
// This is a minimal example; a full setup file offers more customization.
SecRequestBodyAccess On
SecDefaultAction "phase:1,log,auditlog,pass"
SecDefaultAction "phase:2,log,auditlog,pass"
SecAction \
"id:900990,\
phase:1,\
pass,\
t:none,\
nolog,\
tag:'OWASP_CRS',\
ver:'OWASP_CRS/4.16.0',\
setvar:tx.crs_setup_version=4160"
owaspRules:
- REQUEST-901-INITIALIZATION.conf
- REQUEST-913-SCANNER-DETECTION.conf
- REQUEST-921-PROTOCOL-ATTACK.conf
- REQUEST-922-MULTIPART-ATTACK.conf
- REQUEST-949-BLOCKING-EVALUATION.conf
```

For all rules, please check [here](https://github.com/corazawaf/coraza-coreruleset/tree/main/rules/%40owasp_crs).

### IP Blocker

The `ipBlocker` rule filters requests based on the source IP address, specified in `CIDR` format.

#### Whitelist Mode

Logic: Allows requests only from IPs on the list. All others are blocked.

```yaml
kind: WAFController
name: waf-controller
ruleGroups:
- name: ipblocker
rules:
ipBlocker:
whitelist:
- 136.252.0.2/32
```

#### Blacklist Mode

Logic: Blocks requests from IPs on the list. All others are allowed.

```yaml
kind: WAFController
name: waf-controller
ruleGroups:
- name: ipblocker
rules:
ipBlocker:
blacklist:
- 158.160.2.1/32
```

#### Combined Mode (Whitelist & Blacklist)

Logic: Blocks request if IP is in blacklist OR not in whitelist.

```yaml
kind: WAFController
name: waf-controller
ruleGroups:
- name: ipblocker
rules:
ipBlocker:
whitelist:
- 136.252.0.2/32
blacklist:
- 158.160.2.1/32
```

### GEO IP Blocker

The `geoIPBlocker` rule allows or denies requests based on the visitor's country of origin. It requires a GeoIP database to function.

- `dbPath`: The file path to your GeoIP database (.mmdb file).
- `dbUpdateCron`: (Optional) A cron expression to schedule automatic updates for the database.
- `Country Codes`: Use standard two-letter ISO codes (e.g., US, CN).

#### Whitelist Mode (allowedCountries)

Logic: Only allows requests from the specified countries. All other countries will be blocked.

```yaml
kind: WAFController
name: waf-controller
ruleGroups:
- name: geoipblocker
rules:
geoIPBlocker:
dbPath: <your-dir>/Country.mmdb
allowedCountries:
- XX
```

#### Blacklist Mode (deniedCountries)

Logic: Blocks requests from the specified countries. All other countries will be allowed.

```yaml
kind: WAFController
name: waf-controller
ruleGroups:
- name: geoipblocker
rules:
geoIPBlocker:
dbPath: <your-dir>/Country.mmdb
dbUpdateCron: "0 0 1 * *"
deniedCountries:
- XX
```

### Rate Limiter

The RateLimiter restricts how many requests a client can make within a specific time window (e.g., requests per second). This is a crucial defense against brute-force attacks and helps prevent system overload from excessive traffic.

For detailed configuration, please refer to the official documentation for the built-in Easegress RateLimiter filter [here](./../07.Reference/7.02.Filters.md#ratelimiter).

## Observability

To monitor requests blocked by the WAF, you can use the `waf_total_refused_requests` counter metric exposed to Prometheus. This metric increments every time a request is denied by a WAF rule.

It includes several labels to help you pinpoint the cause of the block:

Common Labels:

- `kind`, `clusterName`, `clusterRole`, `instanceName`: Standard labels to identify the Easegress instance.

Metric-Specific Labels:

- `ruleGroup`: The name of the rule group that blocked the request.
- `ruleID`: The ID of the specific rule that was triggered.
- `action`: The WAF action, canbe one of `drop`, `deny`, `redirect`.

Using these labels, you can create detailed dashboards and alerts, for instance, to track which rules are most active or to identify repeated block events from a specific source.

For a complete list of all available metrics, please see the [Metrics](../07.Reference/7.08.Metrics.md) reference documentation.
79 changes: 72 additions & 7 deletions docs/07.Reference/7.01.Controllers.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- [NacosServiceRegistry](#nacosserviceregistry)
- [AutoCertManager](#autocertmanager)
- [AIGatewayController](#aigatewaycontroller)
- [WAFController](#wafcontroller)
- [Common Types](#common-types)
- [tracing.Spec](#tracingspec)
- [spanlimits.Spec](#spanlimitsspec)
Expand All @@ -47,14 +48,18 @@
- [resilience.Policy](#resiliencepolicy)
- [Retry Policy](#retry-policy)
- [CircuitBreaker Policy](#circuitbreaker-policy)
- [aigatewaycontroller.ProviderSpec](#aigatewaycontrollerproviderspec)
- [AIGatewayController.ProviderSpec](#aigatewaycontrollerproviderspec)
- [Supported Providers](#supported-providers)
- [aigatewaycontroller.MiddlewareSpec](#aigatewaycontrollermiddlewarespec)
- [aigatewaycontroller.SemanticCacheSpec](#aigatewaycontrollersemanticcachespec)
- [aigatewaycontroller.EmbeddingSpec](#aigatewaycontrollerembeddingspec)
- [aigatewaycontroller.VectorDBSpec](#aigatewaycontrollervectordbspec)
- [aigatewaycontroller.RedisSpec](#aigatewaycontrollerredisspec)
- [aigatewaycontroller.PostgresSpec](#aigatewaycontrollerpostgresspec)
- [AIGatewayController.MiddlewareSpec](#aigatewaycontrollermiddlewarespec)
- [AIGatewayController.SemanticCacheSpec](#aigatewaycontrollersemanticcachespec)
- [AIGatewayController.EmbeddingSpec](#aigatewaycontrollerembeddingspec)
- [AIGatewayController.VectorDBSpec](#aigatewaycontrollervectordbspec)
- [AIGatewayController.RedisSpec](#aigatewaycontrollerredisspec)
- [AIGatewayController.PostgresSpec](#aigatewaycontrollerpostgresspec)
- [WAFController.RuleGroupSpec](#wafcontrollerrulegroupspec)
- [WAFController.RuleSpec](#wafcontrollerrulespec)
- [WAFController.IPBlockerSpec](#wafcontrolleripblockerspec)
- [WAFController.GeoIPBlockerSpec](#wafcontrollergeoipblockerspec)

As the [architecture diagram](../imgs/architecture.png) shows, the controller is the core entity to control kinds of working. There are two kinds of controllers overall:

Expand Down Expand Up @@ -627,6 +632,37 @@ version: easegress.megaease.com/v2
| providers | [][ProviderSpec](#aigatewaycontrollerproviderspec) | List of AI providers configuration | No |
| middlewares | [][MiddlewareSpec](#aigatewaycontrollermiddlewarespec) | List of middleware configuration for request processing | No |


### WAFController

```yaml
name: waf-controller
kind: WAFController
ruleGroups:
- name: sqlinjection
rules:
customRules: |
// https://github.com/corazawaf/coraza-coreruleset/blob/main/rules/%40crs-setup.conf.example
// check coraza core rule set recommend setup file
owaspRules:
- REQUEST-901-INITIALIZATION.conf
- REQUEST-942-APPLICATION-ATTACK-SQLI.conf
- REQUEST-949-BLOCKING-EVALUATION.conf
- name: geoipblocker
rules:
geoIPBlocker:
dbPath: <your-dir>/Country.mmdb
dbUpdateCron: "0 0 1 * *"
deniedCountries:
- XX
```


| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
|ruleGroups | [][RuleGroupSpec](#wafcontrollerrulegroupspec) | A list of configurations for one or more WAF rule groups. | Yes |


## Common Types

### tracing.Spec
Expand Down Expand Up @@ -1002,3 +1038,32 @@ The providerType can be one of the following:
| Name | Type | Description | Required |
| ------------- | ------ | ------------------------------ | -------- |
| connectionURL | string | PostgreSQL connection URL | Yes |

### WAFController.RuleGroupSpec
| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
| name | string | A unique name for the rule group. | Yes |
| loadOwaspCrs | bool | Indicates whether to load the OWASP Core Rule Set. For more details, please check Coraza CRS. | No |
| rules | [RuleSpec](#wafcontrollerrulespec) | Defines the specific rules included in this rule group. | Yes |

### WAFController.RuleSpec
| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
| owaspRules | []string | Defines the OWASP rules to be applied. See the examples at Coraza CRS for more details. | No |
| customRules | string | Defines custom WAF rules. | No |
| ipBlocker | [IPBlockerSpec](#wafcontrolleripblockerspec) | Defines access control rules based on IP addresses (whitelist/blacklist). | No |
| geoIPBlocker | [GeoIPBlockerSpec](#wafcontrollergeoipblockerspec) | Defines access control rules based on geolocation (GeoIP). | No |

### WAFController.IPBlockerSpec
| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
| whitelist | []string | A list of IP addresses that are allowed access. | No |
| blacklist | []string | A list of IP addresses that are denied access. | No |

### WAFController.GeoIPBlockerSpec
| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
| dbPath | string | The file path to the GeoIP database. | Yes |
| dbUpdateCron | string | A cron expression for automatically updating the GeoIP database on a schedule. | No |
| allowedCountries | []string | A list of country codes (e.g., "US", "CN") that are allowed access. | No |
| deniedCountries | []string | A list of country codes that are denied access. | No|
Loading
Loading