Brute force protection triggered too often by CalDAV app

Hi,

i have a strange issue with my nextcloud instance and the brute force detection. Somehow, the BF detection gets triggered quite often. But from my point of view this seems to be false positives.
I am using Nextcloud 13.0.0 together with my Android smartphone to synchronize my calendar and contacts with CalDAV-Sync and CardDAV-Sync from the play store. I have setup one-time passwords for both apps. Somehow the brute force detection seems to kick in, when my CalDAV app tries to sync the calendar. I am getting an unauthorized notification on my mobile. When i tap on the notification i am prompted to enter a new password. Afterwards each time i setup a new one time password just for the CalDAV sync app.
Each time this happens i have four new rows in the table ‘oc_bruteforce_attempts’

917 login 1519738600 172.23.xx.yy 172.23.xx.yy/32 {"uid":"Michael"} 
918 login 1519738600 172.23.xx.yy 172.23.xx.yy/32 {"uid":"Michael"} 
919 login 1519738601 172.23.xx.yy 172.23.xx.yy/32 {"uid":"Michael"} 
920 login 1519738601 172.23.xx.yy 172.23.xx.yy/32 {"uid":"Michael"} 

The IP address is from the docker host network bridge. I have tried add this IP address to the trusted_proxies array in my config.php, but still the real IP seems not to be resolved and the BF protection still kicks in. Currently i have the IP address of my Synology NAS on which the docker host is running (192.168.xx.yy)

I have found one strange exception in the log stating, that “the request is not allowed to access the file system”. Well, yes i have disabled the access to the file system for the CalDAV-Sync app in my security settings.

I think the issue is, that the user client IP address cannot be resolved, and every request contains the IP address of the docker host.

But how do i configure nextcloud or nginx to resolve correctly the client’s ip address. I have already studies the nextcloud manual, and tried to add all required settings to my nginx.conf. Please find attached logs and configuration files.

Does anyone have a hint for me?

Thanks in Advance,

Michael


Synology DSM 6.1.5-15254 Update 1
Synology LDAP Directory Server 2.2.0-2461
Synology Docker 17.05.0-0367
Nextcloud version 13.0.0.0:
Operating system and version : docker image hoellen/nextcloud Based on Alpine Linux
Apache or nginx version (eg, Apache 2.4.25): PHP 7.1
PHP version (eg, 7.1): PHP 7.1

The issue you are facing:

constant trigger of brute force throtteling by Android app CalDAV-Sync (dmfs GmbH)

Is this the first time you’ve seen this error? (Y/N): N

Steps to replicate it:

  1. Setup CalDAV-Sync app with one time password
  2. run CalDAV sync manually
  3. check the table ‘oc_bruteforce_attempts’

The output of your Nextcloud log in Admin > Logging:

