Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions vertx-core/src/main/java/io/vertx/core/http/Http2ServerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ public class Http2ServerConfig {
private int connectionWindowSize;
private boolean multiplexImplementation;
private int rstFloodMaxRstFramePerWindow;
private int maxSmallContinuationFrames;
private Duration rstFloodWindowDuration;

public Http2ServerConfig() {
initialSettings = new Http2Settings().setMaxConcurrentStreams(DEFAULT_INITIAL_SETTINGS_MAX_CONCURRENT_STREAMS);
connectionWindowSize = DEFAULT_HTTP2_CONNECTION_WINDOW_SIZE;
rstFloodMaxRstFramePerWindow = DEFAULT_HTTP2_RST_FLOOD_MAX_RST_FRAME_PER_WINDOW;
rstFloodWindowDuration = Duration.of(DEFAULT_HTTP2_RST_FLOOD_WINDOW_DURATION, DEFAULT_HTTP2_RST_FLOOD_WINDOW_DURATION_TIME_UNIT.toChronoUnit());
maxSmallContinuationFrames = DEFAULT_HTTP2_MAX_SMALL_CONTINUATION_FRAMES;
multiplexImplementation = DEFAULT_HTTP_2_MULTIPLEX_IMPLEMENTATION;
}

Expand All @@ -43,6 +45,7 @@ public Http2ServerConfig(Http2ServerConfig other) {
this.connectionWindowSize = other.connectionWindowSize;
this.rstFloodMaxRstFramePerWindow = other.rstFloodMaxRstFramePerWindow;
this.rstFloodWindowDuration = other.rstFloodWindowDuration;
this.maxSmallContinuationFrames = other.maxSmallContinuationFrames;
this.multiplexImplementation = other.multiplexImplementation;
}

Expand Down Expand Up @@ -84,6 +87,29 @@ public Http2ServerConfig setRstFloodWindowDuration(Duration rstFloodWindowDurati
return this;
}

/**
* @return the max number of small continuation frame allowed
*/
public int getMaxSmallContinuationFrames() {
return maxSmallContinuationFrames;
}

/**
* Set the maximum number of small continuation frames allowed, this is used to prevent flood DoS attack
* via <a href="https://nvd.nist.gov/vuln/detail/CVE-2026-33871">zero-byte continuation frames</a>. The default value
* is {@link HttpServerOptions#DEFAULT_HTTP2_MAX_SMALL_CONTINUATION_FRAMES}.
*
* @param maxSmallContinuationFrames the max number of small continuation frame allowed
* @return a reference to this, so the API can be used fluently
*/
public Http2ServerConfig setMaxSmallContinuationFrames(int maxSmallContinuationFrames) {
if (maxSmallContinuationFrames < 1) {
throw new IllegalArgumentException();
}
this.maxSmallContinuationFrames = maxSmallContinuationFrames;
return this;
}

/**
* @return the default HTTP/2 connection window size
*/
Expand Down
25 changes: 25 additions & 0 deletions vertx-core/src/main/java/io/vertx/core/http/HttpServerOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ public class HttpServerOptions extends NetServerOptions {
*/
public static final TimeUnit DEFAULT_HTTP2_RST_FLOOD_WINDOW_DURATION_TIME_UNIT = TimeUnit.SECONDS;

/**
* HTTP/2 maximum allowed number of small continuation frames.
*/
public static final int DEFAULT_HTTP2_MAX_SMALL_CONTINUATION_FRAMES = 16;

/**
* Strict thread mode = false.
*/
Expand Down Expand Up @@ -1274,6 +1279,26 @@ public HttpServerOptions setHttp2RstFloodWindowDurationTimeUnit(TimeUnit http2Rs
return this;
}

/**
* @return the max number of small continuation frame allowed
*/
public int getHttp2MaxSmallContinuationFrames() {
return http2Config.getMaxSmallContinuationFrames();
}

/**
* Set the maximum number of small continuation frames allowed, this is used to prevent flood DoS attack
* via <a href="https://nvd.nist.gov/vuln/detail/CVE-2026-33871">zero-byte continuation frames</a>. The default value
* is {@link #DEFAULT_HTTP2_MAX_SMALL_CONTINUATION_FRAMES}.
*
* @param http2MaxSmallContinuationFrames the max number of small continuation frame allowed
* @return a reference to this, so the API can be used fluently
*/
public HttpServerOptions setHttp2MaxSmallContinuationFrames(int http2MaxSmallContinuationFrames) {
http2Config.setMaxSmallContinuationFrames(http2MaxSmallContinuationFrames);
return this;
}

/**
* @return whether the strict thread mode is used
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,12 @@ public void configureHttp1OrH2CUpgradeHandler(ContextInternal context, ChannelPi
public VertxHttp2ConnectionHandler<Http2ServerConnectionImpl> buildHttp2ConnectionHandler(ContextInternal ctx) {
int maxRstFramesPerWindow = config.getRstFloodMaxRstFramePerWindow();
int secondsPerWindow = (int)config.getRstFloodWindowDuration().toSeconds();
int maxSmallContinuationFrames = config.getMaxSmallContinuationFrames();
VertxHttp2ConnectionHandler<Http2ServerConnectionImpl> handler = new VertxHttp2ConnectionHandlerBuilder<Http2ServerConnectionImpl>()
.server(true)
.useCompression(compressionManager != null ? compressionManager.options() : null)
.gracefulShutdownTimeoutMillis(0)
.decoderEnforceMaxSmallContinuationFrames(maxSmallContinuationFrames)
.decoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow)
.encoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow)
.useDecompression(useDecompression)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public VertxHttp2ConnectionHandlerBuilder<C> useCompression(CompressionOptions[]
return this;
}

@Override
public VertxHttp2ConnectionHandlerBuilder<C> decoderEnforceMaxSmallContinuationFrames(int maxSmallContinuationFrames) {
return super.decoderEnforceMaxSmallContinuationFrames(maxSmallContinuationFrames);
}

@Override
public VertxHttp2ConnectionHandlerBuilder<C> decoderEnforceMaxRstFramesPerWindow(int maxRstFramesPerWindow, int secondsPerWindow) {
return super.decoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ public Http2CustomFrameCodecBuilder decoderEnforceMaxRstFramesPerWindow(int maxR
return (Http2CustomFrameCodecBuilder) super.decoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow);
}

@Override
public Http2CustomFrameCodecBuilder decoderEnforceMaxSmallContinuationFrames(int maxConsecutiveContinuationsFrames) {
return (Http2CustomFrameCodecBuilder) super.decoderEnforceMaxSmallContinuationFrames(maxConsecutiveContinuationsFrames);
}

@Override
public Http2CustomFrameCodecBuilder server(boolean isServer) {
this.server = isServer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class Http2MultiplexServerChannelInitializer implements Http2ServerChanne
private final Http2MultiplexConnectionFactory connectionFactory;
private final int rstFloodMaxRstFramePerWindow;
private final int rstFloodWindowDuration;
private final int maxSmallContinuationFrames;
private final boolean logEnabled;

public Http2MultiplexServerChannelInitializer(ContextInternal context,
Expand All @@ -50,6 +51,7 @@ public Http2MultiplexServerChannelInitializer(ContextInternal context,
Http2Settings initialSettings,
int rstFloodMaxRstFramePerWindow,
int rstFloodWindowDuration,
int maxSmallContinuationFrames,
boolean logEnabled) {
Http2MultiplexConnectionFactory connectionFactory = (handler, chctx) -> {
Http2MultiplexServerConnection connection = new Http2MultiplexServerConnection(
Expand All @@ -70,6 +72,7 @@ public Http2MultiplexServerChannelInitializer(ContextInternal context,
this.decompressionSupported = decompressionSupported;
this.rstFloodMaxRstFramePerWindow = rstFloodMaxRstFramePerWindow;
this.rstFloodWindowDuration = rstFloodWindowDuration;
this.maxSmallContinuationFrames = maxSmallContinuationFrames;
this.logEnabled = logEnabled;
}

Expand All @@ -83,6 +86,7 @@ public void configureHttp2(ContextInternal context, ChannelPipeline pipeline, bo

Http2FrameCodec frameCodec = new Http2CustomFrameCodecBuilder(compressionManager, decompressionSupported)
.server(true)
.decoderEnforceMaxSmallContinuationFrames(rstFloodWindowDuration)
.decoderEnforceMaxRstFramesPerWindow(rstFloodMaxRstFramePerWindow, rstFloodWindowDuration)
.encoderEnforceMaxRstFramesPerWindow(rstFloodMaxRstFramePerWindow, rstFloodWindowDuration)
.initialSettings(initialSettings)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ public HttpServerConnectionInitializer(ContextInternal context,
HttpUtils.fromVertxInitialSettings(true, http2Config.getInitialSettings()),
http2Config.getRstFloodMaxRstFramePerWindow(),
(int)http2Config.getRstFloodWindowDuration().toSeconds(),
http2Config.getMaxSmallContinuationFrames(),
logEnabled);
} else {
http2ChannelInitializer = new Http2CodecServerChannelInitializer(
Expand Down
Loading