ansibleguy.infra_haproxy

<a href="https://www.haproxy.com">
<img src="https://www.haproxy.com/assets/legal/web-logo.png" alt="HAProxy Logo" width="300"/>
</a>

# Ansible Role - HAProxy Community (with ACME, GeoIP, and some WAF Features)

This role sets up HAProxy (specifically the Community Version).

I find the structure of `frontend` => `route` => `backend` used in this role very user-friendly. Please [share your feedback](https://github.com/ansibleguy/infra_haproxy/discussions)!

<a href='https://ko-fi.com/ansible0guy' target='_blank'><img height='35' style='border:0px;height:46px;' src='https://az743702.vo.msecnd.net/cdn/kofi3.png?v=0' alt='Buy me a coffee' />

[![Molecule Test Status](https://badges.ansibleguy.net/infra_haproxy.molecule.svg)](https://github.com/ansibleguy/_meta_cicd/blob/latest/templates/usr/local/bin/cicd/molecule.sh.j2)
[![YamlLint Test Status](https://badges.ansibleguy.net/infra_haproxy.yamllint.svg)](https://github.com/ansibleguy/_meta_cicd/blob/latest/templates/usr/local/bin/cicd/yamllint.sh.j2)
[![PyLint Test Status](https://badges.ansibleguy.net/infra_haproxy.pylint.svg)](https://github.com/ansibleguy/_meta_cicd/blob/latest/templates/usr/local/bin/cicd/pylint.sh.j2)
[![Ansible-Lint Test Status](https://badges.ansibleguy.net/infra_haproxy.ansiblelint.svg)](https://github.com/ansibleguy/_meta_cicd/blob/latest/templates/usr/local/bin/cicd/ansiblelint.sh.j2)
[![Ansible Galaxy](https://badges.ansibleguy.net/galaxy.badge.svg)](https://galaxy.ansible.com/ui/standalone/roles/ansibleguy/infra_haproxy)

Molecule Logs: [Short](https://badges.ansibleguy.net/log/molecule_infra_haproxy_test_short.log), [Full](https://badges.ansibleguy.net/log/molecule_infra_haproxy_test.log)

**Tested on:**
* Debian 12

----

## Install

```bash
# latest version
ansible-galaxy role install git+https://github.com/ansibleguy/infra_haproxy

# from Ansible Galaxy
ansible-galaxy install ansibleguy.infra_haproxy

# or install to a custom role path
ansible-galaxy install ansibleguy.infra_haproxy --roles-path ./roles

Roadmap

  • Security features
    • Basic rate limiting for GET/HEAD and POST/PUT/DELETE methods
    • Generic client fingerprinting
  • Interface to convert Dict to Map-File easily
  • Option to download and integrate IP lists (like Tor exit nodes) easily
  • Simple way to change default error pages

Usage

Want a simple Ansible GUI? Check out my Ansible WebUI

Examples

Here are some detailed configuration examples and their results:

Configuration

Minimal example

haproxy:
  acme:
    enable: true
    email: '[email protected]'

  frontends:
    fe_web:
      bind: ['[::]:80 v4v6', '[::]:443 v4v6 ssl']
      acme:
        enable: true

      routes:
        be_intern:
          domains: ['app.template.ansibleguy.net']

      default_backend: 'be_fallback'

  backends:
    be_intern:
      servers:
        - 'srv-1 192.168.10.11:80'
        - 'srv-2 192.168.10.12:80'

    be_fallback:
      lines: 'http-request redirect code 302 location https://github.com/ansibleguy'

Define the configuration as needed:

haproxy:
  version: '2.8'
  acme:
    enable: true
    email: '[email protected]'

  # FRONTENDS
  frontends:
    fe_web:
      bind: ['[::]:80 v4v6', '[::]:443 v4v6 ssl']
      acme:
        enable: true
        domains: ['app.template.ansibleguy.net']  # domains from routes will also be added

      routes:
        be_app01:
          domains: ['app01.template.ansibleguy.net', 'hello.template.ansibleguy.net']

      # define raw config sections/lines to add
      lines:
        section1:
          - ...

      default_backend: 'be_fallback'

    fe_dbs:
      mode: 'tcp'
      default_backend: 'be_db'

    fe_restricted:
      bind: ['[::]:8080 v4v6', '[::]:8443 v4v6 ssl crt /etc/myapp/mycert.pem']

      geoip:
        enable: true

      security:
        restrict_methods: true
        allow_only_methods: ['HEAD', 'GET', 'POST']
        fingerprint_ssl: true  # create and log the JA3 SSL fingerprint of clients
        
        # very basic filtering of bad bots based on user-agent matching
        block_script_bots: true
        block_bad_crawler_bots: true

      routes:
        be_app02:
          filter_country: ['AT', 'DE', 'CH']
          # filter_ip: ['10.0.0.0/8']
          domains: ['app01.template.ansibleguy.net', 'hello.template.ansibleguy.net']

      # define raw config sections/lines to add
      lines:
        section1:
          - ...

      default_backend: 'be_fallback'

  # BACKENDS
  backends:
    be_app01:
      servers:
        - 'app01-1 10.0.1.1:80'
        - 'app01-2 10.0.1.2:80'

      check_uri: '/health'
      check_expect: 'status 200'

    be_app02:
      security:
        # very basic filtering of bad bots based on user-agent matching
        block_script_bots: true
        block_bad_crawler_bots: true

      ssl: true
      ssl_verify: 'none'  # default; example: 'required ca-file /etc/ssl/certs/my_ca.crt verifyhost host01.intern'
      servers:
        - 'app02-1 10.0.1.1:443'
        - 'app02-2 10.0.1.2:443'

    be_db:
      mode: 'tcp'
      balance: 'roundrobin'
          
      # define raw config sections/lines to add
      lines:
        section1:
          - 'option mysql-check user haproxy_check'

      servers:
        - 'mysql-1 10.0.0.1:3306'
        - 'mysql-2 10.0.0.2:3306'

    be_fallback:
      lines:
        default: 'http-request redirect code 302 location https://github.com/ansibleguy'

  # GENERAL
  stats:
    enable: true  # enable stats http listener
    bind: '127.0.0.1:8404'  # default

  geoip:
    enable: true
    provider: 'ipinfo'  # or 'maxmind'
    token: '<YOUR-TOKEN>'

  # define globals/defaults as key/value pairs (multi-value lists)
  global:
    ca-base: '/etc/ssl/certs'

  defaults:
    mode: 'http'
    'timeout connect': 3000
    'timeout server': 5000
    'timeout client': 5000

You may want to use 'ansible-vault' to encrypt your passwords:

ansible-vault encrypt_string

Functionality

  • Package installation

  • Configuration

    • Default config:

      • Global and default settings similar to standard installations
    • Default opt-ins:

      • Frontend configurations
        • HTTP mode
          • Redirect non-SSL traffic to SSL
          • Log User-Agent
          • Set basic security headers
          • Block TRACE & CONNECT methods
    • Default opt-outs:

      • Stats HTTP listener

      • Frontend options

      • Backend options

        • Sticky sessions
        • Block TRACE & CONNECT methods

Info

  • Note: This role currently supports only Debian-based systems.

  • Note: Many of the role's features can be enabled or disabled.

    For all options available, see the default configuration in the main defaults file!

  • Warning: Not all settings you provide will be validated. Incorrect configuration may cause the role to fail!

  • Info: You can filter access to backends using the filter and filter_not settings:

    filter_ip, filter_not_ip, filter_country, filter_not_country, filter_asn, filter_not_asn

  • Info: You can enable basic user-agent based script and bad-crawler bot blocking for frontends and backends. Check the defaults for the list of bots that are blocked.

  • Info: You can restrict allowed HTTP methods on a specific frontend or backend by enabling security.restrict_methods and specifying security.allow_only_methods.

  • Info: Check the Fingerprinting Docs for more information on tracking clients.

  • Info: If you use Graylog Server to analyze your logs, make sure to split your HAProxy logs into fields using pipeline rules. Example: HAProxy Community - Graylog Pipeline Rule

  • Tip: Increase the number of available track-sc by setting the global option tune.stick-counters. Useful in complex environments with rate-limits.

GeoIP

  • Warning: If you use the automatically provided GeoIP databases, ensure compliance with their license:

    • IPinfo: Information, CC4 License (allows commercial use - attribution is required)

      Attribution: <p>IP address data powered by <a href="https://ipinfo.io">IPinfo</a></p>

    • MaxMind: Information, EULA (allows limited commercial use - attribution is required)

      Attribution: This product includes GeoLite2 data created by MaxMind, available from <a href="https://www.maxmind.com">https://www.maxmind.com</a>.

  • Info: Create a free account to access GeoIP Tokens:

  • Info: For self-managed GeoIP databases (not recommended), they should be placed at /var/local/lib/geoip and named asn.mmdb & country.mmdb.

  • Info: Test the GeoIP Lookup Microservice using curl: curl 'http://127.0.0.1:10069/?lookup=country&ip=1.1.1.1'

WAF

  • Note: The WAF/security features in this role are not as comprehensive as those available in HAProxy Enterprise by default. If budget allows, consider using that version.

  • Tip: Use security.flag_bots to enforce stricter rules for suspected bots.

    Examples:

    • Lower rate limit for bots: http-request deny deny_status 429 if !{ var(txn.bot) -m int 0 } { sc_http_req_rate(0) gt 50 }

    • Prevent bots from registering accounts: http-request deny deny_status 400 if !{ var(txn.bot) -m int 0 } { method POST } { path_sub -m str -i /register/ }

    • Pass the bot flag to your application for user-friendly error messages: http-request add-header X-Bot %[var(txn.bot)]

  • Note: Before using security.block_script_kiddies, review the block-list in the defaults and modify as needed.

TCP

  • Info: To dynamically capture data, implement tcp-request content capture.

    You must enable logging of captured data by modifying the log format: {% raw %}<DEFAULT LOG FORMAT HERE> {%[capture.req.hdr(0)]|%[capture.req.hdr(1)]}{% endraw %}

    This allows logging of SNI or GeoIP information.


Execution

Run the playbook:

ansible-playbook -K -D -i inventory/hosts.yml playbook.yml

Useful tags are available:

  • install
  • config => update configuration and SSL certificates
  • ssl or acme
  • geoip
  • lua

To debug errors, set the 'debug' variable during runtime:

ansible-playbook -K -D -i inventory/hosts.yml playbook.yml -e debug=yes

```

Informazioni sul progetto

Provision HAProxy Community (with ACME, GeoIP and some WAF-Features)

Installa
ansible-galaxy install ansibleguy.infra_haproxy
Licenza
other
Download
972
Proprietario
[email protected] | GPG: https://badges.ansibleguy.net/public.gpg