{"reqId"
"siz4U6Pu2lsmJTdBQ8Og","level"
3,"time"
"2018-01-30 20
11
57","remoteAddr"
"172.21.0.1","user"
"Michael","app"
"no app in context","method"
"OPTIONS","url"
"/remote.php/dav/addressbooks/users/Michael/Kontakte/","message"
"Exception
 {\"Exception\"
\"OC\\ForbiddenException\",\"Message\"
\"This request is not allowed to access the filesystem\",\"Code\"
0,\"Trace\"
\"#0 /nextcloud/lib/private/Files/View.php(1156)
 OC\\Lockdown\\Filesystem\\NullStorage->mkdir('files_encryptio...')\n#1 /nextcloud/lib/private/Files/View.php(269)
 OC\\Files\\View->basicOperation('mkdir', '/Michael/files_...', Array)\n#2 /nextcloud/lib/private/Encryption/Keys/Storage.php(370)
 OC\\Files\\View->mkdir('/Michael/files_...')\n#3 /nextcloud/lib/private/Encryption/Keys/Storage.php(230)
 OC\\Encryption\\Keys\\Storage->keySetPreparation('/Michael/files_...')\n#4 /nextcloud/lib/private/Encryption/Keys/Storage.php(115)
 OC\\Encryption\\Keys\\Storage->setKey('/Michael/files_...', '-----BEGIN PUBL...')\n#5 /nextcloud/apps/encryption/lib/KeyManager.php(287)
 OC\\Encryption\\Keys\\Storage->setUserKey('Michael', 'publicKey', '-----BEGIN PUBL...', 'OC_DEFAULT_MODU...')\n#6 /nextcloud/apps/encryption/lib/KeyManager.php(246)
 OCA\\Encryption\\KeyManager->setPublicKey('Michael', '-----BEGIN PUBL...')\n#7 /nextcloud/apps/encryption/lib/Users/Setup.php(77)
 OCA\\Encryption\\KeyManager->storeKeyPair('Michael', 'WHY IS MY PASSWORD VISIBLE IN THE LOGS???', Array)\n#8 /nextcloud/apps/encryption/lib/Hooks/UserHooks.php(183)
 OCA\\Encryption\\Users\\Setup->setupUser('Michael', 'WHY IS MY PASSWORD VISIBLE IN THE LOGS???')\n#9 /nextcloud/lib/private/legacy/hook.php(106)
 OCA\\Encryption\\Hooks\\UserHooks->login(*** sensitive parameters replaced ***)\n#10 /nextcloud/lib/private/Server.php(363)
 OC_Hook

emit('OC_User', 'post_login', Array)\n#11 [internal function]
 OC\\Server->OC\\{closure}(Object(OC\\User\\User), 'WHY IS MY PASSWORD VISIBLE IN THE LOGS???')\n#12 /nextcloud/lib/private/Hooks/EmitterTrait.php(99)
 call_user_func_array(Object(Closure), Array)\n#13 /nextcloud/lib/private/Hooks/PublicEmitter.php(33)
 OC\\Hooks\\BasicEmitter->emit('\OC\User', 'postLogin', Array)\n#14 /nextcloud/lib/private/User/Session.php(359)
 OC\\Hooks\\PublicEmitter->emit('\OC\User', 'postLogin', Array)\n#15 /nextcloud/lib/private/User/Session.php(591)
 OC\\User\\Session->completeLogin(*** sensitive parameters replaced ***)\n#16 /nextcloud/lib/private/User/Session.php(324)
 OC\\User\\Session->loginWithToken('Q826P-386NH-W2q...')\n#17 /nextcloud/lib/private/User/Session.php(400)
 OC\\User\\Session->login(*** sensitive parameters replaced ***)\n#18 /nextcloud/apps/dav/lib/Connector/Sabre/Auth.php(129)
 OC\\User\\Session->logClientIn(*** sensitive parameters replaced ***)\n#19 /nextcloud/3rdparty/sabre/dav/lib/DAV/Auth/Backend/AbstractBasic.php(105)
 OCA\\DAV\\Connector\\Sabre\\Auth->validateUserPass(*** sensitive parameters replaced ***)\n#20 /nextcloud/apps/dav/lib/Connector/Sabre/Auth.php(252)
 Sabre\\DAV\\Auth\\Backend\\AbstractBasic->check(Object(Sabre\\HTTP\\Request), Object(Sabre\\HTTP\\Response))\n#21 /nextcloud/apps/dav/lib/Connector/Sabre/Auth.php(154)
 OCA\\DAV\\Connector\\Sabre\\Auth->auth(Object(Sabre\\HTTP\\Request), Object(Sabre\\HTTP\\Response))\n#22 /nextcloud/3rdparty/sabre/dav/lib/DAV/Auth/Plugin.php(201)
 OCA\\DAV\\Connector\\Sabre\\Auth->check(Object(Sabre\\HTTP\\Request), Object(Sabre\\HTTP\\Response))\n#23 /nextcloud/3rdparty/sabre/dav/lib/DAV/Auth/Plugin.php(150)
 Sabre\\DAV\\Auth\\Plugin->check(Object(Sabre\\HTTP\\Request), Object(Sabre\\HTTP\\Response))\n#24 [internal function]
 Sabre\\DAV\\Auth\\Plugin->beforeMethod(Object(Sabre\\HTTP\\Request), Object(Sabre\\HTTP\\Response))\n#25 /nextcloud/3rdparty/sabre/event/lib/EventEmitterTrait.php(105)
 call_user_func_array(Array, Array)\n#26 /nextcloud/3rdparty/sabre/dav/lib/DAV/Server.php(466)
 Sabre\\Event\\EventEmitter->emit('beforeMethod', Array)\n#27 /nextcloud/3rdparty/sabre/dav/lib/DAV/Server.php(254)
 Sabre\\DAV\\Server->invokeMethod(Object(Sabre\\HTTP\\Request), Object(Sabre\\HTTP\\Response))\n#28 /nextcloud/apps/dav/lib/Server.php(258)
 Sabre\\DAV\\Server->exec()\n#29 /nextcloud/apps/dav/appinfo/v2/remote.php(33)
 OCA\\DAV\\Server->exec()\n#30 /nextcloud/remote.php(162)
 require_once('/nextcloud/apps...')\n#31 {main}\",\"File\"
\"/nextcloud/lib/private/Lockdown/Filesystem/NullStorage.php\",\"Line\"
36}","userAgent"
"CardDAV-Sync/0.4.23 (Sony; D5803; Android 6.0.1; de_DE; org.dmfs.carddav.Sync/145)","version"
"12.0.4.3"}

