Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
---
id: advanced_deployments
title: WAF Deployment Strategies
sidebar_position: 6
---

# WAF Deployment Strategies

This guide covers advanced CrowdSec WAF deployment strategies for organizations looking to gradually enhance their web application security posture. Learn how to progressively improve your WAF configuration from basic virtual patching to comprehensive multi-layer protection.

:::info Prerequisites
This guide assumes you have completed the [General Setup](/appsec/quickstart/general.mdx) and have a functional basic WAF deployment.
:::

You can read more about the CrowdSec WAF CRS support in the [dedicated documentation](/appsec/crs/intro.md)

## Security Enhancement Path

CrowdSec WAF supports multiple deployment strategies that can be implemented progressively:

### 1. Basic Virtual Patching (Quickstart)

**Current State**: Blocking protection against known CVEs

- Collections: [`crowdsecurity/appsec-virtual-patching`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-virtual-patching)
- Mode: In-band (blocking)
- Coverage: Known vulnerabilities only
- False Positives: Minimal

### 2. Enhanced Detection (Out-of-band CRS)

**Next Step**: Add comprehensive attack detection without performance impact

- Add: [`crowdsecurity/appsec-crs`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-crs) (out-of-band) alongside existing virtual patching
- Mode: Non-blocking analysis + behavioral banning
- Coverage: OWASP Top 10 + comprehensive attack patterns + specific CVE protection
- Performance: No latency impact ⚡
- Security: Layered approach - virtual patching + generic attack detection

### 3. Maximum Protection (In-band CRS)

**Advanced**: Full blocking protection with comprehensive coverage

- Modify: Use [`crowdsecurity/appsec-crs-inband`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-crs-inband) for blocking CRS while keeping virtual patching
- Mode: Immediate blocking of all detected attacks (both generic and CVE-specific)
- Coverage: Maximum protection with instant response 🛡️
- Security: Dual-layer blocking - virtual patching handles specific vulnerabilities, CRS covers generic attack patterns
- Consideration: Might require tuning to minimize false positives

You will most likely also need to configure the CRS themselves to tune out potential false positives.
You can do by using either official or custom CRS plugins, you can refer to [this documentation](/appsec/crs/plugin_support.md) for a general plugin overview and [this page](/appsec/crs/customization.md) for some examples.

## Implementation Guide

### Adding Out-of-band CRS

Enhance your existing virtual patching deployment by adding comprehensive attack detection as an additional security layer:

```bash title="Install CRS collection"
sudo cscli collections install crowdsecurity/appsec-crs
```

The [`crowdsecurity/appsec-crs`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-crs) collection includes:

- **crowdsecurity/crs**: AppSec config that loads CRS rules in out-of-band mode
- **crowdsecurity/crowdsec-appsec-outofband**: Scenario that bans IPs after 5+ out-of-band rule violations

Update your WAF acquisition configuration to include both rule sets:

```yaml title="/etc/crowdsec/acquis.d/appsec.yaml"
appsec_configs:
- crowdsecurity/appsec-default # Virtual patching rules (in-band blocking)
- crowdsecurity/crs # OWASP CRS rules (out-of-band detection)
labels:
type: appsec
listen_addr: 127.0.0.1:7422
source: appsec
name: myAppSecComponent
```

```bash title="Restart CrowdSec"
sudo systemctl restart crowdsec
```

**Benefits of this layered configuration:**

- **Layer 1**: Immediate protection against known vulnerabilities (virtual patching)
- **Layer 2**: Comprehensive attack pattern detection (CRS out-of-band)
- **Complementary Coverage**: Virtual patching rules catch specific CVEs that CRS generic rules might miss
- Behavioral analysis and repeat offender banning
- No performance impact on legitimate traffic

#### How to Test Out-of-band CRS Detection

After implementing the layered configuration, verify both protection layers are working correctly:

**Test 1: Virtual Patching Layer (Immediate Blocking)**

Test that virtual patching rules block requests immediately by trying to access sensitive files:

```bash
# Test .env file access (common vulnerability)
curl -v "http://your-app.com/.env"
curl -v "http://your-app.com/api/../.env"
```

Expected result: These requests should be immediately blocked with HTTP 403 Forbidden.

**Test 2: CRS Out-of-band Detection Layer**

The `crowdsecurity/crs` collection brings general detection for OWASP top10 attacks, which can be tested:

```bash
# Replace with your application URL
TARGET="http://your-app.com"

# SQL injection attempts (trigger multiple CRS rules)
curl "$TARGET/?id=1'+OR+'1'='1"
```

Expected results:

- Detailed Alert is created (see `cscli alerts list`)

<details>
<summary>`cscli alerts list` output</summary>

