Skip to content

Commit

Permalink
Netty 4.1.100.Final added an HTTP/2 RST frame flood protection, this …
Browse files Browse the repository at this point in the history
…makes it configurable.
vietj committed Oct 11, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent ce52e36 commit 0dc6568
Showing 3 changed files with 93 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/main/java/io/vertx/core/http/HttpServerOptions.java
Original file line number Diff line number Diff line change
@@ -169,6 +169,21 @@ public class HttpServerOptions extends NetServerOptions {
*/
public static final boolean DEFAULT_REGISTER_WEBSOCKET_WRITE_HANDLERS = false;

/**
* HTTP/2 RST floods DDOS protection, max number of RST frame per time window allowed = 200.
*/
public static final int DEFAULT_HTTP2_RST_FLOOD_MAX_RST_FRAME_PER_WINDOW = 200;

/**
* HTTP/2 RST floods DDOS protection, time window duration = 30.
*/
public static final int DEFAULT_HTTP2_RST_FLOOD_WINDOW_DURATION = 30;

/**
* HTTP/2 RST floods DDOS protection, time window duration unit = {@link TimeUnit#SECONDS}.
*/
public static final TimeUnit DEFAULT_HTTP2_RST_FLOOD_WINDOW_DURATION_TIME_UNIT = TimeUnit.SECONDS;

private boolean compressionSupported;
private int compressionLevel;
private List<CompressionOptions> compressors;
@@ -194,6 +209,9 @@ public class HttpServerOptions extends NetServerOptions {
private int webSocketClosingTimeout;
private TracingPolicy tracingPolicy;
private boolean registerWebSocketWriteHandlers;
private int http2RstFloodMaxRstFramePerWindow;
private int http2RstFloodWindowDuration;
private TimeUnit http2RstFloodWindowDurationTimeUnit;

/**
* Default constructor
@@ -236,6 +254,9 @@ public HttpServerOptions(HttpServerOptions other) {
this.webSocketClosingTimeout = other.webSocketClosingTimeout;
this.tracingPolicy = other.tracingPolicy;
this.registerWebSocketWriteHandlers = other.registerWebSocketWriteHandlers;
this.http2RstFloodMaxRstFramePerWindow = other.http2RstFloodMaxRstFramePerWindow;
this.http2RstFloodWindowDuration = other.http2RstFloodWindowDuration;
this.http2RstFloodWindowDurationTimeUnit = other.http2RstFloodWindowDurationTimeUnit;
}

/**
@@ -285,6 +306,9 @@ private void init() {
webSocketClosingTimeout = DEFAULT_WEBSOCKET_CLOSING_TIMEOUT;
tracingPolicy = DEFAULT_TRACING_POLICY;
registerWebSocketWriteHandlers = DEFAULT_REGISTER_WEBSOCKET_WRITE_HANDLERS;
http2RstFloodMaxRstFramePerWindow = DEFAULT_HTTP2_RST_FLOOD_MAX_RST_FRAME_PER_WINDOW;
http2RstFloodWindowDuration = DEFAULT_HTTP2_RST_FLOOD_WINDOW_DURATION;
http2RstFloodWindowDurationTimeUnit = DEFAULT_HTTP2_RST_FLOOD_WINDOW_DURATION_TIME_UNIT;
}

@Override
@@ -1096,4 +1120,65 @@ public HttpServerOptions setRegisterWebSocketWriteHandlers(boolean registerWebSo
this.registerWebSocketWriteHandlers = registerWebSocketWriteHandlers;
return this;
}

/**
* @return the max number of RST frame allowed per time window
*/
public int getHttp2RstFloodMaxRstFramePerWindow() {
return http2RstFloodMaxRstFramePerWindow;
}

/**
* Set the max number of RST frame allowed per time window, this is used to prevent HTTP/2 RST frame flood DDOS
* attacks. The default value is {@link #DEFAULT_HTTP2_RST_FLOOD_MAX_RST_FRAME_PER_WINDOW}, setting zero or a negative value, disables flood protection.
*
* @param http2RstFloodMaxRstFramePerWindow the new maximum
* @return a reference to this, so the API can be used fluently
*/
public HttpServerOptions setHttp2RstFloodMaxRstFramePerWindow(int http2RstFloodMaxRstFramePerWindow) {
this.http2RstFloodMaxRstFramePerWindow = http2RstFloodMaxRstFramePerWindow;
return this;
}

/**
* @return the duration of the time window when checking the max number of RST frames.
*/
public int getHttp2RstFloodWindowDuration() {
return http2RstFloodWindowDuration;
}

/**
* Set the duration of the time window when checking the max number of RST frames, this is used to prevent HTTP/2 RST frame flood DDOS
* attacks. The default value is {@link #DEFAULT_HTTP2_RST_FLOOD_WINDOW_DURATION}, setting zero or a negative value, disables flood protection.
*
* @param http2RstFloodWindowDuration the new duration
* @return a reference to this, so the API can be used fluently
*/
public HttpServerOptions setHttp2RstFloodWindowDuration(int http2RstFloodWindowDuration) {
this.http2RstFloodWindowDuration = http2RstFloodWindowDuration;
return this;
}

/**
* @return the time unit of the duration of the time window when checking the max number of RST frames.
*/
public TimeUnit getHttp2RstFloodWindowDurationTimeUnit() {
return http2RstFloodWindowDurationTimeUnit;
}

/**
* Set the time unit of the duration of the time window when checking the max number of RST frames, this is used to
* prevent HTTP/2 RST frame flood DDOS attacks. The default value is {@link #DEFAULT_HTTP2_RST_FLOOD_WINDOW_DURATION_TIME_UNIT},
* setting zero or a negative value, disables the flood protection.
*
* @param http2RstFloodWindowDurationTimeUnit the new duration
* @return a reference to this, so the API can be used fluently
*/
public HttpServerOptions setHttp2RstFloodWindowDurationTimeUnit(TimeUnit http2RstFloodWindowDurationTimeUnit) {
if (http2RstFloodWindowDurationTimeUnit == null) {
throw new NullPointerException();
}
this.http2RstFloodWindowDurationTimeUnit = http2RstFloodWindowDurationTimeUnit;
return this;
}
}
3 changes: 3 additions & 0 deletions src/main/java/io/vertx/core/http/impl/HttpServerWorker.java
Original file line number Diff line number Diff line change
@@ -239,9 +239,12 @@ void configureHttp2(ChannelPipeline pipeline) {

VertxHttp2ConnectionHandler<Http2ServerConnection> buildHttp2ConnectionHandler(EventLoopContext ctx, Handler<HttpServerConnection> handler_) {
HttpServerMetrics metrics = (HttpServerMetrics) server.getMetrics();
int maxRstFramesPerWindow = options.getHttp2RstFloodMaxRstFramePerWindow();
int secondsPerWindow = (int)options.getHttp2RstFloodWindowDurationTimeUnit().toSeconds(options.getHttp2RstFloodWindowDuration());
VertxHttp2ConnectionHandler<Http2ServerConnection> handler = new VertxHttp2ConnectionHandlerBuilder<Http2ServerConnection>()
.server(true)
.useCompression(compressionOptions)
.decoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow)
.useDecompression(options.isDecompressionSupported())
.initialSettings(options.getInitialSettings())
.connectionFactory(connHandler -> {
Original file line number Diff line number Diff line change
@@ -55,6 +55,11 @@ VertxHttp2ConnectionHandlerBuilder<C> useCompression(CompressionOptions[] compre
return this;
}

@Override
protected VertxHttp2ConnectionHandlerBuilder<C> decoderEnforceMaxRstFramesPerWindow(int maxRstFramesPerWindow, int secondsPerWindow) {
return super.decoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow);
}

@Override
protected VertxHttp2ConnectionHandlerBuilder<C> gracefulShutdownTimeoutMillis(long gracefulShutdownTimeoutMillis) {
return super.gracefulShutdownTimeoutMillis(gracefulShutdownTimeoutMillis);

0 comments on commit 0dc6568

Please sign in to comment.