In the setup I've right now I've NGINX that works as proxy for (serveral) internal VMs. Now, I would like to protect these VMs from bruteforce, such that, if there's a huge amount of 401 the IP should be blocked.
I've google around on how to use fail2ban, but I can't figure out how it can work in my case.
The access.log
of nginx looks like this (i've hidden some sensitive infos)
148.XXX.XXX.XXX - 92....396 [09/Jan/2017:13:43:32 +0100] "POST /v1/schemas/7...b8/documents HTTP/1.1" 200 364 "-" "python-requests/2.10.0"
148.XXX.XXX.XXX - 92....396 [09/Jan/2017:13:43:32 +0100] "DELETE /v1/documents/fd7...09e1?force=true HTTP/1.1" 200 83 "-" "python-requests/2.10.0"
148.XXX.XXX.XXX - 92....396 [09/Jan/2017:13:43:32 +0100] "GET /v1/schemas/713e4ee8-...b8/documents HTTP/1.1" 200 6689 "-" "python-requests/2.10.0"
47.XXX.XXX.XXX - - [09/Jan/2017:13:43:33 +0100] "GET /wp-login.php HTTP/1.1" 301 178 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
47.XXX.XXX.XXX - - [09/Jan/2017:13:43:39 +0100] "GET /wp-login.php HTTP/1.1" 301 178 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
47.XXX.XXX.XXX - - [09/Jan/2017:13:43:44 +0100] "GET / HTTP/1.1" 301 178 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
148.XXX.XXX.XXX - 92....396 [09/Jan/2017:13:44:33 +0100] "GET /v1/schemas/713e4e...d649b8/documents HTTP/1.1" 200 6689 "-" "python-requests/2.10.0"
148.XXX.XXX.XXX - 92....396 [09/Jan/2017:13:44:33 +0100] "POST /v1/schemas/713e4..fd649b8/documents HTTP/1.1" 200 364 "-" "python-requests/2.10.0"
148.XXX.XXX.XXX - 92....396 [09/Jan/2017:13:44:33 +0100] "DELETE /v1/documents/9f5....cadf29031c?force=true HTTP/1.1" 200 83 "-" "python-requests/2.10.0"
148.XXX.XXX.XXX - 92....396 [09/Jan/2017:13:44:33 +0100] "GET /v1/schemas/713e...649b8/documents HTTP/1.1" 200 6689 "-" "python-requests/2.10.0"
87.XXX.XXX.XXX - {{customerId [09/Jan/2017:13:45:08 +0100] "GET /v1/repositories HTTP/1.1" 401 101 "-" "PostmanRuntime/3.0.9"
87.XXX.XXX.XXX - {{customerId [09/Jan/2017:13:45:09 +0100] "GET /v1/repositories HTTP/1.1" 401 101 "-" "PostmanRuntime/3.0.9"
87.XXX.XXX.XXX - test [09/Jan/2017:13:45:20 +0100] "GET /v1/repositories HTTP/1.1" 401 101 "-" "PostmanRuntime/3.0.9"
As you can see, NGINX works as proxy for the service and for the website and other services. What i would like to prevent are the last 3 lines, where the return code is 401.
As far I understood (mostly from here) I could make a regexp to intercept that lines that contains a 401, setting a burstime of 3600 (60 mins lock) and retries of 100. So that 100 errors per hours are permitted.
Note: I've to figure out this value (any idea?), it may happen that someone gets 401 every now and then.
Yet, I know the thoery but not yet the practice. Can someone help me in setting this up especially on how to write the regexp for that condition.
I came up with ^
but don't know if it's enough and I would like to avoid to block everybody by mistake.
After finding the regexp, I should add this rule to a file (let's call it nginx-401.conf
under /etc/fail2ban/filter.d/
that will look like
[Definition]
failregex = ^<HOST> -.* 401
ignoreregex =
and in jail.conf
[nginx-401]
enabled = true
action = iptables-multiport[name=NoProxy, port="http,https"] # no idea of this, copied from somewhere else. what should I put here?
filter = nginx-401 # should be the file name
logpath = /var/log/nginx*/*access*.log
maxretry = 100 # my limit
bantime = 3600 # 1 hour
Here I don't really have idea of what action
should be and if the rest is set up correctly.
В конце концов, похоже, это сработало, вот мой конфет только для справки:
/etc/fail2ban/filter.d/wrongauth.conf
[Definition]
failregex = ^<HOST> -.* 401
ignoreregex =
в /etc/fail2ban/jail.con
[wrongauth]
enabled = true
filter = wrongauth
action = shorewall
%(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s", sendername="%(sendername)s"]
logpath = /var/log/nginx*/*access*.log
banTime = 600 # 10 minutes
findTime = 60
maxretry = 60
В качестве действия я использую shorewall, а для отправки электронного письма при возникновении блокировки мне пришлось измените действие в соответствии с настройками, которые вы видите.
Сама страница диалога входа возвращается с кодом 401.
Неудачные входы регистрируются синтаксисом:
<host> - <user> [06/Jun/2018:11:18:55 +0300] "GET / HTTP/1.1" 401 ...
...где данное имя пользователя находится в '
[Definition]
failregex = ^<HOST> - [^-[ ]+.+HTTP/1.[0-9]" 401
ignoreregex =
Этот регекс не будет совпадать с попытками входа с пустым именем пользователя. В этом случае имя пользователя будет '-', что неотделимо от страницы диалога входа в систему.
.