Fail2Ban with named and systemd on Debian 10

default in Debian 10 named is logging to systemd. Latest filter in fail2ban: https://github.com/fail2ban/fail2ban/blob/master/config/filter.d/named-refused.conf

is working only with /var/log/named/security.log. I prepared my own filter, it is working, but it's quit ugly :). Works only with "client*denied". Can someone help me to make it works like original one, bad zone transfer etc.

/etc/fail2ban/filter.d/named-refused.conf:

[INCLUDES]
before = common.conf
[DEFAULT]
[Definition]
prefregex = ^<F-MLFID>%(__prefix_line)s</F-MLFID><F-CONTENT>.+</F-CONTENT>$
failregex = ^client @\S* <HOST>#\S.* denied$
ignoreregex =
maxlines = 1
journalmatch = _SYSTEMD_UNIT=bind9.service
datepattern = {^LN-BEG}

Solution 1:

Why the stock filter does not work for you (you did not provide how your messages in journal do look)...

Basically you can rewrite every parameter in the stock filter by supplying them from the jail.
For example:

[named-refused]
filter = %(known/filter)s[__line_prefix="\s*\S+\s+named\[\d+\]:", journalmatch="_SYSTEMD_UNIT=bind9.service"]

So if your systemd-journal entries look like this:

Mar 24 12:47:28 srv named[3935]: client 192.0.2.1#33081: query (cache) 'example.com/NS/IN' denied
Mar 24 12:47:28 srv named[2954]: client 192.0.2.2#56275: zone transfer 'example.com/AXFR/IN' denied
Mar 24 12:47:28 srv named[2809]: client @0x7f6450002ef0 192.0.2.3#23332 (example.com): bad zone transfer request: 'test.com/IN': non-authoritative zone (NOTAUTH)

But normally the original filter must be suitable for jornal too (just need journalmatch for better handling). Below is the example with aforemontioned excerpt (logtype=journal is optional, it is set in newest fail2ban versions for journal monitoring in order to simplify common prefix-line):

$ fail2ban-regex /tmp/log 'named-refused[logtype=journal]'

Running tests
=============

Use   failregex filter file : named-refused
Use   filter options : {'logtype': 'journal'}
Use         log file : /tmp/log
Use         encoding : UTF-8


Results
=======

Prefregex: 3 total
|  ^(?:\s*\S+ (?:(?:\[\d+\])?:\s+\(?named(?:\(\S+\))?\)?:?|\(?named(?:\(\S+\))?\)?:?(?:\[\d+\])?:)\s+)?(?: error:)?\s*client(?: @\S*)? (?:\[?(?:(?:::f{4,6}:)?(?P<ip4>(?:\d{1,3}\.){3}\d{1,3})|(?P<ip6>(?:[0-9a-fA-F]{1,4}::?|::){1,7}(?:[0-9a-fA-F]{1,4}|(?<=:):)))\]?|(?P<dns>[\w\-.^_]*\w))#\S+(?: \([\S.]+\))?: (?P<content>.+)\s(?:denied|\(NOTAUTH\))\s*$
`-

Failregex: 3 total
|-  #) [# of hits] regular expression
|   1) [1] ^(?:view (?:internal|external): )?query(?: \(cache\))?
|   2) [1] ^zone transfer
|   3) [1] ^bad zone transfer request: '\S+/IN': non-authoritative zone
`-

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
|  [3] {^LN-BEG}(?:DAY )?MON Day %k:Minute:Second(?:\.Microseconds)?(?: ExYear)?
`-

Lines: 3 lines, 0 ignored, 3 matched, 0 missed

To check it works over your journal you can use this one:

# stock parameters, only journal match:
fail2ban-regex systemd-journal 'named-refused[journalmatch="_SYSTEMD_UNIT=bind9.service"]'

# overwritten __line_prefix and set journalmatch:
fail2ban-regex systemd-journal 'named-refused[__line_prefix="\s*\S+\s+named\[\d+\]:", journalmatch="_SYSTEMD_UNIT=bind9.service"]'