Skip to content

Commit 5033bd7

Browse files
enhance: add haproxy spoa to appsec getting started (#1011)
1 parent e966471 commit 5033bd7

4 files changed

Lines changed: 164 additions & 4 deletions

File tree

crowdsec-docs/docs/appsec/intro.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ The component uses existing remediation hooks in web servers and reverse proxies
4141
3. The engine evaluates the request against AppSec rules (in-band rules can block immediately).
4242
4. Based on the result, the web server either blocks the request or processes it as usual.
4343

44+
### One WAF, many web servers
45+
46+
The AppSec Component lives in the **CrowdSec Security Engine**, so you get a single “source of truth” for:
47+
- AppSec configurations and rules (collections from the Hub)
48+
- logging, alerting, and Console visibility
49+
50+
This makes it easy to protect **multiple web servers / reverse proxies** with one CrowdSec instance: each remediation component forwards requests to the same AppSec `listen_addr`.
51+
52+
Compared to WAFs embedded directly inside each web server, you don’t have to duplicate rule and configuration updates across multiple locations: update the rules once in CrowdSec, and every connected remediation component benefits.
53+
4454
:::tip Common gotchas
4555
- Installing rules is not enough: you must also enable the AppSec acquisition datasource and restart CrowdSec.
4656
- The remediation component must support AppSec forwarding, and must be configured to forward to the same `listen_addr` you set in the acquisition file.
@@ -71,14 +81,11 @@ The AppSec Component works seamlessly with modern web servers and reverse proxie
7181
<a href="quickstart/traefik">Quick Start Guide →</a>
7282
</div>
7383

74-
{/* HAProxy support coming soon - uncomment when feature is released */}
75-
{/*
7684
<div style={{display: 'flex', flexDirection: 'column', gap: '12px', padding: '16px', border: '1px solid #e5e7eb', borderRadius: '8px', alignItems: 'center', textAlign: 'center'}}>
7785
<img src="/img/haproxy-logo.png" alt="HAProxy" style={{height: '50px', objectFit: 'contain'}} />
7886
<strong>HAProxy</strong>
79-
<a href="https://hub.crowdsec.net/browse/#remediation-components">Hub Component →</a>
87+
<a href="quickstart/haproxy_spoa">Quick Start Guide →</a>
8088
</div>
81-
*/}
8289

8390
<div style={{display: 'flex', flexDirection: 'column', gap: '12px', padding: '16px', border: '1px solid #e5e7eb', borderRadius: '8px', alignItems: 'center', textAlign: 'center'}}>
8491
<img src="/img/WordPress-logotype-wmark.png" alt="WordPress" style={{height: '50px', objectFit: 'contain'}} />
@@ -128,6 +135,7 @@ You can follow our quick start guides depending on your web server:
128135

129136
- [Nginx/OpenResty](quickstart/nginxopenresty)
130137
- [Traefik](quickstart/traefik)
138+
- [HAProxy (SPOA)](quickstart/haproxy_spoa)
131139
- [WordPress](quickstart/wordpress)
132140
- [CrowdSec WAF with Nginx Reverse Proxy](/u/user_guides/waf_rp_howto)
133141

crowdsec-docs/docs/appsec/quickstart/general.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ Now that the AppSec Component is configured and running, you need to:
146146
For specific remediation component configuration, see:
147147
- [Nginx/OpenResty Setup](nginxopenresty.mdx)
148148
- [Traefik Setup](traefik.mdx)
149+
- [HAProxy (SPOA) Setup](haproxy_spoa.mdx)
149150
- [WordPress Setup](wordpress.mdx)
150151
- [Check the hub for other remediation components supporting AppSec](https://app.crowdsec.net/hub/remediation-components)
151152

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
---
2+
id: haproxy_spoa
3+
title: QuickStart - HAProxy (SPOA)
4+
---
5+
6+
import UnderlineTooltip from '@site/src/components/underline-tooltip';
7+
8+
# CrowdSec WAF QuickStart for HAProxy (SPOA)
9+
10+
## Objectives
11+
12+
Set up the [AppSec Component](/appsec/intro.md#introduction) to protect web applications running behind [HAProxy](https://www.haproxy.org/) using the **HAProxy SPOA remediation component**.
13+
14+
You will:
15+
- Enable CrowdSec AppSec (WAF) in the Security Engine.
16+
- Install and configure `crowdsec-haproxy-spoa-bouncer` so HAProxy can forward HTTP requests to AppSec.
17+
- Validate everything by triggering a test detection.
18+
19+
## Prerequisites
20+
21+
1. If you're new to the [AppSec Component](/appsec/intro.md#introduction) or **W**eb **A**pplication **F**irewalls, start with the [Introduction](/appsec/intro.md#introduction).
22+
2. It's assumed that you have already installed:
23+
- **CrowdSec [Security Engine](/intro.mdx)**: for installation, refer to the [QuickStart guide](/u/getting_started/installation/linux).
24+
- **HAProxy**: already running and proxying your application(s).
25+
- **HAProxy SPOA [Remediation Component](/u/bouncers/intro)**: `crowdsec-haproxy-spoa-bouncer`.
26+
27+
:::tip Already did the base setup?
28+
If you already completed the [General Setup](general.mdx) (collections + acquisition), skip to [Remediation Component Setup](#remediation-component-setup).
29+
:::
30+
31+
## AppSec Component Setup
32+
33+
### Collection installation
34+
35+
Install the main AppSec rule collections:
36+
37+
```bash
38+
sudo cscli collections install crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules
39+
```
40+
41+
These <UnderlineTooltip tooltip="Collections are bundles of parsers, scenarios, and AppSec rules/configuration items.">collections</UnderlineTooltip> provide virtual patching (CVE rules), generic WAF detections, and the default AppSec configuration.
42+
43+
### Setup the acquisition
44+
45+
Create `/etc/crowdsec/acquis.d/appsec.yaml` (see the [AppSec datasource](/log_processor/data_sources/appsec.md) for the full reference):
46+
47+
```yaml title="/etc/crowdsec/acquis.d/appsec.yaml"
48+
appsec_configs:
49+
- crowdsecurity/appsec-default
50+
labels:
51+
type: appsec
52+
listen_addr: 127.0.0.1:7422
53+
source: appsec
54+
```
55+
56+
Restart CrowdSec:
57+
58+
```bash
59+
sudo systemctl restart crowdsec
60+
```
61+
62+
:::warning
63+
Do not expose the AppSec Component to the internet. It should only be reachable from your reverse proxy.
64+
:::
65+
66+
## Remediation Component Setup
67+
68+
### Install and configure the HAProxy SPOA bouncer
69+
70+
Read here how to install the SPOA remediation component: [HAProxy SPOA remediation component docs](/u/bouncers/haproxy_spoa).
71+
72+
Once the bouncer is installed and able to talk to CrowdSec LAPI, you only need to enable **AppSec forwarding**.
73+
74+
### Enable AppSec forwarding in the bouncer (YAML)
75+
76+
In `/etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml`, configure the AppSec endpoint the bouncer should query for WAF evaluation:
77+
78+
```yaml title="/etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml"
79+
# AppSec (WAF forwarding)
80+
appsec_url: "http://127.0.0.1:7422"
81+
appsec_timeout: "200ms"
82+
83+
hosts:
84+
- host: "*"
85+
appsec:
86+
always_send: false
87+
```
88+
89+
Restart the bouncer:
90+
91+
```bash
92+
sudo systemctl restart crowdsec-spoa-bouncer
93+
```
94+
95+
:::note
96+
If AppSec runs on a different host (or in containers), update `appsec_url` to the correct reachable address.
97+
:::
98+
99+
:::warning AppSec limitations with HAProxy SPOA (important)
100+
HAProxy SPOA forwarding is constrained by HAProxy/SPOE/SPOA mechanics:
101+
- Request bodies are only available if you enable buffering (`option http-buffer-request`) and they must fit within tight size limits (commonly capped at ~50KB in examples).
102+
- When the body is too large (uploads, large JSON, etc.), you typically fall back to a “no-body” SPOE group, which means **body-dependent WAF rules cannot match**.
103+
- You are not doing full “streaming” inspection: SPOA works with what HAProxy can capture and send to the agent within buffer/frame limits.
104+
105+
CrowdSec AppSec is still a single “source of truth” for rules/config: you can point multiple AppSec-capable integrations to the same AppSec endpoint so rule updates stay in sync across your infrastructure.
106+
107+
Recommended layered approach:
108+
- Use HAProxy SPOA for **edge enforcement** (IP/range/country decisions, ban/captcha) and lightweight WAF evaluation when the request fits within the configured limits.
109+
- Put a full-featured L7 proxy/WAF-capable integration **downstream** (or protect the app directly) when you need deeper inspection of large bodies, file uploads, or application-specific request parsing. Examples of AppSec-capable integrations include:
110+
- [Nginx/OpenResty](/appsec/quickstart/nginxopenresty)
111+
- [Traefik](/appsec/quickstart/traefik)
112+
- [WordPress](/appsec/quickstart/wordpress)
113+
:::
114+
115+
## Testing the AppSec Component + Remediation Component
116+
117+
:::note
118+
Adjust the URL below to match your HAProxy frontend (HTTP/HTTPS, port, hostname).
119+
:::
120+
121+
If you try to access `http(s)://<your-haproxy-url>/.env`, your request should be blocked:
122+
123+
```bash
124+
curl -i http://<your-haproxy-url>/.env
125+
```
126+
127+
![appsec-denied](/img/appsec_denied.png)
128+
129+
You can also check AppSec metrics:
130+
131+
```bash
132+
sudo cscli metrics show appsec
133+
```
134+
135+
### Explanation
136+
137+
What happened in the test above is:
138+
139+
1. You requested `/.env` through HAProxy.
140+
2. HAProxy forwarded the request to the SPOA remediation component (SPOE/SPOA).
141+
3. The remediation component queried the AppSec Component at `appsec_url`.
142+
4. The request matched the [AppSec rule to detect `.env` access](https://app.crowdsec.net/hub/author/crowdsecurity/appsec-rules/vpatch-env-access).
143+
5. AppSec returned a blocking action (HTTP 403) to the remediation component.
144+
6. HAProxy blocked the request.
145+
146+
## Next steps
147+
148+
- Monitor WAF alerts with `sudo cscli alerts list` and in the [CrowdSec Console](https://app.crowdsec.net).
149+
- Tune rules and configurations: `/appsec/configuration.md` and `/appsec/configuration_rule_management.md`.
150+
- Troubleshoot: `/appsec/troubleshooting.md` and [HAProxy SPOA remediation component docs](/u/bouncers/haproxy_spoa).

crowdsec-docs/sidebars.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ const sidebarsConfig: SidebarConfig = {
683683
{ type: "doc", id: "appsec/quickstart/general_setup" },
684684
{ type: "doc", id: "appsec/quickstart/nginx-ingress" },
685685
{ type: "doc", id: "appsec/quickstart/nginxopenresty" },
686+
{ type: "doc", id: "appsec/quickstart/haproxy_spoa" },
686687
{ type: "doc", id: "appsec/quickstart/npmplus" },
687688
{ type: "doc", id: "appsec/quickstart/traefik" },
688689
{ type: "doc", id: "appsec/quickstart/wordpress" },

0 commit comments

Comments
 (0)