|
| 1 | +# Web Application Firewall <!-- omit from toc --> |
| 2 | + |
| 3 | + |
| 4 | +- [Introduction](#introduction) |
| 5 | +- [Configuring Web Application Firewall](#configuring-web-application-firewall) |
| 6 | + - [Custom](#custom) |
| 7 | + - [OWASP Core Rule Set](#owasp-core-rule-set) |
| 8 | + - [IP Blocker](#ip-blocker) |
| 9 | + - [Whitelist Mode](#whitelist-mode) |
| 10 | + - [Blacklist Mode](#blacklist-mode) |
| 11 | + - [Combined Mode (Whitelist \& Blacklist)](#combined-mode-whitelist--blacklist) |
| 12 | + - [GEO IP Blocker](#geo-ip-blocker) |
| 13 | + - [Whitelist Mode (allowedCountries)](#whitelist-mode-allowedcountries) |
| 14 | + - [Blacklist Mode (deniedCountries)](#blacklist-mode-deniedcountries) |
| 15 | + - [Rate Limiter](#rate-limiter) |
| 16 | +- [Observability](#observability) |
| 17 | + |
| 18 | + |
| 19 | +## Introduction |
| 20 | + |
| 21 | +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. |
| 22 | + |
| 23 | +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. |
| 24 | + |
| 25 | +## Configuring Web Application Firewall |
| 26 | + |
| 27 | +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. |
| 28 | + |
| 29 | +```yaml |
| 30 | +name: waf-controller |
| 31 | +kind: WAFController |
| 32 | +ruleGroups: |
| 33 | +- name: sqlinjection |
| 34 | + rules: |
| 35 | + customRules: | |
| 36 | + // https://github.com/corazawaf/coraza-coreruleset/blob/main/rules/%40crs-setup.conf.example |
| 37 | + // check coraza core rule set recommend setup file |
| 38 | + owaspRules: |
| 39 | + - REQUEST-901-INITIALIZATION.conf |
| 40 | + - REQUEST-942-APPLICATION-ATTACK-SQLI.conf |
| 41 | + - REQUEST-949-BLOCKING-EVALUATION.conf |
| 42 | + |
| 43 | +------ |
| 44 | + |
| 45 | +name: waf-server |
| 46 | +kind: HTTPServer |
| 47 | +port: 10080 |
| 48 | +rules: |
| 49 | +- paths: |
| 50 | + - pathPrefix: / |
| 51 | + backend: waf-pipeline |
| 52 | + |
| 53 | +----- |
| 54 | + |
| 55 | +name: waf-pipeline |
| 56 | +kind: Pipeline |
| 57 | +filters: |
| 58 | +- name: waf-filter |
| 59 | + kind: WAF |
| 60 | + ruleGroup: sqlinjection |
| 61 | +- name: proxy |
| 62 | + kind: Proxy |
| 63 | + pools: |
| 64 | + - servers: |
| 65 | + - url: http://127.0.0.1:9095 |
| 66 | + - url: http://127.0.0.1:9096 |
| 67 | + loadBalance: |
| 68 | + policy: roundRobin |
| 69 | +``` |
| 70 | +
|
| 71 | +It will do following things: |
| 72 | +
|
| 73 | +1. Loads a minimal, SQLi-focused subset of the OWASP CRS: |
| 74 | + - 901: Initialization and variable setup |
| 75 | + - 942: SQL Injection detection |
| 76 | + - 949: Final blocking evaluation |
| 77 | +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. |
| 78 | +
|
| 79 | +### Custom |
| 80 | +
|
| 81 | +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. |
| 82 | + |
| 83 | +```yaml |
| 84 | +name: waf-controller |
| 85 | +kind: WAFController |
| 86 | +ruleGroups: |
| 87 | +- name: sqlinjection |
| 88 | + rules: |
| 89 | + loadOwaspCrs: true |
| 90 | + customRules: | |
| 91 | + SecRule REQUEST_METHOD "POST" "id:1000001,phase:1,block,log,msg:'Block all POST requests (phase 1)',severity:'CRITICAL'" |
| 92 | + SecRule REQUEST_METHOD "POST" "id:1000002,phase:2,block,log,msg:'Block all POST requests (phase 2)',severity:'CRITICAL'" |
| 93 | +``` |
| 94 | + |
| 95 | +What this does: |
| 96 | + |
| 97 | +- `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). |
| 98 | +- `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/) |
| 99 | + |
| 100 | +Feel free to add your own rules as needed. |
| 101 | + |
| 102 | +### OWASP Core Rule Set |
| 103 | + |
| 104 | +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). |
| 105 | + |
| 106 | +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. |
| 107 | + |
| 108 | +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. |
| 109 | + |
| 110 | +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. |
| 111 | + |
| 112 | +```yaml |
| 113 | +name: waf-controller |
| 114 | +kind: WAFController |
| 115 | +ruleGroups: |
| 116 | +- name: sqlinjection |
| 117 | + rules: |
| 118 | + customRules: | |
| 119 | + // https://github.com/corazawaf/coraza-coreruleset/blob/main/rules/%40crs-setup.conf.example |
| 120 | + // The crs-setup.conf file is required for CRS to function. |
| 121 | + // This is a minimal example; a full setup file offers more customization. |
| 122 | + SecRequestBodyAccess On |
| 123 | + SecDefaultAction "phase:1,log,auditlog,pass" |
| 124 | + SecDefaultAction "phase:2,log,auditlog,pass" |
| 125 | + SecAction \ |
| 126 | + "id:900990,\ |
| 127 | + phase:1,\ |
| 128 | + pass,\ |
| 129 | + t:none,\ |
| 130 | + nolog,\ |
| 131 | + tag:'OWASP_CRS',\ |
| 132 | + ver:'OWASP_CRS/4.16.0',\ |
| 133 | + setvar:tx.crs_setup_version=4160" |
| 134 | + owaspRules: |
| 135 | + - REQUEST-901-INITIALIZATION.conf |
| 136 | + - REQUEST-913-SCANNER-DETECTION.conf |
| 137 | + - REQUEST-921-PROTOCOL-ATTACK.conf |
| 138 | + - REQUEST-922-MULTIPART-ATTACK.conf |
| 139 | + - REQUEST-949-BLOCKING-EVALUATION.conf |
| 140 | +``` |
| 141 | + |
| 142 | +For all rules, please check [here](https://github.com/corazawaf/coraza-coreruleset/tree/main/rules/%40owasp_crs). |
| 143 | + |
| 144 | +### IP Blocker |
| 145 | + |
| 146 | +The `ipBlocker` rule filters requests based on the source IP address, specified in `CIDR` format. |
| 147 | + |
| 148 | +#### Whitelist Mode |
| 149 | + |
| 150 | +Logic: Allows requests only from IPs on the list. All others are blocked. |
| 151 | + |
| 152 | +```yaml |
| 153 | +kind: WAFController |
| 154 | +name: waf-controller |
| 155 | +ruleGroups: |
| 156 | + - name: ipblocker |
| 157 | + rules: |
| 158 | + ipBlocker: |
| 159 | + whitelist: |
| 160 | + - 136.252.0.2/32 |
| 161 | +``` |
| 162 | + |
| 163 | +#### Blacklist Mode |
| 164 | + |
| 165 | +Logic: Blocks requests from IPs on the list. All others are allowed. |
| 166 | + |
| 167 | +```yaml |
| 168 | +kind: WAFController |
| 169 | +name: waf-controller |
| 170 | +ruleGroups: |
| 171 | + - name: ipblocker |
| 172 | + rules: |
| 173 | + ipBlocker: |
| 174 | + blacklist: |
| 175 | + - 158.160.2.1/32 |
| 176 | +``` |
| 177 | + |
| 178 | +#### Combined Mode (Whitelist & Blacklist) |
| 179 | + |
| 180 | +Logic: Blocks request if IP is in blacklist OR not in whitelist. |
| 181 | + |
| 182 | +```yaml |
| 183 | +kind: WAFController |
| 184 | +name: waf-controller |
| 185 | +ruleGroups: |
| 186 | + - name: ipblocker |
| 187 | + rules: |
| 188 | + ipBlocker: |
| 189 | + whitelist: |
| 190 | + - 136.252.0.2/32 |
| 191 | + blacklist: |
| 192 | + - 158.160.2.1/32 |
| 193 | +``` |
| 194 | + |
| 195 | +### GEO IP Blocker |
| 196 | + |
| 197 | +The `geoIPBlocker` rule allows or denies requests based on the visitor's country of origin. It requires a GeoIP database to function. |
| 198 | + |
| 199 | +- `dbPath`: The file path to your GeoIP database (.mmdb file). |
| 200 | +- `dbUpdateCron`: (Optional) A cron expression to schedule automatic updates for the database. |
| 201 | +- `Country Codes`: Use standard two-letter ISO codes (e.g., US, CN). |
| 202 | + |
| 203 | +#### Whitelist Mode (allowedCountries) |
| 204 | + |
| 205 | +Logic: Only allows requests from the specified countries. All other countries will be blocked. |
| 206 | + |
| 207 | +```yaml |
| 208 | +kind: WAFController |
| 209 | +name: waf-controller |
| 210 | +ruleGroups: |
| 211 | + - name: geoipblocker |
| 212 | + rules: |
| 213 | + geoIPBlocker: |
| 214 | + dbPath: <your-dir>/Country.mmdb |
| 215 | + allowedCountries: |
| 216 | + - XX |
| 217 | +``` |
| 218 | + |
| 219 | +#### Blacklist Mode (deniedCountries) |
| 220 | + |
| 221 | +Logic: Blocks requests from the specified countries. All other countries will be allowed. |
| 222 | + |
| 223 | +```yaml |
| 224 | +kind: WAFController |
| 225 | +name: waf-controller |
| 226 | +ruleGroups: |
| 227 | + - name: geoipblocker |
| 228 | + rules: |
| 229 | + geoIPBlocker: |
| 230 | + dbPath: <your-dir>/Country.mmdb |
| 231 | + dbUpdateCron: "0 0 1 * *" |
| 232 | + deniedCountries: |
| 233 | + - XX |
| 234 | +``` |
| 235 | + |
| 236 | +### Rate Limiter |
| 237 | + |
| 238 | +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. |
| 239 | + |
| 240 | +For detailed configuration, please refer to the official documentation for the built-in Easegress RateLimiter filter [here](./../07.Reference/7.02.Filters.md#ratelimiter). |
| 241 | + |
| 242 | +## Observability |
| 243 | + |
| 244 | +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. |
| 245 | + |
| 246 | +It includes several labels to help you pinpoint the cause of the block: |
| 247 | + |
| 248 | +Common Labels: |
| 249 | + |
| 250 | +- `kind`, `clusterName`, `clusterRole`, `instanceName`: Standard labels to identify the Easegress instance. |
| 251 | + |
| 252 | +Metric-Specific Labels: |
| 253 | + |
| 254 | +- `ruleGroup`: The name of the rule group that blocked the request. |
| 255 | +- `ruleID`: The ID of the specific rule that was triggered. |
| 256 | +- `action`: The WAF action, canbe one of `drop`, `deny`, `redirect`. |
| 257 | + |
| 258 | +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. |
| 259 | + |
| 260 | +For a complete list of all available metrics, please see the [Metrics](../07.Reference/7.08.Metrics.md) reference documentation. |
0 commit comments