Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net/haproxy: Support for GPC General Purpose Counters #1123

Open
seizedengine opened this issue Jan 9, 2019 · 4 comments
Open

net/haproxy: Support for GPC General Purpose Counters #1123

seizedengine opened this issue Jan 9, 2019 · 4 comments
Assignees
Labels
feature Adding new functionality help wanted Contributor missing

Comments

@seizedengine
Copy link

Is support for gpc counters in stick tables and ACLs planned? Gpc as in general purpose counters.

They are used most often in the abuse prevention and blocking type rules.

Some examples:

https://www.haproxy.com/blog/bot-protection-with-haproxy/
https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#7 (search for gpc0)

`frontend http
# Use General Purpose Couter 0 in SC0 as a global abuse counter
# protecting all our sites
stick-table type ip size 1m expire 5m store gpc0
tcp-request connection track-sc0 src
tcp-request connection reject if { sc0_get_gpc0 gt 0 }
...
use_backend http_dynamic if { path_end .php }

backend http_dynamic
# if a source makes too fast requests to this dynamic site (tracked
# by SC1), block it globally in the frontend.
stick-table type ip size 1m expire 5m store http_req_rate(10s)
acl click_too_fast sc1_http_req_rate gt 10
acl mark_as_abuser sc0_inc_gpc0(http) gt 0
tcp-request content track-sc1 src
tcp-request content reject if click_too_fast mark_as_abuser`

@fichtner
Copy link
Member

@fraenki fraenki added the feature Adding new functionality label Jan 10, 2019
@seizedengine
Copy link
Author

Ok, some more detail around what I was doing and managed to figure out which might help you. The example I attached in the original issue is what I thought would work but I found a better one (for my goal). I have HAProxy reverse proxying my Unifi NVR VM and applying a Lets Encrypt cert, but I wanted to use some of the common ACLs to protect it further. The NVR also has fail2ban running with a script updating an alias on OPNSense via the API to block IPs that get the password wrong too often, the problem there is due to keepalives and the nature of pf adding an IP to the alias doesnt block until the next connection. Hence HAProxy ACLs to disconnect the abusive user and let pf take over if they connect again since stick tables are reset on restart.

This is what I based things on:
https://www.haproxy.com/blog/http-request-flood-mitigation/

A few things I ran into:

  • No option to add gpc0 in the frontend or backend pool configs so I did that through the passthrough options

  • Putting "tcp-request connection track-sc1 src" in the passthrough options for the frontend resulted in a config error warning about "tcp-request before tcp-request connection" I think. I worked around this by putting "tcp-request connection track-sc1 src" in its own rule as a passthrough then rebuilding the other rules to get them to apply in the correct order in the UI

  • Last thing I tried and this is more of a future state is the plugin doesnt allow for stick table only backends to be created, a backend without any servers attached, only a stick table config. My goal here was to use one backend with a gpc stick table as a reference for all the others, IP with gpc0>1 in that backend would be blocked in all frontends. But that is minor for now.

@fraenki
Copy link
Member

fraenki commented Feb 3, 2019

@seizedengine Thanks for keeping this issue updated! Could you please provide the final haproxy.conf (excerpt) for reference? This would help me when adding the missing pieces to the plugin.

@seizedengine
Copy link
Author

seizedengine commented Feb 4, 2019

@fraenki Config is below, I redacted some minor stuff and unrelated frontends/backends but this is the relevant stuff. Also keep in mind this is my first time using HAProxy so I could be way off base on some things...

