Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Harden Nextcloud 17+ with Fail2Ban, GUI and WebDAV - Ubuntu 18.04

Short how-to harden your Nextcloud Server with 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]
failregex=^{.*Login failed: .* \(Remote IP: <HOST>\).*}$
          ^{.*Login failed: .* \(Remote IP: '<HOST>'\).*}$
ignoreregex =

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]
failregex=^{.*Login failed: .* \(Remote IP: <HOST>\).*}$
          ^{.*Login failed: .* \(Remote IP: '<HOST>'\).*}$
          ^.*\"remoteAddr\":\"<HOST>\".*Trusted domain error.*\$
ignoreregex =

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 following
logpath = /var/www/nextcloud/data/nextcloud.log

Re-start the fail2ban-service:

sudo service fail2ban restart

and enjoy your Nextcloud-Server!

P.S. 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"}

#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

fail2ban-regex /var/nextcloud/data/nextcloud.log /etc/fail2ban/filter.d/nextcloud.conf --print-all-matched

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

Use   failregex filter file : Nextcloud, basedir: /etc/fail2ban
Use         log file : /var/nextcloud/data/nextcloud.log
Use         encoding : UTF-8


Results
=======

Failregex: 1 total
|-  #) [# of hits] regular expression
|   1) [1] ^{.*Login failed: .* \(Remote IP: <HOST>\).*}$
`-

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
|  [355] ExYear(?P<_sep>[-/.])Month(?P=_sep)Day(?:T|  ?)24hour:Minute:Second(?:[.,]Microseconds)?(?:\s*Zone offset)?
`-

Lines: 355 lines, 0 ignored, 1 matched, 354 missed
[processed in 1.40 sec]

|- Matched line(s):
|  {"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"}
`-
Missed line(s): too many to print.  Use --print-all-missed to print all 354 lines

WebDav

# fail2ban-regex /var/log/nextcloud.log /etc/fail2ban/filter.d/nextcloud.conf --print-all-matched

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

Use   failregex filter file : Nextcloud, basedir: /etc/fail2ban
Use         log file : /var/log/nextcloud.log
Use         encoding : UTF-8


Results
=======

Failregex: 1 total
|-  #) [# of hits] regular expression
|   2) [1] ^{.*Login failed: .* \(Remote IP: '<HOST>'\).*}$
`-

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
|  [1927] ExYear(?P<_sep>[-/.])Month(?P=_sep)Day(?:T|  ?)24hour:Minute:Second(?:[.,]Microseconds)?(?:\s*Zone offset)?
`-

Lines: 1927 lines, 0 ignored, 1 matched, 1926 missed
[processed in 7.41 sec]

|- Matched line(s):
|  {"reqId":"3wZljW4tZahOCJD8DMpq","level":2,"time":"2020-02-27T10:57:25+00:00","remoteAddr":"192.168.0.10","user":"--","app":"core","method":"COPY","url":"\/remote.php\/webdav\/file","message":"Login failed: 'blabla' (Remote IP: '192.168.0.10')","userAgent":"curl\/7.58.0","version":"17.0.3.1"}
`-
Missed line(s): too many to print.  Use --print-all-missed to print all 1926 lines
@tiagofreire-pt

This comment has been minimized.

Copy link

tiagofreire-pt commented Jul 18, 2019

For Univention Appliances the logfile is in: /var/lib/univention-appcenter/apps/nextcloud/data/nextcloud-data/nextcloud.log

@badgateway666

This comment has been minimized.

Copy link

badgateway666 commented Jan 8, 2020

The Pattern did change: There are no '' around the login-name and the ip anymore.

[Definition]
failregex=^{.Login failed: . (Remote IP: ).*}$
ignoreregex =

@GAS85

This comment has been minimized.

Copy link
Owner Author

GAS85 commented Jan 13, 2020

Thanks!
Did it changed for Trusted Domain error also?

@stucksubstitute

This comment has been minimized.

Copy link

stucksubstitute commented Jan 26, 2020

The pattern doesn't work. See i.e. here. Any suggestions?

@GAS85

This comment has been minimized.

Copy link
Owner Author

GAS85 commented Jan 26, 2020

The pattern doesn't work. See i.e. here. Any suggestions?

Could you please try it? What you provide is independend of this solution. I will try to push correction into nextcloudpi repo --> nextcloud/nextcloudpi#1070

@datdomse

This comment has been minimized.

Copy link

datdomse commented Feb 27, 2020

The Pattern doesn't work with webdav.
I used this from here.

[Definition] failregex = ^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)","level":2,"time":".*"}$ ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","app":"core".*","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)".*}$ ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: .* \(Remote IP: <HOST>\).*}$ ignoreregex =

Now it finally works with Nextcloud 18 stable.

@GAS85

This comment has been minimized.

Copy link
Owner Author

GAS85 commented Feb 27, 2020

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.