Skip to content

HAProxy Fodder

FoDDeR-Logo

What is FoDDeR

Fodder is a slightly opinionated fiddler for FoD-go - Firewall on Demand (Go).

The application has dependencies, some of which are strict requirements while others are optional or bypassable.

IPv6 is enforced if IPv6 is not in use, it's possible to add a Link-local address which will never be hit by external connections.

It is conceived to work with a two nodes cluster If you don't have a cluster, you can use the IP of the HAProxy server as the VIP.

It integrates a PoW at this stage PoW (Proof of Work) is not part of this project. To exclude the PoW it's possible to set a very high value for global_medium_threshold

it works only with HAProxy it relies on stick-tables which are available with HAProxy

it requires FoD-go it does not interact with BGP Flowspec, but with FoD-go.

How does FoDDer work

Fodder consists of two applications: a Web application written in Go, a connection monitoring script written in Python.

The Connection monitoring operates as detection layer: haproxy_conn_monitor.py

HAProxy fodder is the Web UI, operating as enforcement layer: haproxy-fodder

Configuration files

The informations are are read and stored in the following order:

  • stick-table. The stick table fod_vars is used as a KV store. With a two nodes cluster, there should be a peer section in haproxy.cfg to enable synchronization of the stick-table.
  • /etc/fodder/fod-vars.yaml. The file fod-vars.yaml is used by the Web App to store the information from the stick-table, and as a backup source of truth, when the stick-table is missing (i.e.: if both haproxy go down the data will be missing).
  • /etc/fodder/fod-vars-defaults.yaml. This file is used to bootstrap the application and provides the initial values.

Stick tables

The following stick-tables must be created on HAProxy

backend ip_rate
  stick-table type ipv6 size 400k expire 10m store http_req_rate(10s) peers test_geant_haproxy
backend pow_state
  stick-table type ipv6 size 400k expire 720m store gpc0,http_req_rate(10s) peers test_geant_haproxy
backend fod_vars
  stick-table type string size 1k store gpc0 peers test_geant_haproxy

The tables ip_rate and pow_state must be tracked in the configuration file:

  http-request track-sc0 src table pow_state
  http-request track-sc1 src table ip_rate

The table fod_vars is used only as a KV store and should not be tracked.

fod_vars

FoD vars are scattered as following

fod_vars stick-table

the stick table fod_vars contains the following information, with different values for the key gpc0:

# echo "show table fod_vars" | socat stdio /run/haproxy.sock
# table: fod_vars, type: string, size:1024, used:7
0x7e3b7a85c988: key=sleep_time use=0 exp=0 shard=0 gpc0=30
0x7e3b7a85c7c8: key=ip_rate_medium use=0 exp=0 shard=0 gpc0=5000
0x7e3b7a85ca68: key=fod_ip_threshold use=0 exp=0 shard=0 gpc0=150
0x7e3b7a85c8a8: key=ip_rate_high use=0 exp=0 shard=0 gpc0=10000
0x7e3b7a85cc28: key=fod_rule_expiration use=0 exp=0 shard=0 gpc0=10
0x7e3b7a85c6e8: key=ip_rate_low use=0 exp=0 shard=0 gpc0=1000
0x7e3b7a85cb48: key=fod_subnet_threshold use=0 exp=0 shard=0 gpc0=1000

haproxy-conn-monitor.yaml

The file haproxy-conn-monitor.yaml contains the information to connect to Fod, as well as actions to trigger.

The first key is country-ip-blocks.tar.gz. This file is pulled daily from this repository: country-ip-blocks (at a later stage I'll share a script to pull this artifact).

---
country_tarball: "/etc/fodder/country-ip-blocks.tar.gz"
haproxy_socket: "/run/haproxy.sock"
fod_api_endpoint: https://fod-go.example.org/api/v1
fod_token: "<fod-secret-token>"
rate_table: ip_rate
pow_table: pow_state
fod_network_id: "<fod-network-id>"
rule_description: "FoD rule created by haproxy-conn-monitor"
fod_dict_v4:
  protocols:
    - TCP
  action: discard
  status: active
  destination: 192.168.1.1
  destination_mask: 32
  destination_ports:
    - begin: 443
      end: 443
    - begin: 80
      end: 80
fod_dict_v6:
  protocols:
    - TCP
  action: discard
  status: active
  destination: 2001:db8::1
  destination_mask: 128
  destination_ports:
    - begin: 443
      end: 443
    - begin: 80
      end: 80

fod-vars.yaml

this file is empty and it's handled by haproxy-fodder

fod-vars-defaults.yaml

this file contains the information to bootstrap the application.

---
ip_rate_low: 1000
ip_rate_medium: 5000
ip_rate_high: 10000
fod_ip_threshold: 150
fod_subnet_threshold: 1000
fod_rule_expiration: 10
sleep_time: 30