- Ubuntu 20.04
- nextcloud, fail2ban and e.g. iptables are installed
Finally since 29 Juli 2020 this procedure is a part of an official Nextcloud Documentation. Please follow the link: https://docs.nextcloud.com/server/latest/admin_manual/installation/harden_server.html#setup-fail2ban
Install fail2ban:
sudo apt update && sudo apt install fail2ban -y
Create the Nextcloud-filter:
sudo nano /etc/fail2ban/filter.d/nextcloud.conf
Paste the following lines, this will cover GUI Failed login and WebDAV:
[Definition]
_groupsre = (?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)
failregex = ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
datepattern = ,?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"
If you want to protect also from direct IP access or wrong Domain name access configure it as below (as per https://github.com/nextcloud/vm/blob/master/apps/fail2ban.sh)
[Definition]
_groupsre = (?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)
failregex = ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Trusted domain error.
datepattern = ,?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"
Create a new jail:
sudo nano /etc/fail2ban/jail.d/nextcloud.local
Paste the following rows:
[nextcloud]
backend = auto
enabled = true
port = 80,443
protocol = tcp
filter = nextcloud
#Number of retrys before to ban
maxretry = 3
#time in seconds
bantime = 36000
findtime = 36000
#Log path, on Ubuntu usually is following
logpath = /var/www/nextcloud/data/nextcloud.log
#For Univention Appliances the logfile is in /var/lib/univention-appcenter/apps/nextcloud/data/nextcloud-data/nextcloud.log
#logpath = /var/lib/univention-appcenter/apps/nextcloud/data/nextcloud-data/nextcloud.log
Re-start the fail2ban-service:
sudo service fail2ban restart
and enjoy your Nextcloud-Server!
Pattern For GUI:
#Nextcloud 17+
{"reqId":"BRHKHyh1lVFon5D33u4K","level":2,"time":"2020-01-13T12:34:00+00:00","remoteAddr":"10.11.12.13","user":"--","app":"no app in context","method":"POST","url":"\/index.php\/login","message":"Login failed: Tralololjlkl (Remote IP: 10.11.12.13)","userAgent":"Mozilla\/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko\/20100101 Firefox\/72.0","version":"17.0.2.1"}
{"reqId":"y6OUpenieOevULRMaAFi","level":1,"time":"2020-06-10T13:19:06+00:00","remoteAddr":"10.11.12.13","user":"--","app":"core","method":"GET","url":"/","message":"Trusted domain error. \"10.11.12.13\" tried to access using \"Trololo.com\" as host.","userAgent":"curl/7.58.0","version":"18.0.6.0"}
#Nextcloud <= 16
{"reqId":"bFnTdevf7ZdCMQ5ddmNl","level":2,"time":"2019-04-03T21:49:30+00:00","remoteAddr":"10.11.12.13","user":"--","app":"core","method":"POST","url":"\/index.php\/login","message":"Login failed: 'Tralololjlkl' (Remote IP: '10.11.12.13')","userAgent":"Mozilla\/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko\/20100101 Firefox\/66.0","version":"15.0.5.3"}
For WebDav:
#Nextcloud 17+
{"reqId":"lqdbtb7y3pZSv8sGM0mD","level":2,"time":"2020-01-26T22:20:32+00:00","remoteAddr":"10.11.12.13","user":"--","app":"core","method":"PUT","url":"\/remote.php\/webdav\/files","message":"Login failed: 'webdavlogin' (Remote IP: '10.11.12.13')","userAgent":"curl\/7.58.0","version":"17.0.2.1"}
#Nextcloud <= 16
{"reqId":"Q4wX3I4LOUeuMV4wRK91","level":2,"time":"2019-04-03T22:14:11+00:00","remoteAddr":"10.11.12.13","user":"--","app":"core","method":"GET","url":"\/remote.php\/dav\/files","message":"Login failed: 'test' (Remote IP: '10.11.12.13')","userAgent":"Mozilla\/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko\/20100101 Firefox\/66.0","version":"15.0.5.3"}
Test WebUI and Webdav and Trusted domain error.
# fail2ban-regex /var/nextcloud/data/nextcloud.log /etc/fail2ban/filter.d/nextcloud.local -v --print-all-matched
Running tests
=============
Use failregex filter file : nextcloud, basedir: /etc/fail2ban
Use datepattern : ,?\s*"time"\s*:\s*"Year-Month-Day[T ]24hour:Minute:Second(Zone offset)?"
Use log file : /var/nextcloud/data/nextcloud.log
Use encoding : UTF-8
Results
=======
Failregex: 3 total
|- #) [# of hits] regular expression
| 1) [2] ^\{(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*),?\s*"remoteAddr":"<HOST>"(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*),?\s*"message":"Login failed:
| 10.11.12.13 Wed Jun 10 13:07:43 2020
| 10.11.12.13 Wed Jun 10 13:07:50 2020
| 2) [1] ^\{(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*),?\s*"remoteAddr":"<HOST>"(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*),?\s*"message":"Trusted domain error.
| 10.11.12.13 Wed Jun 10 15:19:06 2020
`-
Ignoreregex: 0 total
Date template hits:
|- [# of hits] date format
| [1654] ,?\s*"time"\s*:\s*"Year-Month-Day[T ]24hour:Minute:Second(Zone offset)?"
`-
Lines: 1654 lines, 0 ignored, 3 matched, 1651 missed
[processed in 0.61 sec]
|- Matched line(s):
| {"reqId":"2uzhhzlkkzXEp9yICWXE","level":2,"time":"2020-06-10T11:07:43+00:00","remoteAddr":"10.11.12.13","user":"--","app":"no app in context","method":"POST","url":"/index.php/login","message":"Login failed: Gggggg (Remote IP: 10.11.12.13)","userAgent":"Mozilla/5.0 (Android 9; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0","version":"18.0.6.0"}
| {"reqId":"2QPK9SkSVBj6r2d9ojnk","level":2,"time":"2020-06-10T11:07:50+00:00","remoteAddr":"10.11.12.13","user":"--","app":"no app in context","method":"POST","url":"/index.php/login","message":"Login failed: Gggggvvvvg (Remote IP: 10.11.12.13)","userAgent":"Mozilla/5.0 (Android 9; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0","version":"18.0.6.0"}
| {"reqId":"y6OUpenieOevULRMaAFi","level":1,"time":"2020-06-10T13:19:06+00:00","remoteAddr":"10.11.12.13","user":"--","app":"core","method":"GET","url":"/","message":"Trusted domain error. \"10.11.12.13\" tried to access using \"Trololo.com\" as host.","userAgent":"curl/7.58.0","version":"18.0.6.0"}
`-
Missed line(s): too many to print. Use --print-all-missed to print all 1651 lines
@datdomse you are right, I check source code of NC and it seems that it is producing different logs output depends on different issues. This is not the best practice how to implement it.
I added 2nd line to enable checks of WebDav in a config and also test. Thanks you for reporting.