```yaml
+-------+--------------------+--------------------------------------------------------------+---------+------------------------------+-----------+----------------------+
| ID | value | reason | country | as | decisions | created_at |
+-------+--------------------+--------------------------------------------------------------+---------+------------------------------+-----------+----------------------+
| 62419 | Ip:xxx.xx.xx.xx | anomaly score out-of-band: sql_injection: 10, anomaly: 10, | FR | 5410 Bouygues Telecom SA | | 2025-09-09T14:41:07Z |
...
```

</details>

- Detailed Alert is visible in console

<details>
<summary>Alert Console view</summary>
![timeline](/img/console-appsec-oob.png)
</details>

**Test 3: Verify Scenario Behavior**

The `crowdsecurity/crowdsec-appsec-outofband` scenario will ban IPs triggering the CRS on more than 5 distinct requests on a short period, which can be tested:

```bash
for i in {1..6}; do curl "$TARGET/?id=1'+OR+'1'='1"; done
```

Expected results:

- Alerts are created for each request
- Decision is created by the 6th request

<details>
<summary>`cscli alerts list` output</summary>

```yaml
───────┬────────────────────┬──────────────────────────────────────────────────────────────┬─────────┬──────────────────────────────┬───────────┬──────────────────────╮
│ ID │ value │ reason │ country │ as │ decisions │ created_at │
├───────┼────────────────────┼──────────────────────────────────────────────────────────────┼─────────┼──────────────────────────────┼───────────┼──────────────────────┤
│ 62427 │ Ip:xxx.xx.xx.xx │ crowdsecurity/crowdsec-appsec-outofband │ FR │ 5410 Bouygues Telecom SA │ ban:1 │ 2025-09-09T14:51:11Z │
│ 62426 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:12Z │
│ 62425 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:11Z │
│ 62424 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:11Z │
│ 62423 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:11Z │
│ 62422 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:11Z │
│ 62421 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:11Z │

```

</details>

### CRS In-band (Blocking Mode)

For organizations requiring maximum protection, configure CRS rules to block requests immediately by installing the in-band CRS collection:

```bash title="Install CRS in-band collection"
sudo cscli collections install crowdsecurity/appsec-crs-inband
```

:::info

In order to avoid potential false positives, you can also install a CRS exclusion rules plugin from the hub or write a custom one.

Refer to [this documentation](/appsec/crs/plugin_support.md) for a general plugin overview and [this page](/appsec/crs/customization.md) for instruction on how to write a custom plugin.

:::

#### Update Acquisition Configuration

Modify your acquisition to use the in-band CRS configuration:

```yaml title="/etc/crowdsec/acquis.d/appsec.yaml"
appsec_configs:
- crowdsecurity/appsec-default # Virtual patching rules (in-band blocking)
- crowdsecurity/crs-inband # OWASP CRS rules (in-band blocking)
labels:
type: appsec
listen_addr: 127.0.0.1:7422
source: appsec
name: myAppSecComponent
```

```bash title="Restart CrowdSec"
sudo systemctl restart crowdsec
```

#### How to Test CRS In-band Blocking

After configuring CRS for in-band (blocking) mode, test that both virtual patching and CRS rules provide immediate blocking:

**Test 1: Virtual Patching Layer (Still Blocking)**

Verify virtual patching continues to work:

```bash
# These should still be immediately blocked
curl -v "http://your-app.com/.env"
```

Expected result: HTTP 403 Forbidden immediately.

**Test 2: CRS In-band Blocking**

Test that CRS rules now block requests immediately (no more out-of-band delay):

```bash
TARGET="http://your-app.com"

# SQL injection - should be blocked immediately
curl -v "$TARGET/?id=1' OR '1'='1"

# XSS - should be blocked immediately
curl -v "$TARGET/?q=<script>alert('xss')</script>"

# Command injection - should be blocked immediately
curl -v "$TARGET/?cmd=; cat /etc/passwd"

# Path traversal - should be blocked immediately
curl -v "$TARGET/?file=../../../etc/passwd"
```

**Expected behavior:**

- **All requests above**: Immediately blocked with HTTP 403 Forbidden
- **No delay**: Unlike out-of-band mode, blocking is instant
- **Dual protection**: Both virtual patching AND CRS rules provide immediate blocking

:::warning Important Considerations
In-band CRS blocking provides maximum protection but requires:

- **Thorough testing** in a staging environment
- **Gradual rollout** to production traffic
- **Monitoring and tuning** to prevent blocking legitimate requests
- **Whitelisting capabilities** for false positives
:::

## Next Steps

Once you've implemented advanced deployments:

