-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathbfd.1
More file actions
1428 lines (1428 loc) · 36.7 KB
/
Copy pathbfd.1
File metadata and controls
1428 lines (1428 loc) · 36.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
.\" Brute Force Detection 2.0.2 man page
.\" Copyright (C) 1999-2026, R-fx Networks <proj@rfxn.com>
.\" Copyright (C) 2026, Ryan MacDonald <ryan@rfxn.com>
.\" Licensed under the GNU General Public License v2
.\"
.TH BFD 1 "2026-04-03" "BFD 2.0.2" "Brute Force Detection"
.SH NAME
bfd \- brute force detection and IP banning
.SH SYNOPSIS
.B bfd
.RB [ \-s | \-q | \-d | \-w ]
.br
.B bfd
.RB [ \-b
.IR IP " [" SERVICE ]]
.RB [ \-u
.IR IP ]
.RB [ \-\-flush\-temp ]
.RB [ \-\-flush\-all ]
.br
.B bfd
.RB [ \-l ]
.RB [ \-a
.RI [ IP | STRING ]]
.RB [ \-e
.RI [ IP | CIDR ]
.RI [ N ]]
.RB [ \-S
.RI [ SERVICE ]]
.RB [ \-C
.RI [ VAR ]]
.RB [ \-R
.RI [ RULE ]]
.RB [ \-c ]
.br
.B bfd
.RB [ \-T
.IR RULE " [" FILE | \- ]]
.RB [ \-\-test\-pattern
.IR PATTERN " [" FILE | \- ]]
.RB [ \-\-test\-alert
.IR TYPE ]
.br
.B bfd
.B \-\-scan
.RI [ RULE ]
.RB [ \-d ]
.RB [ \-\-max\-lines= \fIN\fR]
.RB [ \-\-scan\-timeout= \fIN\fR]
.br
.B bfd
.B \-\-report
.RI [ daily | weekly | monthly ]
.br
.B bfd
.RB [ \-\-json ]
.RB [ \-\-csv ]
.RB [ \-\-sort= \fIMODE\fR]
.RB [ \-\-limit= \fIN\fR]
.RB [ \-\-24h | \-\-7d | \-\-30d ]
.RB [ \-\-active ]
.RB [ \-V | \-\-verbose ]
.br
.B bfd
.B \-\-cdn
.RI [ PROVIDER | update | check
.IR IP ]
.br
.B bfd ban
.RI [ add | remove | list | flush | history ]
.RI [ args... ]
.br
.B bfd ignore
.RI [ add | remove | list | check ]
.RI [ args... ]
.br
.B bfd test
.RI [ rule | pattern | alert | scan ]
.RI [ args... ]
.br
.B bfd
.RI { cdn | report | status }
.RI [ args... ]
.br
.B bfd
.RB [ \-v ]
.RB [ \-h ]
.SH DESCRIPTION
.B bfd
(Brute Force Detection) is a shell-based intrusion detection and
response system that monitors authentication logs for repeated login
failures and automatically bans offending IP addresses using the
system firewall.
.PP
BFD supports two operating modes.
In
.B watch mode
(enabled automatically on install), BFD runs continuously, polling at a
configurable interval (default 10 seconds) for near-real-time detection.
In
.B batch mode\fR,
a cron job runs BFD every 2 minutes as an automatic fallback; it is
silently skipped when watch mode holds the lock and resumes detection
if the watch daemon exits.
.PP
Each detection cycle reads new log lines (via the
.B tlog
byte-offset tracker), matches them against 57 service rule files
using the
.B extract_hosts()
engine with fail2ban-compatible
.I <HOST>
patterns, computes exponential-decay pressure scores, and bans
addresses whose accumulated pressure exceeds the trip point.
Bans are applied via one of 8 firewall backends (auto-detected or
manually configured) and can be temporary with automatic expiry,
recidivism escalation, and distributed subnet detection.
.SH OPTIONS
.SS Run Modes
.TP
.BR \-s ", " \-\-standard
Run a detection cycle with output to stdout and log.
.TP
.BR \-q ", " \-\-quiet
Run a detection cycle silently (output redirected to /dev/null).
.TP
.BR \-d ", " \-\-dryrun
Run detection without actually executing ban commands.
Log output shows what would be banned.
.TP
.BR \-w ", " \-\-watch
Run in continuous watch mode (foreground).
Polls every
.B WATCH_INTERVAL
seconds.
Supports
.B SIGHUP
for configuration reload and
.B SIGTERM/SIGINT
for clean shutdown.
.SS Ban Management
.TP
.BI \-b ", " \-\-ban " IP" "\fR [" SERVICE \fR]
Manually ban an IP address (permanent).
If
.I SERVICE
is given, it is recorded as the triggering rule; otherwise
.BR manual .
.TP
.BI \-u ", " \-\-unban " IP"
Unban an IP address (removes from firewall and active bans).
.TP
.B \-\-flush\-temp
Remove all temporary (non-permanent) bans.
.TP
.B \-\-flush\-all
Remove all bans (temporary and permanent).
.PP
See also:
.BR "bfd ban" .
.SS Scan Mode
.TP
.BI \-\-scan " \fR[" RULE \fR] " \fR[" \-d \fR]
Process the full current log file through the detection pipeline.
Without
.IR RULE ,
scans all active rules.
Combine with
.BR \-d
for dry-run (no bans, no cursor advancement).
Acquires the global lock; stop watch mode first if running.
.TP
.BI \-\-max\-lines= N
Maximum lines per log file during scan; 0 = unlimited (default: 50000).
.TP
.BI \-\-scan\-timeout= N
Journal read timeout in seconds per rule during scan (default: 120).
.SS Information
.TP
.B \-l ", " \-\-list
List all active bans.
Combine with
.B \-\-json
or
.B \-\-csv
for structured output.
.TP
.BI \-a ", " \-\-activity " \fR[" IP | STRING \fR]
Threat activity report.
Without arguments, shows an aggregate summary (unique IPs, total
count, active bans for 24h and 7d windows), top 25 threat IPs for
24h and 7d with live pressure scores, and a per-service breakdown
with dual-interval columns (24h/7d count, unique IPs, top country).
With a valid IP, shows an enriched report with ban status, history,
events, pressure, and attack pool triggers.
With a string, searches attack pool entries.
Combine with
.B \-\-json
or
.B \-\-csv
for structured output.
.IP
.B Note:
Both
.B \-a
and
.B \-e
read from the same attack pool data store.
.B \-a
provides a summary-oriented threat activity overview with dual-interval
(24h/7d) views and per-service breakdown.
.B \-e
provides event-level detail with configurable time windows
.RB ( \-\-24h ", " \-\-7d ", " \-\-30d )
and sort modes
.RB ( \-\-sort=count|time|ip ).
Use
.B \-a
to review aggregate threat patterns and
.B \-e
to drill into specific IPs or subnets.
.TP
.BI \-e ", " \-\-events " \fR[" IP | CIDR "\fR] [" N \fR]
Event history and investigation.
Reads from the attack pool, which records all detected auth failures
(both ban-triggering and sub-trip observations) with configurable retention
(default: 365 days).
.sp
Without arguments, shows an event list of all IPs with failure counts,
services, country, first/last seen, and ban status.
Default: sorted by count descending, 24-hour window.
Use
.BR \-\-sort=time " or " \-\-sort=ip
to change ordering, and
.BR \-\-7d " or " \-\-30d
to expand the time window.
.sp
With a valid IP, shows a comprehensive investigation report: historical
failure counts from the attack pool (total and per-service breakdown),
live pressure detail if the IP has active pressure, and a log sample.
The optional
.I N
overrides the number of log sample lines shown (default:
.BR EMAIL_LOGLINES ).
.sp
With an IPv4 CIDR (mask 8\-32), shows a subnet-scoped report with
matching IPs and a summary line.
.sp
Combine with
.B \-\-json
or
.B \-\-csv
for structured output.
.TP
.BR \-\-report " \fR[" daily | weekly | monthly \fR]
Generate and deliver a periodic threat report.
Reports include threat summary (unique IPs, total events, bans), top threat IPs
with country codes and ban status, per-service breakdown with top country, and
a trend comparison against the prior equivalent time window.
Reports are delivered via all configured channels (email, Slack, Telegram,
Discord) or only those listed in
.BR REPORT_CHANNELS .
When run from the CLI, report text is also written to stdout.
.sp
Intervals:
.B daily
(last 24h, default),
.B weekly
(last 7d),
.B monthly
(last 30d).
Scheduled delivery is handled by
.B cron.daily
when
.B REPORT_ENABLED=1
\(em daily runs every day, weekly on Mondays, monthly on the 1st.
.TP
.BR \-S ", " \-\-status " \fR[" \fISERVICE\fR ]
System status overview, or per-service status when
.I SERVICE
is given.
Shows run mode, firewall backend, active bans, events, and active rules.
.TP
.BR \-C ", " \-\-config " \fR[" \fIVAR\fR ]
Show all configuration variables, or a single variable value.
.TP
.BR \-R ", " \-\-rules " \fR[" \fIRULE\fR "] \fR[" \-\-active \fR]
List all rules with active/inactive status, or show details for a
specific rule.
Use
.B \-\-active
to show only active rules.
The LOG SOURCE column shows the effective source for each rule:
file path when the log file exists, "journal" when using systemd journal,
or "file+journal" when both sources are available (file is primary,
journal is fallback).
.TP
.BR \-c ", " \-\-check
Run health check diagnostics.
Validates configuration, binaries, rules, state files, and alert
capability.
.SS Testing
.TP
.BI \-T ", " \-\-test " RULE" "\fR [" FILE | \- \fR]
Test a rule's patterns against its configured log file, a specific
.IR FILE ,
or stdin
.RB ( \- ).
Shows match count and unique IPs.
.TP
.BI \-\-test\-pattern " PATTERN" "\fR [" FILE | \- \fR]
Test a raw
.I <HOST>
pattern against a log file or stdin.
.TP
.BI \-\-test\-alert " TYPE"
Send a test alert to verify the delivery pipeline for the specified channel.
.I TYPE
is one of:
.BR email ", " slack ", " telegram ", " discord .
Uses a synthetic ban entry (RFC 5737 test IP 192.0.2.1, sshd service)
and calls the real rendering and delivery path.
.sp
For
.BR email :
requires
.B EMAIL_ALERTS=1
and a valid
.BR EMAIL_ADDRESS .
Honors all email configuration:
.BR EMAIL_FORMAT ", " SMTP_RELAY ", " EMAIL_REPUTATION_LINKS ,
etc.
.sp
For
.BR slack :
requires
.BR SLACK_ALERTS=1 ,
.B curl
in PATH, and the appropriate webhook URL or bot token/channel.
.sp
For
.BR telegram :
requires
.BR TELEGRAM_ALERTS=1 ,
.BR curl ,
.BR TELEGRAM_BOT_TOKEN ,
and
.BR TELEGRAM_CHAT_ID .
.sp
For
.BR discord :
requires
.BR DISCORD_ALERTS=1 ,
.BR curl ,
and
.BR DISCORD_WEBHOOK_URL .
.sp
The subject line is prefixed with
.B [TEST]
to distinguish from real alerts.
Bypasses digest mode to always send immediately.
.PP
See also:
.BR "bfd test" .
.SS Output Modifiers
.TP
.B \-\-json
Output in JSON format.
Supported with
.BR \-l ", " \-e ", and " \-a .
.TP
.B \-\-csv
Output in CSV format.
Supported with
.BR \-l ", " \-e ", and " \-a .
.TP
.BI \-\-sort= MODE
Sort order for event list
.RB ( \-e
without IP).
.I MODE
is one of:
.BR count " (default)," " time" ", or " ip .
.TP
.BI \-\-limit= N
Maximum number of IPs to display in event list
.RB ( \-e )
and CIDR output.
Default is 100.
Use
.B \-\-limit=0
for unlimited output.
.TP
.B \-\-24h
Show events from the last 24 hours (default).
.TP
.B \-\-7d
Show events from the last 7 days.
.TP
.B \-\-30d
Show events from the last 30 days.
.TP
.B \-\-active
Show only active rules.
Supported with
.BR \-R .
.TP
.BR \-V ", " \-\-verbose
Show detailed output.
Adds per-rule event counts and pressure details, filtered host details,
ban execution details, per-unban information, detection method in
status, and binary paths in health check.
Silenced by
.BR \-q .
.SS CDN / Trusted Proxy
.TP
.B \-\-cdn
List all configured CDN providers with active/inactive status and CIDR counts.
.TP
.BI \-\-cdn " PROVIDER"
Show the compiled CIDR ranges for a specific provider.
.TP
.B \-\-cdn update
Fetch and compile IP ranges for all enabled CDN providers.
Ranges are downloaded from the URLs configured in
.BR cdn\-providers.conf .
.TP
.BI "\-\-cdn check " IP
Check whether an IP address matches any CDN provider's compiled ranges.
.PP
Combine with
.B \-\-json
for structured output.
.PP
See also:
.BR "bfd cdn" .
.SS General
.TP
.BR \-v ", " \-\-version
Display version information.
.TP
.BR \-h ", " \-\-help
Display full usage help with grouped options and examples.
When
.B bfd
is run with no arguments, a short summary of common commands is shown instead.
.SH SUBCOMMANDS
BFD supports grouped subcommand syntax alongside traditional flag-based
invocation.
Each subcommand group accepts
.B \-\-help
or
.B \-h
to display its verb list.
.SS "bfd ban"
.TP
.BI "bfd ban add " "IP \fR[" SERVICE \fR]
Manually ban an IP address (permanent).
Equivalent to
.BR "bfd \-b" .
.TP
.BI "bfd ban remove " IP
Remove a ban.
Equivalent to
.BR "bfd \-u" .
.TP
.B "bfd ban list"
List active bans.
Equivalent to
.BR "bfd \-l" .
.TP
.BI "bfd ban flush " "temp\fR|\fPall"
Flush temporary or all bans.
Equivalent to
.B \-\-flush\-temp
/
.BR \-\-flush\-all .
.TP
.BI "bfd ban history " \fR[ IP \fR]
Query ban history across current and rotated
.B bans.history
archives.
Supports
.BR \-\-24h ", " \-\-7d ", " \-\-30d
time windows,
.BR \-\-limit= \fIN\fR,
and
.BR \-\-json " / " \-\-csv
output.
.SS "bfd ignore"
.TP
.BI "bfd ignore add " "IP\fR|\fPCIDR \fR[" COMMENT \fR]
Add an IP address or CIDR to the ignore list.
CIDR entries are normalized to the network address (e.g., 10.0.0.5/8
becomes 10.0.0.0/8).
Validates input and rejects duplicates.
.TP
.BI "bfd ignore remove " IP\fR|\fPCIDR
Remove an entry from the ignore list.
.TP
.B "bfd ignore list"
Display all ignore list entries (skips comments and blank lines).
.TP
.BI "bfd ignore check " IP
Check whether an IP is ignored, by exact match or CIDR containment.
Returns exit code 0 if ignored, 1 if not.
.SS "bfd test"
.TP
.BI "bfd test rule " "RULE \fR[" FILE \fR| \fB\- \fR]
Test a rule's patterns against its configured log file, a specific file, or stdin.
Equivalent to
.BR "bfd \-T" .
.TP
.BI "bfd test pattern " "PATTERN \fR[" FILE \fR| \fB\- \fR]
Test a raw
.I <HOST>
pattern.
Equivalent to
.BR \-\-test\-pattern .
.TP
.BI "bfd test alert " TYPE
Send a test alert.
Equivalent to
.BR \-\-test\-alert .
.TP
.BI "bfd test scan " "\fR[" RULE \fR] " \fR[" \-d \fR]
Full-log scan.
Equivalent to
.BR \-\-scan .
.SS "bfd cdn"
CDN/trusted proxy management.
Equivalent to the
.B \-\-cdn
flag variants; see
.B CDN / Trusted Proxy
in OPTIONS above.
.SS "bfd report"
.TP
.BI "bfd report " "\fR[" daily \fR| weekly \fR| monthly \fR]
Generate and deliver a periodic threat report.
Equivalent to
.BR \-\-report .
.SS "bfd status"
.TP
.B "bfd status"
Operational status overview.
Equivalent to
.BR "bfd \-S" .
.TP
.BI "bfd status " SERVICE
Service-specific status.
Equivalent to
.BR "bfd \-S " \fISERVICE\fR .
.TP
.B "bfd status lock"
Display lock state: holder PID, age, and staleness relative to
.BR LOCK_FILE_TIMEOUT .
.TP
.B "bfd status cursors"
Display tlog cursor file positions and ages.
Shows byte offset and last update time for each cursor file.
.TP
.B "bfd status pool"
Display attack pool statistics: total events, unique IPs, age range,
and top 5 IPs by event count.
.TP
.BI "bfd status pressure " \fR[ IP \fR]
Display current pressure scores with exponential decay.
Without an IP argument, shows the top 10 IPs by score.
With an IP argument, shows per-service breakdown and threshold status.
.SH CONFIGURATION
Configuration is in
.BR conf.bfd ,
organized into fourteen sections.
The file is sourced as bash; all values are shell variables.
Additional tuning variables with sensible defaults
.RB ( LOG_SOURCE ", " LOCK_FILE_TIMEOUT ", " BAN_RETRY_COUNT ", " OUTPUT_SYSLOG_FILE )
are in
.BR internals.conf ;
add them to
.B conf.bfd
to override.
.SS Pressure Model (Detection)
BFD uses exponential-decay pressure scoring.
Each failure adds pressure weighted by service severity;
pressure decays over time via a half-life.
A ban fires when accumulated pressure exceeds the trip point.
.TP
.B PRESSURE_TRIP
Accumulated pressure to trigger a ban; must be > 0 (default: 20).
Per-rule overrides in rule files or
.BR pressure.conf .
.TP
.B PRESSURE_HALF_LIFE
Half-life in seconds for pressure decay (default: 300).
Shorter = more forgiving.
.SS Email Alerts
.TP
.B EMAIL_ALERTS
Enable email alerts: 0 or 1 (default: 0).
.TP
.B EMAIL_ADDRESS
Alert recipient; comma-separated for multiple (default: root).
.TP
.B EMAIL_SUBJECT
Alert subject line; $HOSTNAME expands at runtime. Only used when
.B EMAIL_SUBJECT_STYLE=legacy;
the default
.B summary
style builds the subject dynamically.
.TP
.B EMAIL_SUBJECT_STYLE
Subject construction style:
.B summary
(default) produces a dense per-ban line such as
.I "[BFD] ban · sshd · 1.2.3.4 (CN) · host · temp 10m"
for single bans and
.I "[BFD] 3 bans · sshd, dovecot · host"
for multi-ban digests, with
.I ESCALATED
and
.I subnet
verbs flagged inline.
.B legacy
uses
.B EMAIL_SUBJECT
verbatim and appends
.I " (N bans)"
for multi-ban alerts.
.TP
.B EMAIL_LOGLINES
Log lines from the offending service included in each alert and events
view (default: 5).
.TP
.B EMAIL_FORMAT
Email body format:
.B text
(plain text via
.BR mail ),
.B html
(HTML only via
.BR sendmail ),
or
.B both
(multipart text+HTML via
.BR sendmail ).
Falls back to text-only if
.B sendmail
is not available (default: text).
.TP
.B EMAIL_DIGEST
Email digest mode:
.B cycle
(one email per detection run) or
.B timed
(accumulate across runs and send on interval).
Timed mode reduces email volume on active servers (default: cycle).
.TP
.B EMAIL_DIGEST_INTERVAL
Digest flush interval in seconds when
.BR EMAIL_DIGEST = timed
(default: 900 = 15 minutes).
.TP
.B EMAIL_REPUTATION_LINKS
IP reputation lookup links included in alerts, comma-separated.
Available providers:
.BR abuseipdb ", " shodan ", " virustotal ", " ipinfo ", " greynoise .
Leave empty to disable (default: empty).
.SS SMTP Relay
Optional authenticated SMTP relay for outbound email delivery.
Leave
.B SMTP_RELAY
empty to use the local MTA (default).
.TP
.B SMTP_RELAY
SMTP relay server URL.
Examples:
.B smtps://smtp.gmail.com:465
(implicit TLS),
.B smtp://relay.example.com:587
(STARTTLS),
.B smtp://relay.internal:25
(plain, internal relays).
.TP
.B SMTP_FROM
Sender address for relay mode (required when
.B SMTP_RELAY
is set).
.TP
.B SMTP_USER
SMTP authentication username.
.TP
.B SMTP_PASS
SMTP authentication password.
Stored in
.B conf.bfd
(permissions 640, root-owned).
.SS Slack Alerts
Deliver alert notifications to Slack channels.
Requires
.B curl
in PATH.
.TP
.B SLACK_ALERTS
Enable Slack alerts:
.B 1
to enable,
.B 0
to disable (default: 0).
.TP
.B SLACK_MODE
Delivery mode:
.B webhook
(incoming webhook URL) or
.B bot
(Bot API with token + channel; supports file uploads).
Default: webhook.
.TP
.B SLACK_WEBHOOK_URL
Slack incoming webhook URL (required when
.BR SLACK_MODE = webhook ).
Create at
.IR https://api.slack.com/messaging/webhooks .
.TP
.B SLACK_TOKEN
Slack Bot API token, starting with
.B xoxb-
(required when
.BR SLACK_MODE = bot ).
.TP
.B SLACK_CHANNEL
Slack channel ID or
.B #name
(required when
.BR SLACK_MODE = bot ).
.SS Telegram Alerts
Deliver alert notifications via Telegram Bot API.
Requires
.B curl
in PATH.
.TP
.B TELEGRAM_ALERTS
Enable Telegram alerts:
.B 1
to enable,
.B 0
to disable (default: 0).
.TP
.B TELEGRAM_BOT_TOKEN
Telegram bot token from @BotFather (required when
.BR TELEGRAM_ALERTS = 1 ).
.TP
.B TELEGRAM_CHAT_ID
Telegram chat, group, or channel ID (required when
.BR TELEGRAM_ALERTS = 1 ).
.SS Discord Alerts
Deliver alert notifications to Discord channels via webhooks.
Requires
.B curl
in PATH.
.TP
.B DISCORD_ALERTS
Enable Discord alerts:
.B 1
to enable,
.B 0
to disable (default: 0).
.TP
.B DISCORD_WEBHOOK_URL
Discord webhook URL (required when
.BR DISCORD_ALERTS = 1 ).
Create at Server Settings > Integrations > Webhooks.
.SS Banning
.TP
.B FIREWALL
Firewall backend: auto, apf, csf, firewalld, ufw, nftables,
iptables, route, or custom (default: auto).
.TP
.B BAN_TTL
Ban duration in seconds; 0 = permanent (default: 600).
Temporary bans auto-expire and the firewall rule is removed.
.PP
The next four settings form a repeat-offender pipeline:
.BR BAN_ESCALATION
controls how ban duration grows,
.BR BAN_ESCALATION_CAP
limits that growth,
.BR BAN_ESCALATE_AFTER
flips to permanent once the count is reached, and
.BR BAN_ESCALATE_WINDOW
is the lookback window for all of the above.
.TP
.B BAN_ESCALATION
How ban duration grows for repeat offenders: none, linear, or double
(default: none).
.TP
.B BAN_ESCALATION_CAP
Maximum escalated duration in seconds; 0 = no cap (default: 86400).
.TP
.B BAN_ESCALATE_AFTER
Temporary bans before flipping to permanent; 0 = never (default: 5).
.TP
.B BAN_ESCALATE_WINDOW
Lookback window for counting repeat offenses in seconds (default: 86400).
.SS Custom Firewall Commands
Only used when
.BR FIREWALL = custom ;
skip if using auto or a named backend.
Supports
.BR $ATTACK_HOST ", " $MOD ", " $PORTS
variable substitution.
.TP
.B BAN_COMMAND
Command to deny an attacking host.
.TP
.B UNBAN_COMMAND
Command to remove a ban; required for temporary ban auto-expiry.
.TP
.B BAN_COMMAND_V6 ", " UNBAN_COMMAND_V6
IPv6-specific command templates (empty = use standard commands).
.SS Log Paths
.TP
.B AUTH_LOG_PATH
Auth log path (default: /var/log/secure; auto-detected on Debian/Ubuntu).
.TP
.B KERNEL_LOG_PATH
Kernel/messages log path (default: /var/log/messages).
.TP
.B MAIL_LOG_PATH
Mail log path (default: /var/log/maillog).
.TP
.B BFD_LOG_PATH
BFD application log path (default: /var/log/bfd/bfd.log).
Upgraded from v1.x, the legacy /var/log/bfd_log is automatically symlinked.
.SS Advanced
.TP
.B PRESSURE_TRIP_GLOBAL
Cross-service aggregate pressure trip point (default: 0, disabled).
.TP
.B SUBNET_TRIG
Unique IPs from same subnet to trigger subnet ban (default: 0, disabled).
.TP
.B SUBNET_MASK
IPv4 subnet mask for distributed detection, 8\-32 (default: 24).
.TP
.B SUBNET_MASK_V6
IPv6 subnet mask, multiple of 16 (default: 48).
.TP
.B WATCH_INTERVAL
Watch mode polling interval in seconds (default: 10).
.TP
.B SCAN_MAX_LINES
Maximum lines per log file during scan mode; 0 = unlimited (default: 50000).
Override with
.BR \-\-max\-lines= .
.TP
.B SCAN_TIMEOUT
Journal read timeout in seconds per rule during scan mode (default: 120).
Override with
.BR \-\-scan\-timeout= .
.TP
.B OUTPUT_SYSLOG
Echo BFD log messages to syslog: 0 or 1 (default: 1).
.TP
.B LOG_IDLE_SUPPRESS
Suppress idle (zero\-event) run\-complete messages from syslog: 0 or 1
(default: 1).
When enabled, zero\-event cycles are still recorded in
.B BFD_LOG_PATH
but do not echo to syslog.
Cycles with events always log to both regardless of this setting.
Reduces syslog noise by ~8,640 lines/day in watch mode.
.TP
.B LOG_FORMAT
Log output format (default: classic).
.B classic
produces traditional syslog\-style lines.
.B json
produces one JSON object per line (JSONL) with fields:
.IR ts ", " host ", " app ", " pid ", " level ", " tag " (optional), " msg .
Suitable for ELK, Graylog, or similar log aggregation systems.
.TP
.B LOG_LEVEL
Minimum log severity threshold (default: 1).
0\ =\ debug, 1\ =\ info, 2\ =\ warn, 3\ =\ error.
Messages below the threshold are suppressed.
Debug messages are stdout\-only and controlled by
.B \-\-verbose
rather than
.BR LOG_LEVEL .
.SS Attack Pool
.TP
.B APOOL_RETENTION_DAYS
Maximum age in days for attack pool entries (default: 365).
Entries older than this are pruned by
.BR cron.daily .
.TP
.B APOOL_MAX_LINES
Maximum number of lines in the attack pool file (default: 500000).
When exceeded, the oldest entries are removed by
.BR cron.daily .
.SS Periodic Reports
.TP
.B REPORT_ENABLED
Enable periodic threat reports (default: 0).
When set to 1 and
.B cron.daily
is active, reports are generated and delivered on configured intervals.
.TP
.B REPORT_INTERVALS
Comma-separated list of intervals to generate (default: "daily").
Valid values: daily, weekly, monthly.
.TP
.B REPORT_CHANNELS
Comma-separated list of delivery channels (default: "" = all enabled alert channels).
Valid values: email, slack, telegram, discord.
When empty, reports are delivered to all channels enabled for ban alerts.
.TP
.B REPORT_EMAIL_ADDRESS
Report email recipient (default: "" = use EMAIL_ADDRESS).
.TP
.B REPORT_EMAIL_SUBJECT
Email subject template (default: "BFD {{INTERVAL}} Threat Report for {{HOSTNAME}}").
.B {{INTERVAL}}
and
.B {{HOSTNAME}}
are expanded at send time.
.TP
.B REPORT_TOP_N
Maximum IPs to include in report tables (default: 25).
.SS "CDN / Trusted Proxy"
When enabled, BFD loads
.B cdn\-providers.conf
and applies per-provider treatment (ignore, exclude, or derate) to matching
source IPs before they enter the detection pipeline.
.TP
.B CDN_ENABLE
Enable CDN/trusted proxy IP awareness: auto, 0, or 1 (default: auto).
When set to \fBauto\fR, CDN processing is enabled if cdn\-providers.conf
contains any uncommented provider entries.
.TP
.B CDN_UPDATE_DAYS
How often to refresh provider IP ranges in days; 0 = never auto-refresh
(default: 7).
.PP
Provider configuration is in
.BR cdn\-providers.conf .
Each line defines a provider with fields:
.BR NAME ", " TREATMENT ", " MULT ", " FORMAT ", " URL_V4 ", " URL_V6 .
.PP
Treatment modes:
.B ignore
(pre-filter, invisible to detection),
.B exclude
(visible in logs, never banned), or
.B derate
(reduced pressure via multiplier).
Lines beginning with
.B #
are inactive; uncomment to enable a provider.
Five providers are pre-configured: Cloudflare, AWS CloudFront, Fastly,
Google Cloud, and Akamai.
.SS "Country Weighting"
Per-country pressure multipliers adjust detection sensitivity based on
geographic origin.
Activation is automatic when
.B pressure\-country.conf
contains uncommented entries.
.PP
.B pressure\-country.conf
format: one entry per line,
.IR "CC N" ,
where
.I CC
is a two-letter ISO 3166-1 country code and
.I N
is the weight multiplied by 10 (e.g., 15 = 1.5\(mu).
Legacy
.I CC=N
format is also accepted for backward compatibility.
.PP
Country lookup uses
.B ipcountry.dat
(IPv4 integer-range format) and
.B ipcountry6.dat
(IPv6 hex-range format), rebuilt by
.BR update\-ipcountry.sh .
.SH ALERT TEMPLATES
Alert messages are rendered from customizable template partials in the
.B alert/
directory under the BFD install path.
Templates use
.B {{VAR}}
mustache-style placeholders replaced at render time via a safe
awk-based engine (no shell code execution).
.PP
Twenty-one partials are provided across three categories:
.PP
.B Email templates
(4 plain text + 4 HTML):