The output of your config.php file in /path/to/nextcloud (make sure you remove any identifiable information!):

<?php
$CONFIG = array (
  'datadirectory' => '/data',
  'apps_paths' =>
  array (
    0 =>
    array (
      'path' => '/nextcloud/apps',
      'url' => '/apps',
      'writable' => false,
    ),
    1 =>
    array (
      'path' => '/apps2',
      'url' => '/apps2',
      'writable' => true,
    ),
  ),
  'memcache.distributed' => '\\OC\\Memcache\\Redis',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'redis' =>
  array (
    'host' => 'redis',
    'port' => 6379,
  ),
  'instanceid' => '***',
  'passwordsalt' => '***',
  'secret' => '***',
  'trusted_domains' =>
  array (
    0 => 'localhost',
    1 => '192.168.xx.yy',
    2 => 'mydomain.de',
  ),
  'trusted_proxies' =>
  array (
      0 => '192.168.xx.yy:12345',
      1 => 'mydomain.de',
  ),
  'overwrite.cli.url' => 'https://mydomain.de',
  'dbtype' => 'mysql',
  'dbtype' => 'mysql',
  'version' => '13.0.0.14',
  'dbname' => 'ncprod',
  'dbhost' => '192.168.xx.yy',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'ncprod',
  'dbpassword' => '***',
  'logtimezone' => 'Europe/Berlin',
  'installed' => true,
  'mail_from_address' => 'info',
  'logdateformat' => 'Y-m-d H:i:s',
  'mail_smtpmode' => 'smtp',
  'mail_domain' => '***.de',
  'mail_smtpauth' => 1,
  'mail_smtpsecure' => 'ssl',
  'mail_smtpauthtype' => 'LOGIN',
  'mail_smtphost' => '***',
  'mail_smtpport' => '465',
  'mail_smtpname' => '***@***.de',
  'mail_smtppassword' => '***',
  'maintenance' => false,
  'loglevel' => 2,
  'theme' => '',
  'ldapIgnoreNamingRules' => false,
  'ldapProviderFactory' => '\\OCA\\User_LDAP\\LDAPProviderFactory',
  'preview_max_filesize_image' => 5,
  'preview_max_x' => 2048,
  'preview_max_y' => 2048,
  'enabledPreviewProviders' =>
  array (
    0 => 'OC\\Preview\\PNG',
    1 => 'OC\\Preview\\JPEG',
    2 => 'OC\\Preview\\GIF',
    3 => 'OC\\Preview\\TXT',
	4 => 'OC\\Preview\\MarkDown',
  ),
);

The output of your Apache/nginx/system log in /var/log/____:

2018/02/27 14:53:58 [error] 13146#13146: *25750 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.xx.yy, server: mydomain.de, request: "GET /apps/files HTTP/2.0", upstream: "http://127.0.0.1:1234/apps/files", host: "mydomain.de"

nginx.conf

	server {
	listen 443 ssl;
	listen [::]:443 ssl;

    server_name mydomain.de;

    ssl_certificate /usr/syno/etc/certificate/ReverseProxy/***/fullchain.pem;

    ssl_certificate_key /usr/syno/etc/certificate/ReverseProxy/***/privkey.pem;

    location / {
        proxy_set_header        Host                $http_host;
        proxy_set_header        X-Real-IP           $remote_addr;
        proxy_set_header        X-Forwarded-For     $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto   $scheme;
        proxy_intercept_errors  on;
        proxy_http_version      1.1;

        proxy_pass http://localhost:12345;

    }

}

ok, i found the solution by myself. It was quite simple.

In Synology DSM Reverse Proxy settings, my reverse proxy setting was set to forward all traffic from “mydomain.de” to localhost:12345.
The problem seems, that localhost resolves (from the docker point of view) to the 172.x.x.x network. So i changed ‘localhost’ to the fixed internal IP address of my NAS (192.168.xx.yy) and voila i was able to see the local network IP addresses in the oc_bruteforce_attempts table. Even after i connected via mobile connection and tried to trigger the BF throtteling i got an entry with a real world IP address.

Thanks