Skip to content
Closed
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
e66005e
[enhancement] add controller fw
LokiWager Aug 4, 2025
f50065e
[enhancement] imp some methods
LokiWager Aug 4, 2025
cf7ba4a
[enhancement] WIP fw
LokiWager Aug 5, 2025
c3b8804
[enhancement] all flow can work with test case
LokiWager Aug 5, 2025
658fedd
introduce owasp coreruleset, refactor rules and rulegroup
suchen-sci Aug 6, 2025
503e962
support waf control without coraza
suchen-sci Aug 6, 2025
ece5857
[enhancement] refactor
LokiWager Aug 6, 2025
26c23bc
[enhancement] add api
LokiWager Aug 6, 2025
d2e72bd
add waf process reqesut part
suchen-sci Aug 7, 2025
dfc90df
fix waf process body bug
suchen-sci Aug 7, 2025
3bcf2a2
add tests for sql injection and fix waf bugs
suchen-sci Aug 7, 2025
c8e902b
add tests for xss attack
suchen-sci Aug 8, 2025
65961b7
add tests for remote code exec (RCE) attack
suchen-sci Aug 8, 2025
ce31419
remove unused codes, add comments
suchen-sci Aug 8, 2025
c23b235
add test for protocol attacks
suchen-sci Aug 12, 2025
3d9ff67
support ip block for wafcontroller
suchen-sci Aug 12, 2025
ebe277e
[enhancement] finish api & metrics collection
LokiWager Aug 12, 2025
c96a220
add test for bot detection
suchen-sci Aug 13, 2025
bdb0044
update ip blocker logic make it more reasonable
suchen-sci Aug 13, 2025
7367928
refactor rule related codes
suchen-sci Aug 13, 2025
a1f9e2a
add basic logic of geoip blocker
suchen-sci Aug 13, 2025
9df0005
[enhancement] add filter
LokiWager Aug 13, 2025
41d6d78
add cron job to update geoip data
suchen-sci Aug 15, 2025
f06c608
[testing] add basic test case for filter & controller
LokiWager Aug 18, 2025
8eac790
[testing] test case for custom settings
LokiWager Aug 19, 2025
90a3fd3
test upload file attacks with multipart
suchen-sci Aug 19, 2025
26a7ab1
[testing] test case for ip blocker
LokiWager Aug 19, 2025
3c6303f
test local file inclusion attack
suchen-sci Aug 19, 2025
bfbf6c2
test generic attacks for waf
suchen-sci Aug 19, 2025
d2868fd
[testing] test case for geo ip
LokiWager Aug 20, 2025
fc9c68e
add WAF doc of introdution, wafcontroller, waffilter and custom spec
suchen-sci Aug 20, 2025
19e712d
[testing] refactor
LokiWager Aug 21, 2025
6e9edca
simplify waf setup conf
suchen-sci Aug 21, 2025
105101c
add more docs
suchen-sci Aug 21, 2025
1146e9c
add doc for wafcontroller and waf filter
suchen-sci Aug 22, 2025
485dbc4
Merge branch 'main' into waf
suchen-sci Aug 25, 2025
5903705
fix go.mod conflict
suchen-sci Aug 25, 2025
7b7e9da
[testing] remove unused conf
LokiWager Aug 25, 2025
ebbcf8f
[cilint] fix go vet new intruduced ci lint about printf
suchen-sci Aug 25, 2025
aa4db17
fix race condition in testing
suchen-sci Aug 25, 2025
40b5a08
fix go version
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