example-data-and-configs/HAProxy/haproxy.cfg (72 lines of code) (raw):
global
log 127.0.0.1 local2 debug
maxconn 2000
user haproxy
group haproxy
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-default-bind-ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256: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 good practise taken from: https://www.haproxy.com/documentation/aloha/12-5/traffic-management/lb-layer7/tls/
#ssl ciphers level intermediate (compatible with almost everything) taken from: https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended-configurations
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
timeout connect 5000
timeout client 10000
timeout server 10000
log-format "GMT:%T frontend:%f/%H/%fi:%fp backend:%b client:%ci:%cp xforwardedfor:%[capture.req.hdr(3)] headers:%hr statuscode:%ST request:%r"
frontend www-https
mode http
option http-buffer-request
declare capture request len 40000
capture request header User-Agent len 512
capture request header Host len 512
capture request header X-Forwarded-For len 512
capture request header X-Forwarded-Proto len 512
capture request header X-Host len 512
capture request header Forwarded len 512
capture request header Via len 512
log /dev/log local2 debug
http-response set-header X-Frame-Options DENY
http-response set-header X-Content-Type-Options nosniff
http-response set-header Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
bind :::443 v4v6 ssl crt /etc/letsencrypt/live/haproxy.pem
http-request add-header X-Forwarded-Proto https
# modify the paths below to match your c2 channel
acl path_stage1 path -m beg /s1
acl path_cs path -m beg /cs
# stager - enable only if you know what you are doing
#acl path_cs path_reg ^/[0-z][0-z][0-z][0-z]$
use_backend c2_stage1_https if path_stage1
use_backend c2_cobaltstrike_https if path_cobaltstrike
default_backend decoy-www
timeout client 1m
frontend www-http
mode http
option http-buffer-request
declare capture request len 40000
capture request header User-Agent len 512
capture request header Host len 512
capture request header X-Forwarded-For len 512
capture request header X-Forwarded-Proto len 512
capture request header X-Host len 512
capture request header Forwarded len 512
capture request header Via len 512
log /dev/log local2 debug
http-response set-header X-Frame-Options DENY
http-response set-header X-Content-Type-Options nosniff
http-response set-header Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
bind :::80 v4v6
http-request add-header X-Forwarded-Proto http
# modify the paths below to match your c2 channel
acl path_stage1 path -m beg /s1
acl path_cs path -m beg /cs
# stager - enable only if you know what you are doing
#acl path_cs path_reg ^/[0-z][0-z][0-z][0-z]$
default_backend decoy-www
timeout client 1m
# backend names should start with decoy, c2 or alarm for redelk to understand and act upon
backend decoy-www
mode http
http-request set-header Host 127.0.0.1
server 127.0.0.1 127.0.0.1:80
backend c2_cobaltstrike_https
# Insert X-Forwarded-For header to have Cobalt Strike display the proper IP address of target. Uncomment if you want this functionality
# Remark: when using Domain Fronting/CDNs, this needs to be commented out as Cobalt Strike does not understand a double inserted X-Forwarded-For header: it will display the IP of the CDN endpoint
#option forwardfor
server teamserver $$IP_OF_YOUR_C2SERVER:443 check ssl verify none
backend c2_cobaltstrike_http
#option forwardfor
server teamserver $$IP_OF_YOUR_C2SERVER:80
backend c2_stage1
server c2server $$IP_OF_YOUR_C2SERVER:11081