mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-990: Enabled/disable auth failure tracking via implementations of a common interface.
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.ban;
|
package org.apache.guacamole.auth.ban;
|
||||||
|
|
||||||
|
import org.apache.guacamole.auth.ban.status.AuthenticationFailureTracker;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
|
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
|
||||||
import org.apache.guacamole.net.event.AuthenticationFailureEvent;
|
import org.apache.guacamole.net.event.AuthenticationFailureEvent;
|
||||||
|
@@ -19,8 +19,11 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.ban;
|
package org.apache.guacamole.auth.ban;
|
||||||
|
|
||||||
|
import org.apache.guacamole.auth.ban.status.InMemoryAuthenticationFailureTracker;
|
||||||
|
import org.apache.guacamole.auth.ban.status.AuthenticationFailureTracker;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleServerException;
|
import org.apache.guacamole.GuacamoleServerException;
|
||||||
|
import org.apache.guacamole.auth.ban.status.NullAuthenticationFailureTracker;
|
||||||
import org.apache.guacamole.environment.Environment;
|
import org.apache.guacamole.environment.Environment;
|
||||||
import org.apache.guacamole.environment.LocalEnvironment;
|
import org.apache.guacamole.environment.LocalEnvironment;
|
||||||
import org.apache.guacamole.net.auth.AbstractAuthenticationProvider;
|
import org.apache.guacamole.net.auth.AbstractAuthenticationProvider;
|
||||||
@@ -29,6 +32,8 @@ import org.apache.guacamole.net.auth.Credentials;
|
|||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.LongGuacamoleProperty;
|
import org.apache.guacamole.properties.LongGuacamoleProperty;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AuthenticationProvider implementation that blocks further authentication
|
* AuthenticationProvider implementation that blocks further authentication
|
||||||
@@ -37,6 +42,11 @@ import org.apache.guacamole.properties.LongGuacamoleProperty;
|
|||||||
*/
|
*/
|
||||||
public class BanningAuthenticationProvider extends AbstractAuthenticationProvider {
|
public class BanningAuthenticationProvider extends AbstractAuthenticationProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger for this class.
|
||||||
|
*/
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(BanningAuthenticationProvider.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of failed authentication attempts allowed before an
|
* The maximum number of failed authentication attempts allowed before an
|
||||||
* address is temporarily banned.
|
* address is temporarily banned.
|
||||||
@@ -126,7 +136,29 @@ public class BanningAuthenticationProvider extends AbstractAuthenticationProvide
|
|||||||
+ "\"" + MAX_ADDRESSES.getName() + "\" property, must be "
|
+ "\"" + MAX_ADDRESSES.getName() + "\" property, must be "
|
||||||
+ "greater than zero.");
|
+ "greater than zero.");
|
||||||
|
|
||||||
tracker = new AuthenticationFailureTracker(maxAttempts, banDuration, maxAddresses);
|
// Configure auth failure tracking behavior and inform administrator of
|
||||||
|
// ultimate result
|
||||||
|
if (maxAttempts <= 0) {
|
||||||
|
this.tracker = new NullAuthenticationFailureTracker();
|
||||||
|
logger.info("Maximum failed authentication attempts has been set "
|
||||||
|
+ "to {}. Automatic banning of brute-force authentication "
|
||||||
|
+ "attempts will be disabled.", maxAttempts);
|
||||||
|
}
|
||||||
|
else if (banDuration <= 0) {
|
||||||
|
this.tracker = new NullAuthenticationFailureTracker();
|
||||||
|
logger.info("Ban duration for addresses that repeatedly fail "
|
||||||
|
+ "authentication has been set to {}. Automatic banning "
|
||||||
|
+ "of brute-force authentication attempts will be "
|
||||||
|
+ "disabled.", banDuration);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.tracker = new InMemoryAuthenticationFailureTracker(maxAttempts, banDuration, maxAddresses);
|
||||||
|
logger.info("Addresses will be automatically banned for {} "
|
||||||
|
+ "seconds after {} failed authentication attempts. Up "
|
||||||
|
+ "to {} unique addresses will be tracked/banned at any "
|
||||||
|
+ "given time.", banDuration, maxAttempts, maxAddresses);
|
||||||
|
}
|
||||||
|
|
||||||
BanningAuthenticationListener.setAuthenticationFailureTracker(tracker);
|
BanningAuthenticationListener.setAuthenticationFailureTracker(tracker);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.guacamole.auth.ban;
|
package org.apache.guacamole.auth.ban.status;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.auth.ban.status;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks past authentication results, automatically blocking the IP addresses
|
||||||
|
* of machines that repeatedly fail to authenticate.
|
||||||
|
*/
|
||||||
|
public interface AuthenticationFailureTracker {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reports that an authentication request has been received, but it is
|
||||||
|
* either not yet known whether the request has succeeded or failed. If the
|
||||||
|
* associated address is currently being blocked, an exception will be
|
||||||
|
* thrown.
|
||||||
|
*
|
||||||
|
* @param credentials
|
||||||
|
* The credentials associated with the authentication request.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the authentication request is being blocked due to brute force
|
||||||
|
* prevention rules.
|
||||||
|
*/
|
||||||
|
void notifyAuthenticationRequestReceived(Credentials credentials)
|
||||||
|
throws GuacamoleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reports that an authentication request has been received and has
|
||||||
|
* succeeded. If the associated address is currently being blocked, an
|
||||||
|
* exception will be thrown.
|
||||||
|
*
|
||||||
|
* @param credentials
|
||||||
|
* The credentials associated with the successful authentication
|
||||||
|
* request.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the authentication request is being blocked due to brute force
|
||||||
|
* prevention rules.
|
||||||
|
*/
|
||||||
|
void notifyAuthenticationSuccess(Credentials credentials)
|
||||||
|
throws GuacamoleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reports that an authentication request has been received and has
|
||||||
|
* failed. If the associated address is currently being blocked, an
|
||||||
|
* exception will be thrown.
|
||||||
|
*
|
||||||
|
* @param credentials
|
||||||
|
* The credentials associated with the failed authentication request.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the authentication request is being blocked due to brute force
|
||||||
|
* prevention rules.
|
||||||
|
*/
|
||||||
|
void notifyAuthenticationFailed(Credentials credentials)
|
||||||
|
throws GuacamoleException;
|
||||||
|
|
||||||
|
}
|
@@ -17,7 +17,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.guacamole.auth.ban;
|
package org.apache.guacamole.auth.ban.status;
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Cache;
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
@@ -30,15 +30,16 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides automated tracking and blocking of IP addresses that repeatedly
|
* AuthenticationFailureTracker implementation that tracks the failure status
|
||||||
* fail authentication.
|
* of each IP address in memory. The maximum amount of memory consumed is
|
||||||
|
* bounded by the configured maximum number of addresses tracked.
|
||||||
*/
|
*/
|
||||||
public class AuthenticationFailureTracker {
|
public class InMemoryAuthenticationFailureTracker implements AuthenticationFailureTracker {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logger for this class.
|
* Logger for this class.
|
||||||
*/
|
*/
|
||||||
private static final Logger logger = LoggerFactory.getLogger(AuthenticationFailureTracker.class);
|
private static final Logger logger = LoggerFactory.getLogger(InMemoryAuthenticationFailureTracker.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All authentication failures currently being tracked, stored by the
|
* All authentication failures currently being tracked, stored by the
|
||||||
@@ -74,38 +75,17 @@ public class AuthenticationFailureTracker {
|
|||||||
* The maximum number of unique IP addresses that should be tracked
|
* The maximum number of unique IP addresses that should be tracked
|
||||||
* before discarding older tracked failures.
|
* before discarding older tracked failures.
|
||||||
*/
|
*/
|
||||||
public AuthenticationFailureTracker(int maxAttempts, int banDuration,
|
public InMemoryAuthenticationFailureTracker(int maxAttempts, int banDuration,
|
||||||
long maxAddresses) {
|
long maxAddresses) {
|
||||||
|
|
||||||
this.maxAttempts = maxAttempts;
|
this.maxAttempts = maxAttempts;
|
||||||
this.banDuration = banDuration;
|
this.banDuration = banDuration;
|
||||||
|
|
||||||
// Inform administrator of configured behavior
|
|
||||||
if (maxAttempts <= 0) {
|
|
||||||
logger.info("Maximum failed authentication attempts has been set "
|
|
||||||
+ "to {}. Automatic banning of brute-force authentication "
|
|
||||||
+ "attempts will be disabled.", maxAttempts);
|
|
||||||
}
|
|
||||||
else if (banDuration <= 0) {
|
|
||||||
logger.info("Ban duration for addresses that repeatedly fail "
|
|
||||||
+ "authentication has been set to {}. Automatic banning "
|
|
||||||
+ "of brute-force authentication attempts will be "
|
|
||||||
+ "disabled.", banDuration);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logger.info("Addresses will be automatically banned for {} "
|
|
||||||
+ "seconds after {} failed authentication attempts.",
|
|
||||||
banDuration, maxAttempts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit maximum number of tracked addresses to configured upper bound
|
// Limit maximum number of tracked addresses to configured upper bound
|
||||||
this.failures = Caffeine.newBuilder()
|
this.failures = Caffeine.newBuilder()
|
||||||
.maximumSize(maxAddresses)
|
.maximumSize(maxAddresses)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
logger.info("Up to {} unique addresses will be tracked/banned at any "
|
|
||||||
+ " given time.", maxAddresses);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -187,10 +167,6 @@ public class AuthenticationFailureTracker {
|
|||||||
private void notifyAuthenticationStatus(Credentials credentials,
|
private void notifyAuthenticationStatus(Credentials credentials,
|
||||||
boolean failed) throws GuacamoleException {
|
boolean failed) throws GuacamoleException {
|
||||||
|
|
||||||
// Do not track/ban if tracking or banning are disabled
|
|
||||||
if (maxAttempts <= 0 || banDuration <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Ignore requests that do not contain explicit parameters of any kind
|
// Ignore requests that do not contain explicit parameters of any kind
|
||||||
if (isEmpty(credentials))
|
if (isEmpty(credentials))
|
||||||
return;
|
return;
|
||||||
@@ -234,54 +210,19 @@ public class AuthenticationFailureTracker {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Reports that an authentication request has been received, but it is
|
|
||||||
* either not yet known whether the request has succeeded or failed. If the
|
|
||||||
* associated address is currently being blocked, an exception will be
|
|
||||||
* thrown.
|
|
||||||
*
|
|
||||||
* @param credentials
|
|
||||||
* The credentials associated with the authentication request.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If the authentication request is being blocked due to brute force
|
|
||||||
* prevention rules.
|
|
||||||
*/
|
|
||||||
public void notifyAuthenticationRequestReceived(Credentials credentials)
|
public void notifyAuthenticationRequestReceived(Credentials credentials)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
notifyAuthenticationStatus(credentials, false);
|
notifyAuthenticationStatus(credentials, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Reports that an authentication request has been received and has
|
|
||||||
* succeeded. If the associated address is currently being blocked, an
|
|
||||||
* exception will be thrown.
|
|
||||||
*
|
|
||||||
* @param credentials
|
|
||||||
* The credentials associated with the successful authentication
|
|
||||||
* request.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If the authentication request is being blocked due to brute force
|
|
||||||
* prevention rules.
|
|
||||||
*/
|
|
||||||
public void notifyAuthenticationSuccess(Credentials credentials)
|
public void notifyAuthenticationSuccess(Credentials credentials)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
notifyAuthenticationStatus(credentials, false);
|
notifyAuthenticationStatus(credentials, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Reports that an authentication request has been received and has
|
|
||||||
* failed. If the associated address is currently being blocked, an
|
|
||||||
* exception will be thrown.
|
|
||||||
*
|
|
||||||
* @param credentials
|
|
||||||
* The credentials associated with the failed authentication request.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If the authentication request is being blocked due to brute force
|
|
||||||
* prevention rules.
|
|
||||||
*/
|
|
||||||
public void notifyAuthenticationFailed(Credentials credentials)
|
public void notifyAuthenticationFailed(Credentials credentials)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
notifyAuthenticationStatus(credentials, true);
|
notifyAuthenticationStatus(credentials, true);
|
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.auth.ban.status;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AuthenticationFailureTracker implementation that does nothing. All requests
|
||||||
|
* are ignored, regardless of status, and no tracking is performed.
|
||||||
|
*/
|
||||||
|
public class NullAuthenticationFailureTracker implements AuthenticationFailureTracker {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyAuthenticationRequestReceived(Credentials credentials)
|
||||||
|
throws GuacamoleException {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyAuthenticationSuccess(Credentials credentials)
|
||||||
|
throws GuacamoleException {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyAuthenticationFailed(Credentials credentials)
|
||||||
|
throws GuacamoleException {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user