diff --git a/.env.example.complete b/.env.example.complete index 472ca051b..26dfdc54b 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -270,4 +270,10 @@ API_DEFAULT_ITEM_COUNT=100 API_MAX_ITEM_COUNT=500 # The number of API requests that can be made per minute by a single user. -API_REQUESTS_PER_MIN=180 \ No newline at end of file +API_REQUESTS_PER_MIN=180 + +# Failed access +# message to log into webserver logs in case of failed access, for further processing by tools like Fail2Ban +# Apache users should use : user "%u" authentication failure for "BookStack" +# Nginx users should use : user "%u" was not found in "BookStack" +FAILED_ACCESS_MESSAGE='' diff --git a/app/Actions/ActivityService.php b/app/Actions/ActivityService.php index 9b69cbb17..0e3ac7861 100644 --- a/app/Actions/ActivityService.php +++ b/app/Actions/ActivityService.php @@ -159,4 +159,21 @@ class ActivityService session()->flash('success', $message); } } + + /** + * Log failed accesses, for further processing by tools like Fail2Ban + * + * @param username + * @return void + */ + public function logFailedAccess($username) + { + $log_msg = config('logging.failed_access_message'); + + if (!is_string($username) || !is_string($log_msg) || strlen($log_msg)<1) + return; + + $log_msg = str_replace("%u", $username, $log_msg); + error_log($log_msg, 4); + } } diff --git a/app/Config/logging.php b/app/Config/logging.php index 375e84083..ba77ba81e 100644 --- a/app/Config/logging.php +++ b/app/Config/logging.php @@ -86,4 +86,9 @@ return [ ], ], + // Failed Access Message + // Defines the message to log into webserver logs in case of failed access, + // for further processing by tools like Fail2Ban. + 'failed_access_message' => env('FAILED_ACCESS_MESSAGE', ''), + ]; diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index fb2573b5c..f031c12cf 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -2,6 +2,7 @@ namespace BookStack\Http\Controllers\Auth; +use Activity; use BookStack\Auth\Access\SocialAuthService; use BookStack\Exceptions\LoginAttemptEmailNeededException; use BookStack\Exceptions\LoginAttemptException; @@ -106,6 +107,9 @@ class LoginController extends Controller $this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); + // Also log some error message + Activity::logFailedAccess($request->get($this->username())); + return $this->sendLockoutResponse($request); } @@ -122,6 +126,9 @@ class LoginController extends Controller // user surpasses their maximum number of attempts they will get locked out. $this->incrementLoginAttempts($request); + // Also log some error message + Activity::logFailedAccess($request->get($this->username())); + return $this->sendFailedLoginResponse($request); }