Added RFC6585 status codes and use 429 for DoSFilter
This commit is contained in:
parent
39360d91e6
commit
1834e360ea
|
@ -668,6 +668,7 @@ public class HttpStatus
|
|||
public final static int UNPROCESSABLE_ENTITY_422 = 422;
|
||||
public final static int LOCKED_423 = 423;
|
||||
public final static int FAILED_DEPENDENCY_424 = 424;
|
||||
public final static int UPGRADE_REQUIRED_426 = 426;
|
||||
|
||||
public final static int INTERNAL_SERVER_ERROR_500 = 500;
|
||||
public final static int NOT_IMPLEMENTED_501 = 501;
|
||||
|
@ -677,8 +678,13 @@ public class HttpStatus
|
|||
public final static int HTTP_VERSION_NOT_SUPPORTED_505 = 505;
|
||||
public final static int INSUFFICIENT_STORAGE_507 = 507;
|
||||
|
||||
public static final int MAX_CODE = 507;
|
||||
|
||||
// RFC 6585
|
||||
public final static int PRECONDITION_REQUIRED_428 = 428;
|
||||
public final static int TOO_MANY_REQUESTS_429 = 429;
|
||||
public final static int REQUEST_HEADER_FIELDS_TOO_LARGE_431 = 431;
|
||||
public final static int NETWORK_AUTHENTICATION_REQUIRED_511 = 511;
|
||||
|
||||
public static final int MAX_CODE = 511;
|
||||
|
||||
private static final Code[] codeMap = new Code[MAX_CODE+1];
|
||||
|
||||
|
@ -802,7 +808,17 @@ public class HttpStatus
|
|||
LOCKED(LOCKED_423, "Locked"),
|
||||
/** <code>424 Failed Dependency</code> */
|
||||
FAILED_DEPENDENCY(FAILED_DEPENDENCY_424, "Failed Dependency"),
|
||||
|
||||
|
||||
/** <code>426 Upgrade Required (RFC7231)</code> */
|
||||
UPGRADE_REQUIRED(UPGRADE_REQUIRED_426, "Upgrade Required"),
|
||||
|
||||
/** <code>428 Precondition Required (RFC6585)</code> */
|
||||
PRECONDITION_REQUIRED(PRECONDITION_REQUIRED_428, "Precondition Required"),
|
||||
/** <code>429 Too Many Requests (RFC6585)</code> */
|
||||
TOO_MANY_REQUESTS(TOO_MANY_REQUESTS_429, "Too Many Requests"),
|
||||
/** <code>431 Request Header Fields Too Large (RFC6585)</code> */
|
||||
REQUEST_HEADER_FIELDS_TOO_LARGE(REQUEST_HEADER_FIELDS_TOO_LARGE_431, "Request Header Fields Too Large"),
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* Server Error messages in 5xx series. As defined by ... RFC 1945 -
|
||||
|
@ -822,8 +838,13 @@ public class HttpStatus
|
|||
/** <code>505 HTTP Version Not Supported</code> */
|
||||
HTTP_VERSION_NOT_SUPPORTED(HTTP_VERSION_NOT_SUPPORTED_505, "HTTP Version Not Supported"),
|
||||
/** <code>507 Insufficient Storage</code> */
|
||||
INSUFFICIENT_STORAGE(INSUFFICIENT_STORAGE_507, "Insufficient Storage");
|
||||
INSUFFICIENT_STORAGE(INSUFFICIENT_STORAGE_507, "Insufficient Storage"),
|
||||
|
||||
/** <code>511 Network Authentication Required (RFC6585)</code> */
|
||||
NETWORK_AUTHENTICATION_REQUIRED(NETWORK_AUTHENTICATION_REQUIRED_511, "Network Authentication Required"),
|
||||
|
||||
;
|
||||
|
||||
private final int _code;
|
||||
private final String _message;
|
||||
|
||||
|
|
|
@ -91,40 +91,33 @@ import org.eclipse.jetty.util.thread.Scheduler;
|
|||
* <dd>is the delay given to all requests over the rate limit,
|
||||
* before they are considered at all. -1 means just reject request,
|
||||
* 0 means no delay, otherwise it is the delay.</dd>
|
||||
* <p/>
|
||||
* <dt>maxWaitMs</dt>
|
||||
* <dd>how long to blocking wait for the throttle semaphore.</dd>
|
||||
* <p/>
|
||||
* <dt>throttledRequests</dt>
|
||||
* <dd>is the number of requests over the rate limit able to be
|
||||
* considered at once.</dd>
|
||||
* <p/>
|
||||
* <dt>throttleMs</dt>
|
||||
* <dd>how long to async wait for semaphore.</dd>
|
||||
* <p/>
|
||||
* <dt>maxRequestMs</dt>
|
||||
* <dd>how long to allow this request to run.</dd>
|
||||
* <p/>
|
||||
* <dt>maxIdleTrackerMs</dt>
|
||||
* <dd>how long to keep track of request rates for a connection,
|
||||
* before deciding that the user has gone away, and discarding it</dd>
|
||||
* <p/>
|
||||
* <dt>insertHeaders</dt>
|
||||
* <dd>if true , insert the DoSFilter headers into the response. Defaults to true.</dd>
|
||||
* <p/>
|
||||
* <dt>trackSessions</dt>
|
||||
* <dd>if true, usage rate is tracked by session if a session exists. Defaults to true.</dd>
|
||||
* <p/>
|
||||
* <dt>remotePort</dt>
|
||||
* <dd>if true and session tracking is not used, then rate is tracked by IP+port (effectively connection). Defaults to false.</dd>
|
||||
* <p/>
|
||||
* <dt>ipWhitelist</dt>
|
||||
* <dd>a comma-separated list of IP addresses that will not be rate limited</dd>
|
||||
* <p/>
|
||||
* <dt>managedAttr</dt>
|
||||
* <dd>if set to true, then this servlet is set as a {@link ServletContext} attribute with the
|
||||
* filter name as the attribute name. This allows context external mechanism (eg JMX via {@link ContextHandler#MANAGED_ATTRIBUTES}) to
|
||||
* manage the configuration of the filter.</dd>
|
||||
* <dt>tooManyCode</dt>
|
||||
* <dd>The status code to send if there are too many requests. By default is 429 (too many requests), but 503 (Unavailable) is
|
||||
* another option</dd>
|
||||
* </dl>
|
||||
* </p>
|
||||
*/
|
||||
|
@ -163,6 +156,7 @@ public class DoSFilter implements Filter
|
|||
static final String REMOTE_PORT_INIT_PARAM = "remotePort";
|
||||
static final String IP_WHITELIST_INIT_PARAM = "ipWhitelist";
|
||||
static final String ENABLED_INIT_PARAM = "enabled";
|
||||
static final String TOO_MANY_CODE = "tooManyCode";
|
||||
|
||||
private static final int USER_AUTH = 2;
|
||||
private static final int USER_SESSION = 2;
|
||||
|
@ -173,6 +167,7 @@ public class DoSFilter implements Filter
|
|||
private final String _resumed = "DoSFilter@" + Integer.toHexString(hashCode()) + ".RESUMED";
|
||||
private final ConcurrentHashMap<String, RateTracker> _rateTrackers = new ConcurrentHashMap<>();
|
||||
private final List<String> _whitelist = new CopyOnWriteArrayList<>();
|
||||
private int _tooManyCode;
|
||||
private volatile long _delayMs;
|
||||
private volatile long _throttleMs;
|
||||
private volatile long _maxWaitMs;
|
||||
|
@ -260,7 +255,10 @@ public class DoSFilter implements Filter
|
|||
|
||||
parameter = filterConfig.getInitParameter(ENABLED_INIT_PARAM);
|
||||
setEnabled(parameter == null || Boolean.parseBoolean(parameter));
|
||||
|
||||
|
||||
parameter = filterConfig.getInitParameter(TOO_MANY_CODE);
|
||||
setTooManyCode(parameter==null?429:Integer.parseInt(parameter));
|
||||
|
||||
_scheduler = startScheduler();
|
||||
|
||||
ServletContext context = filterConfig.getServletContext();
|
||||
|
@ -331,7 +329,7 @@ public class DoSFilter implements Filter
|
|||
LOG.warn("DOS ALERT: Request rejected ip={}, session={}, user={}", request.getRemoteAddr(), request.getRequestedSessionId(), request.getUserPrincipal());
|
||||
if (insertHeaders)
|
||||
response.addHeader("DoSFilter", "unavailable");
|
||||
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
response.sendError(getTooManyCode());
|
||||
return;
|
||||
}
|
||||
case 0:
|
||||
|
@ -414,12 +412,13 @@ public class DoSFilter implements Filter
|
|||
LOG.debug("Rejecting {}", request);
|
||||
if (isInsertHeaders())
|
||||
response.addHeader("DoSFilter", "unavailable");
|
||||
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
response.sendError(getTooManyCode());
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
LOG.ignore(e);
|
||||
response.sendError(getTooManyCode());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -980,6 +979,16 @@ public class DoSFilter implements Filter
|
|||
{
|
||||
_enabled = enabled;
|
||||
}
|
||||
|
||||
public int getTooManyCode()
|
||||
{
|
||||
return _tooManyCode;
|
||||
}
|
||||
|
||||
public void setTooManyCode(int tooManyCode)
|
||||
{
|
||||
_tooManyCode = tooManyCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of IP addresses that will not be rate limited.
|
||||
|
|
|
@ -260,7 +260,7 @@ public abstract class AbstractDoSFilterTest
|
|||
// System.err.println("RESPONSES: \n"+responses);
|
||||
|
||||
assertEquals(4,count(responses,"HTTP/1.1 200 OK"));
|
||||
assertEquals(1,count(responses,"HTTP/1.1 503"));
|
||||
assertEquals(1,count(responses,"HTTP/1.1 429"));
|
||||
assertEquals(1,count(responses,"DoSFilter: delayed"));
|
||||
assertEquals(1,count(responses,"DoSFilter: throttled"));
|
||||
assertEquals(1,count(responses,"DoSFilter: unavailable"));
|
||||
|
|
Loading…
Reference in New Issue