`

#
# Automatically generated configuration.
# Do not edit this file manually.
#

global
    # NOTE: Could be a security issue, but required for some feature.
    uid                         80
    gid                         80
    chroot                      /var/haproxy
    daemon
    stats                       socket /var/run/haproxy.socket level admin expose-fd listeners
    nbproc                      1
    nbthread                    1
    tune.ssl.default-dh-param   2048
    spread-checks               0
    tune.chksize                16384
    tune.bufsize                16384
    tune.lua.maxmem             0
    log /var/run/log local0 warning
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
    ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256

defaults
    log     global
    option redispatch -1
    timeout client 60s
    timeout connect 60s
    timeout server 60s
    retries 3
    # WARNING: pass through options below this line
    timeout http-request 5s
    option forwardfor


# Frontend: NVRUIFrontend (Ubiquiti NVR - UI Frontend)
frontend NVRUIFrontend
    http-response set-header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
    bind 172.16.66.1:7443 name 172.16.66.1:7443 ssl no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256 crt-list /tmp/haproxy/ssl/5b9424159c7b20.37423090.certlist 
    mode http
    option http-keep-alive
    default_backend NVRUIBackend
    option forwardfor
    # tuning options
    timeout client 60s

    # logging options
    option log-separate-errors
    option httplog
    # ACL: Gpc0GtZero
    acl acl_5c5238ebcce876.74865754 src_get_gpc0 gt 0

    # NOTE: actions with no ACLs/conditions will always match
# ACTION: SetTCPRequestTrackSC1Src
    tcp-request connection track-sc1 src 
    # ACTION: TCPContentRejectGPC
    tcp-request content reject if acl_5c5238ebcce876.74865754
    # ACTION: HTTPRequestDenyGPC
    http-response deny if acl_5c5238ebcce876.74865754

    # WARNING: pass through options below this line
    tcp-request inspect-delay 10s
    stick-table type ip size 100k expire 5m store gpc0,http_req_rate(10s),http_err_rate(10s),http_err_cnt

# Frontend: NVRVIDEOFrontend (Ubiquiti NVR - Video Frontend)
frontend NVRVIDEOFrontend
    http-response set-header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
    bind 172.16.66.1:7446 name 172.16.66.1:7446 ssl no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256 crt-list /tmp/haproxy/ssl/5b94249be0b644.20239361.certlist 
    mode http
    option http-keep-alive
    default_backend NVRVIDEOBackend
    option forwardfor
    # tuning options
    timeout client 60s

    # logging options
    option log-separate-errors
    option httplog
    # WARNING: pass through options below this line
    tcp-request inspect-delay 10s
    stick-table type ip size 100k expire 1h store gpc0,http_req_rate(10s),http_err_rate(10s),http_err_cnt


# Backend: NVRUIBackend (Ubiquiti NVR - UI Backend)
backend NVRUIBackend
    # health checking is DISABLED
    mode http
    balance source
    # stickiness
    stick-table type ip size 50k expire 30m store http_req_rate(10s) 

    # tuning options
    timeout connect 60s
    timeout server 60s
    # ACL: NVRUIFrontend-HTTPErrorCount
    acl acl_5c5285ee799c05.54159107 src_http_err_cnt(NVRUIFrontend) ge 10
    # ACL: NVRUIFrontend-SrcIncGPC
    acl acl_5c528c17730794.51386104 src_inc_gpc0(NVRUIFrontend) ge 0

    # NOTE: actions with no ACLs/conditions will always match
# ACTION: ResponseDeleteServerHeader
    http-response del-header Server 
    # ACTION: NVRUIBackend-BlockOnFrontend
    http-request deny if acl_5c5285ee799c05.54159107 acl_5c528c17730794.51386104

    # WARNING: pass through options below this line
    tcp-request inspect-delay 10s
    
    # add X-Forwarded-Proto 
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    
    #force SSL redirect
    redirect scheme https if !{ ssl_fc }
    
    option http-keep-alive
    
    # add X-FORWARDED-FOR
    option forwardfor
    
    # Set security headers
    http-response set-header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload;"
    
    http-response set-header X-Frame-Options SAMEORIGIN
    
    http-response set-header X-XSS-Protection "1; mode=block"
    
    http-response set-header Referrer-Policy no-referrer-when-downgrade
    
    http-response set-header X-Content-Type-Options nosniff
    
    http-response set-header Content-Security-Policy "default-src https://nvr.foo.bar:7443/; script-src https://nvr.foo.bar:7443/ 'unsafe-inline' 'unsafe-eval'; style-src https://nvr.foo.bar:7443/ 'unsafe-inline'; img-src data: blob: https://nvr.foo.bar:7443/ https://nvr.foo.bar:7446; connect-src wss://nvr.foo.bar:7443/ wss://nvr.foo.bar:7446/ https://nvr.foo.bar:7443/ https://nvr.foo.bar:7446/; media-src blob: https://nvr.foo.bar:7443/ https://nvr.foo.bar:7446/; "
    http-reuse never
    server NVRUI unifinvr.foo.bar:7443 ssl verify none

# Backend: NVRVIDEOBackend (Ubiquiti NVR - Video Backend)
backend NVRVIDEOBackend
    # health checking is DISABLED
    mode http
    balance source
    # stickiness
    stick-table type ip size 50k expire 30m  

    # tuning options
    timeout connect 60s
    timeout server 60s

    # NOTE: actions with no ACLs/conditions will always match
# ACTION: ResponseDeleteServerHeader
    http-response del-header Server 

    # WARNING: pass through options below this line
    # add X-Forwarded-Proto 
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    
    #force SSL redirect
    redirect scheme https if !{ ssl_fc }
    
    option http-keep-alive
    
    # add X-FORWARDED-FOR
    option forwardfor
    
    # Set security headers
    http-response set-header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload;"
    
    http-response set-header X-Frame-Options SAMEORIGIN
    
    http-response set-header X-XSS-Protection "1; mode=block"
    
    http-response set-header Referrer-Policy no-referrer-when-downgrade
    
    http-response set-header X-Content-Type-Options nosniff
    
    http-response set-header Access-Control-Allow-Origin "https://nvr.foo.bar:7443/ https://nvr.foo.bar:7446/"
    
    http-response set-header Content-Security-Policy "default-src 'none'; img-src data: blob: https://nvr.foo.bar:7446/; connect-src wss://nvr.foo.bar:7446/ https://nvr.foo.bar:7446/; media-src blob: https://nvr.foo.bar:7446/; "
    http-reuse never
    server NVRVIDEO unifinvr.foo.bar:7446 ssl verify none


# Backend (DISABLED): Abuse (Abuse Blocking Backend)

listen local_statistics
    bind            127.0.0.1:8822
    mode            http
    stats uri       /haproxy?stats
    stats realm     HAProxy\ statistics
    stats admin     if TRUE

listen  remote_statistics
    bind            172.16.42.1:8822
    mode            http
    stats uri       /haproxy?stats
    stats hide-version
    acl auth_ok http_auth(stats_auth)
    stats http-request allow if auth_ok
    stats http-request auth realm HAProxy\ statistics

`

@fraenki fraenki added the help wanted Contributor missing label Feb 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Adding new functionality help wanted Contributor missing
Development

No branches or pull requests

3 participants