This guide shows you how to capture logs from an HAProxy Docker container, extract relevant fields, and forward them to OneFirewall’s traffic validation API using Fluent Bit and Lua scripting.
Overview
- HAProxy logs are sent directly to Fluent Bit over UDP (syslog)
- Fluent Bit extracts fields (like source IP and HTTP status)
- Lua script transforms log into a JSON payload
- Fluent Bit posts the data to OneFirewall’s API
1. Folder Structure
project-root/
├── docker-compose.yml
├── fluent-bit/
│ ├── fluent-bit.conf
│ ├── parsers.conf
│ └── send_to_onefirewall.lua
├── haproxy/
│ └── haproxy.cfg
2. HAProxy Configuration
haproxy.cfg
global
log fluent-bit:5140 local0
daemon
defaults
log global
mode http
option httplog
timeout connect 5s
timeout client 30s
timeout server 30s
This configuration sends logs over UDP to Fluent Bit, which must be running in the same Docker network.
3. Fluent Bit Parser
parsers.conf
[PARSER]
Name haproxy_raw
Format regex
Regex ^<\d+>\w+\s+\d+\s+\d+:\d+:\d+\s+haproxy\[\d+\]: (?<src_ip>\d+\.\d+\.\d+\.\d+):\d+ \[[^\]]+\] \S+ \S+ \d+/\d+/\d+/\d+/\d+ (?<action>\d{3})
send_to_onefirewall.lua
function escape(s)
s = string.gsub(s, '\\', '\\\\')
s = string.gsub(s, '"', '\\"')
return s
end
function cb_send(tag, ts, record)
local src_ip = tostring(record["src_ip"])
local action = tostring(record["action"])
if not string.match(src_ip, "^%d+%.%d+%.%d+%.%d+$") then
return -1
end
local json = string.format(
'{"src_ip":"%s","dst_ip":"192.168.0.1","src_port":3435,"dst_port":443,"service":"myservice","firewall":"haproxy","action":"%s","direction":"inbound"}',
escape(src_ip),
escape(action)
)
return 1, ts, {
body = json,
headers = {}
}
end
5. Fluent Bit Configuration
fluent-bit.conf
[SERVICE]
Flush 1
Log_Level info
Parsers_File /fluent-bit/etc/parsers.conf
[INPUT]
Name syslog
Mode udp
Listen 0.0.0.0
Port 5140
Parser haproxy_raw
Tag haproxy.syslog
[FILTER]
Name lua
Match haproxy.*
script /fluent-bit/etc/send_to_onefirewall.lua
call cb_send
[OUTPUT]
Name http
Match haproxy.*
Host app.onefirewall.com
Port 443
URI /api/v1/poc_traffic/direct
Format msgpack
tls On
tls.verify On
Header Authorization Bearer YOUR_TOKEN_HERE
Header Content-Type application/json
Body_Key body
Headers_Key headers
Compress off
[OUTPUT]
Name stdout
Match *
Format json_lines
6. Docker Compose Example
version: '3.8'
services:
haproxy:
image: haproxy:lts-alpine3.21
container_name: haproxy
ports:
- "443:443"
depends_on:
- fluent-bit
command: >
sh -c "haproxy -f /usr/local/etc/haproxy/haproxy.cfg"
volumes:
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
fluent-bit:
image: fluent/fluent-bit:2.1
container_name: fluent-bit
ports:
- "5140:5140/udp"
volumes:
- ./fluent-bit:/fluent-bit/etc
Ensure both containers are on the same network (Docker Compose does this by default).
7. OneFirewall Traffic Validation
When Fluent Bit sends structured traffic data to OneFirewall:
- OneFirewall validates
src_ip
and dst_ip
fields
- Invalid or private IPs are rejected with:
{ "message": "Not valid SRC or DST IP" }
- Ensure you’re using valid public IPv4 addresses for testing.
✅ Result
With this setup:
- HAProxy sends logs over UDP to Fluent Bit
- Fluent Bit parses and transforms the data with Lua
- JSON is posted to OneFirewall’s traffic validation API
🔒 Notes
- Replace
YOUR_TOKEN_HERE
with your actual OneFirewall token
- Consider adding retry/failure handling or S3 backup for production
- Ensure
dst_ip
is not a private/local IP unless OneFirewall allows it
💬 Need Help?
Feel free to reach out to OneFirewall Support if you need help debugging HTTP integration or validating traffic.