2
votes

Im trying to use fail2ban to block IP addresses of sources that have too many login attempts through the UI. fail2ban is working properly for sshd but it is not working with my custom filter for gitlab access logs.

System

  • ubuntu server 16.04.4 LTS
  • gitlab 10.8.4
  • fail2ban 0.9.3

Access Log Permission/path

-rw-r--r-- 1 root root 186726 Jun 21 09:54 /var/log/gitlab/nginx/gitlab_access.log

Access Log Example to ban

192.168.1.2 - - [21/Jun/2018:09:52:06 -0400] "POST /users/sign_in HTTP/2.0" 200 4199 "https://example.com:88/users/sign_in" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"

fail2ban config

/etc/fail2ban/jail.conf

[nginx-gitlab]

enabled  = true
port     = http,https
filter   = nginx-gitlab
logpath  = /var/log/gitlab/nginx/gitlab_access.log
maxretry = 3

fail2ban filter

/etc/fail2ban/filter.d/nginx-gitlab.conf

# Fail2Ban configuration file
#
# Author: Deac Karns 
#

[Definition]


failregex = ^<HOST> – -.*”POST /users/sign_in HTTP.*” 200.*$

ignoreregex =

fail2ban-regex test output

sudo fail2ban-regex /var/log/gitlab/nginx/gitlab_access.log /etc/fail2ban/filter.d/nginx-gitlab.conf


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

Use   failregex filter file : nginx-gitlab, basedir: /etc/fail2ban
Use         log file : /var/log/gitlab/nginx/gitlab_access.log
Use         encoding : UTF-8


Results
=======

Failregex: 0 total

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
|  [1147] Day(?P<_sep>[-/])MON(?P=_sep)Year[ :]?24hour:Minute:Second(?:\.Microseconds)?(?: Zone offset)?
`-

Lines: 1147 lines, 0 ignored, 0 matched, 1147 missed [processed in 0.06 sec] 
Missed line(s): too many to print.  Use --print-all-missed to print all 1147 lines
2
it might be the quotes " in your regex isn't right. I suggest using the fail2ban-regex -D and include your single line of failure. Are you sure this POST wont' occur on a successful login? Read FILTERS for avoiding DDoS because of excessively broad regexes. - danblack

2 Answers

2
votes

You have wrong characters inside your filter. Did you write it manually? You should rather instead copy&paste the log you want to match so that you avoid typing similar characters.

First wrong character is the hyphen.

  • you have written ^<HOST> – -
  • but it is expected ^<HOST> - -

Another wrong characters are double quotes as pointed by @danblack's comment.

  • you have written .*”POST /users/sign_in HTTP.*” 200.*$
  • but it is expected .*"POST /users/sign_in HTTP.*" 200.*$

And finally let me suggest you to add a comment into your filter regarding the matched status code 200, which seems to be absolutely valid and it's presence may become very confusing. It would be appropriate to state that we are considering status code 200 as failed login attempt because if it was successful, it would be 302 (redirection instead).

Fixed version of the filter

/etc/fail2ban/filter.d/nginx-gitlab.conf

# Fail2Ban configuration file
#
# Authors: Deac Karns & jirislav
#

[Definition]

# We are considering status code 200 as failed login attempt 
# because if it was successfull, it would be 302
failregex = ^<HOST> - -.*"POST /users/sign_in HTTP.*" 200.*$

ignoreregex =
0
votes

Some of your characters required escaping them. I also improved the expression with more anchors to make it more secure. Try this

failregex = ^<HOST> - - \[.+\] \"POST \/users\/sign_in HTTP\/.+\".*\b\"$

You can test it at: regex101.com replace with:

^(\d+.\d+.\d+.\d+) - - \[.+\] \"POST \/users\/sign_in HTTP\/.+\".*\b\"$