- Configure [Custom Rules](create_rules.md) for application-specific protection
- Set up [Hooks](hooks.md) for custom response actions
- Explore [Configuration Options](configuration.md) for fine-tuning
- Review [Troubleshooting Guide](troubleshooting.md) for operational issues
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The [`crowdsecurity/appsec-logs` parser](https://app.crowdsec.net/hub/author/cro

### Triggering on _In-Band_ Rules

A simple yexample is the [`crowdsecurity/appsec-vpatch` scenario](https://app.crowdsec.net/hub/author/crowdsecurity/configurations/appsec-vpatch) that will ban IPs triggering two distinct _In-Band_ rules:
A simple example is the [`crowdsecurity/appsec-vpatch` scenario](https://app.crowdsec.net/hub/author/crowdsecurity/configurations/appsec-vpatch) that will ban IPs triggering two distinct _In-Band_ rules:

```yaml title="/etc/crowdsec/scenarios/appsec-vpatch.yaml"
type: leaky
Expand Down
110 changes: 110 additions & 0 deletions crowdsec-docs/versioned_docs/version-v1.7/appsec/benchmark.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ sidebar_position: 80

-->

# Basic Benchmark

The Application Security Component benchmarks were run on an AWS EC2 instance `t2.medium` (2vCPU/4GiB RAM).

All benchmarks were run with a single `routine` configured for the Application Security Component.
Expand Down Expand Up @@ -63,3 +65,111 @@ On the system, we deployed:

![15 concurrent connections / 1000 requests](/img/appsec/bench/big_post_appsec_one_routine_15_1000.png)
-->

# Stress Test

This test was run on a `c5a.4xlarge` EC2 instance (16CPU/32GiB RAM).

Tested versions are:

- Openresty `v1.27.1.2`
- CrowdSec `v1.7.0`
- cs-openresty-bouncer `v1.1.2`

Openresty was configured to not log anything and forward requests to a Go backend that always returns 200, to improve raw throughput and avoid disk access limits.

CrowdSec WAF was configured with 16 routines to make use of as much CPU as possible.

All tests were simulating 400 concurrent users, making requests as quickly as possible during 1 minute.

Except for the baseline, all values in the tables are shown as a delta from the baseline performance.

## Baseline

This test was run without loading the Openresty bouncer to get a baseline throughput of the system.

### GET Requests

| Metric | Value |
| --------------------- | -------- |
| Average Response Time | 23.55ms |
| Minimum Response Time | 21.24ms |
| Median Response Time | 23.18ms |
| Maximum Response Time | 255.16ms |
| P90 Response Time | 24.72ms |

### 10% POST Requests

| Metric | Value |
| --------------------- | -------- |
| Average Response Time | 25.08ms |
| Minimum Response Time | 21.29ms |
| Median Response Time | 23.95ms |
| Maximum Response Time | 331.08ms |
| P90 Response Time | 30.95ms |

## Virtual Patching Rules

### GET Requests - 10% malicious - InBand

| Metric | Delta |
| --------------------- | -------- |
| Average Response Time | +4.94ms |
| Minimum Response Time | +0.93ms |
| Median Response Time | +3.48ms |
| Maximum Response Time | +6.83ms |
| P90 Response Time | +10.13ms |

### Realistic Traffic - 70% GET - 25% POST - 5% malicious - Inband

| Metric | Delta |
| --------------------- | ------- |
| Average Response Time | +4.03ms |
| Minimum Response Time | +0.71ms |
| Median Response Time | +2.36ms |
| Maximum Response Time | +6.79ms |
| P90 Response Time | +8.07ms |

## CRS

### GET Requests - 10% malicious - InBand

| Metric | Delta |
| --------------------- | -------- |
| Average Response Time | +32.85ms |
| Minimum Response Time | +2.21ms |
| Median Response Time | +27.47ms |
| Maximum Response Time | -64.45ms |
| P90 Response Time | +58.19ms |

### POST Requests - 10% malicious - InBand

| Metric | Delta |
| --------------------- | --------- |
| Average Response Time | +58.49ms |
| Minimum Response Time | +3.18ms |
| Median Response Time | +54.1ms |
| Maximum Response Time | -106.76ms |
| P90 Response Time | +83.01ms |

### Realistic Traffic - 70% GET - 25% POST - 5% malicious - Inband

| Metric | Delta |
| --------------------- | -------- |
| Average Response Time | +32.54ms |
| Minimum Response Time | +1.87ms |
| Median Response Time | +28.36ms |
| Maximum Response Time | -68.34ms |
| P90 Response Time | +53.83ms |

## Virtual Patching Inband + CRS Out-of-band

### Realistic Traffic - 70% GET - 25% POST - 5% malicious

| Metric | Delta |
| --------------------- | --------- |
| Average Response Time | +30.5ms |
| Minimum Response Time | +1.56ms |
| Median Response Time | +26.26ms |
| Maximum Response Time | -101.66ms |
| P90 Response Time | +51.18ms |
Loading
Loading