-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2a9e50b
commit 485ce62
Showing
9 changed files
with
303 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
# Basic Example with GeoIP | ||
|
||
There are still some basic WAF features to be implemented. | ||
|
||
NOTE: The feature-set this role provides does not come lose to the one [available in HAProxy Enterprise by default](https://www.haproxy.com/solutions/web-application-firewall). | ||
|
||
## Config | ||
|
||
```yaml | ||
haproxy: | ||
waf: {} | ||
|
||
frontends: | ||
fe_web: | ||
bind: ['[::]:80 v4v6'] | ||
|
||
security: | ||
headers: true | ||
fingerprint_ssl: true | ||
restrict_methods: true | ||
allow_only_methods: ['HEAD', 'GET', 'POST'] | ||
# deny_dangerous_methods: true | ||
block_script_bots: true | ||
block_bad_crawler_bots: true | ||
|
||
|
||
routes: | ||
be_test: | ||
domains: ['app.test.ansibleguy.net'] | ||
|
||
default_backend: 'be_fallback' | ||
|
||
backends: | ||
be_test: | ||
security: | ||
restrict_methods: true | ||
allow_only_methods: ['HEAD', 'GET', 'POST'] | ||
# deny_dangerous_methods: true | ||
block_script_bots: true | ||
block_bad_crawler_bots: true | ||
|
||
servers: | ||
- 'srv-1 192.168.10.11:80' | ||
- 'srv-2 192.168.10.12:80' | ||
|
||
be_fallback: | ||
lines: 'http-request redirect code 301 location https://github.com/ansibleguy' | ||
``` | ||
---- | ||
## Result | ||
```bash | ||
root@test-ag-haproxy-waf:/# cat /etc/haproxy/haproxy.cfg | ||
> # Ansible managed: Do NOT edit this file manually! | ||
> # ansibleguy.infra_haproxy | ||
> | ||
> global | ||
> daemon | ||
> user haproxy | ||
> group haproxy | ||
> | ||
> | ||
> log /dev/log local0 | ||
> log /dev/log local1 notice | ||
> chroot /var/lib/haproxy | ||
> stats socket /run/haproxy/admin.sock mode 660 level admin | ||
> stats timeout 30s | ||
> ca-base /etc/ssl/certs | ||
> crt-base /etc/ssl/private | ||
> ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 | ||
> ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 | ||
> ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets | ||
> tune.ssl.capture-buffer-size 96 | ||
> | ||
> defaults | ||
> log global | ||
> mode http | ||
> option httplog | ||
> option dontlognull | ||
> timeout connect 5000 | ||
> timeout client 50000 | ||
> timeout server 50000 | ||
> errorfile 400 /etc/haproxy/errors/400.http | ||
> errorfile 403 /etc/haproxy/errors/403.http | ||
> errorfile 408 /etc/haproxy/errors/408.http | ||
> errorfile 500 /etc/haproxy/errors/500.http | ||
> errorfile 502 /etc/haproxy/errors/502.http | ||
> errorfile 503 /etc/haproxy/errors/503.http | ||
> errorfile 504 /etc/haproxy/errors/504.http | ||
|
||
root@test-ag-haproxy-waf:/# cat /etc/haproxy/conf.d/frontend.cfg | ||
> # Ansible managed: Do NOT edit this file manually! | ||
> # ansibleguy.infra_haproxy | ||
> | ||
> frontend fe_web | ||
> mode http | ||
> bind [::]:80 v4v6 | ||
> | ||
> http-request deny status 405 default-errorfiles if !{ method HEAD GET POST } | ||
> | ||
> # block well-known script-bots | ||
> http-request deny status 425 default-errorfiles if { req.fhdr(User-Agent) -m sub -i curl wget Apache-HttpClient nmap Metasploit headless cypress go-http-client zgrab python httpx httpcore aiohttp httputil urllib GuzzleHttp phpcrawl Zend_Http_Client Wordpress Symfony-HttpClient cpp-httplib java perl axios ruby } | ||
> # block well-known bad-crawler-bots | ||
> http-request deny status 425 default-errorfiles if { req.fhdr(User-Agent) -m sub -i spider test-bot tiny-bot fidget-spinner-bot download scrapy } | ||
> # Security headers | ||
> http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;" | ||
> http-response set-header X-Frame-Options "DENY" | ||
> http-response set-header X-Content-Type-Options "nosniff" | ||
> http-response set-header X-Permitted-Cross-Domain-Policies "none" | ||
> http-response set-header X-XSS-Protection "1; mode=block" | ||
> # SSL fingerprint | ||
> http-request set-var(txn.fp_ssl_p1) ssl_fc_cipherlist_bin(1),be2dec(-,2) | ||
> http-request set-var(txn.fp_ssl_p2) ssl_fc_extlist_bin(1),be2dec(-,2) | ||
> http-request set-var(txn.fp_ssl_p3) ssl_fc_eclist_bin(1),be2dec(-,2) | ||
> http-request set-var(txn.fp_ssl_p4) ssl_fc_ecformats_bin,be2dec(-,1) | ||
> http-request set-var(txn.fingerprint_ssl_raw) "ssl_fc_protocol_hello_id,concat(',',txn.fp_ssl_p1),concat(',',txn.fp_ssl_p2),concat(',',txn.fp_ssl_p3),concat(',',txn.fp_ssl_p4)" | ||
> http-request set-var(txn.fingerprint_ssl) var(txn.fingerprint_ssl_raw),digest(md5),hex,lower | ||
> http-request capture var(txn.fingerprint_ssl) len 32 | ||
> | ||
> http-request capture req.fhdr(User-Agent) len 200 | ||
> | ||
> # BACKEND be_test | ||
> acl be_test_domains req.hdr(host) -m str -i app.test.ansibleguy.net | ||
> acl be_test_filter_ip always_true | ||
> acl be_test_filter_not_ip always_false | ||
> | ||
> use_backend be_test if be_test_domains be_test_filter_ip !be_test_filter_not_ip | ||
> | ||
> default_backend be_fallback | ||
|
||
root@test-ag-haproxy-waf:/# cat /etc/haproxy/conf.d/backend.cfg | ||
> # Ansible managed: Do NOT edit this file manually! | ||
> # ansibleguy.infra_haproxy | ||
> | ||
> backend be_test | ||
> mode http | ||
> balance leastconn | ||
> | ||
> http-request deny status 405 default-errorfiles if !{ method HEAD GET POST } | ||
> | ||
> # block well-known script-bots | ||
> http-request deny status 425 default-errorfiles if { req.fhdr(User-Agent) -m sub -i curl wget Apache-HttpClient nmap Metasploit headless cypress go-http-client zgrab python httpx httpcore aiohttp httputil urllib GuzzleHttp phpcrawl Zend_Http_Client Wordpress Symfony-HttpClient cpp-httplib java perl axios ruby } | ||
> # block well-known bad-crawler-bots | ||
> http-request deny status 425 default-errorfiles if { req.fhdr(User-Agent) -m sub -i spider test-bot tiny-bot fidget-spinner-bot download scrapy } | ||
> | ||
> server srv-1 192.168.10.11:80 check | ||
> server srv-2 192.168.10.12:80 check | ||
> | ||
> | ||
> backend be_fallback | ||
> mode http | ||
> balance leastconn | ||
> | ||
> # SECTION: default | ||
> http-request redirect code 301 location https://github.com/ansibleguy | ||
> | ||
|
||
root@test-ag-haproxy-waf:/# systemctl status haproxy.service | ||
> * haproxy.service - HAProxy Load Balancer | ||
> Loaded: loaded (/lib/systemd/system/haproxy.service; enabled; preset: enabled) | ||
> Drop-In: /etc/systemd/system/haproxy.service.d | ||
> `-override.conf | ||
> Active: active (running) since Sat 2024-05-04 16:24:54 UTC; 4min 11s ago | ||
> Docs: man:haproxy(1) | ||
> file:/usr/share/doc/haproxy/configuration.txt.gz | ||
> https://www.haproxy.com/documentation/haproxy-configuration-manual/latest/ | ||
> https://github.com/ansibleguy/infra_haproxy | ||
> Process: 4574 ExecStartPre=/usr/sbin/haproxy -c -f $CONFIG -f /etc/haproxy/conf.d/ (code=exited, status=0/SUCCESS) | ||
> Process: 4635 ExecReload=/usr/sbin/haproxy -c -f $CONFIG -f /etc/haproxy/conf.d/ (code=exited, status=0/SUCCESS) | ||
> Process: 4637 ExecReload=/bin/kill -USR2 $MAINPID (code=exited, status=0/SUCCESS) | ||
> Main PID: 4576 (haproxy) | ||
> Status: "Ready." | ||
> Tasks: 7 (limit: 1783) | ||
> Memory: 132.2M | ||
> CPU: 297ms | ||
> CGroup: /system.slice/haproxy.service | ||
> |-4576 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/ -p /run/haproxy.pid -S /run/haproxy-master.sock | ||
> `-4639 /usr/sbin/haproxy -sf 4578 -x sockpair@4 -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/ -p /run/haproxy.pid -S /run/haproxy-master.sock | ||
``` |
Oops, something went wrong.