Skip to content

Commit ff78924

Browse files
committed
Allow an HTTP/2 server to be protected against MadeYouReset attacks
Motivation: HTTP/2 servers can be vulnerable to MadeYouReset attacks, to protect against this attach Netty can detect a RST flood attack and close the connection in response. Changes: Configure the HTTP/2 server connection builder encoder RST flood protection with the same setting than the decoder RST flood protection. In addition ignore headers frame when the server has received or sent a go away to avoid creating un-necessary request handler calls.
1 parent fdcaeab commit ff78924

File tree

8 files changed

+259
-6
lines changed

8 files changed

+259
-6
lines changed

vertx-core/pom.xml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,57 +44,70 @@
4444
<dependency>
4545
<groupId>io.netty</groupId>
4646
<artifactId>netty-common</artifactId>
47+
<version>4.2.4.Final-SNAPSHOT</version>
4748
</dependency>
4849
<dependency>
4950
<groupId>io.netty</groupId>
5051
<artifactId>netty-buffer</artifactId>
52+
<version>4.2.4.Final-SNAPSHOT</version>
5153
</dependency>
5254
<dependency>
5355
<groupId>io.netty</groupId>
5456
<artifactId>netty-transport</artifactId>
57+
<version>4.2.4.Final-SNAPSHOT</version>
5558
</dependency>
5659
<dependency>
5760
<groupId>io.netty</groupId>
5861
<artifactId>netty-handler</artifactId>
62+
<version>4.2.4.Final-SNAPSHOT</version>
5963
</dependency>
6064
<dependency>
6165
<groupId>io.netty</groupId>
6266
<artifactId>netty-handler-proxy</artifactId>
67+
<version>4.2.4.Final-SNAPSHOT</version>
6368
</dependency>
6469
<dependency>
6570
<groupId>io.netty</groupId>
6671
<artifactId>netty-codec-http</artifactId>
72+
<version>4.2.4.Final-SNAPSHOT</version>
6773
</dependency>
6874
<dependency>
6975
<groupId>io.netty</groupId>
7076
<artifactId>netty-codec-http2</artifactId>
77+
<version>4.2.4.Final-SNAPSHOT</version>
7178
</dependency>
7279
<dependency>
7380
<groupId>io.netty</groupId>
7481
<artifactId>netty-resolver</artifactId>
82+
<version>4.2.4.Final-SNAPSHOT</version>
7583
</dependency>
7684
<dependency>
7785
<groupId>io.netty</groupId>
7886
<artifactId>netty-resolver-dns</artifactId>
87+
<version>4.2.4.Final-SNAPSHOT</version>
7988
</dependency>
8089
<dependency>
8190
<groupId>io.netty</groupId>
8291
<artifactId>netty-codec-haproxy</artifactId>
92+
<version>4.2.4.Final-SNAPSHOT</version>
8393
<optional>true</optional>
8494
</dependency>
8595
<dependency>
8696
<groupId>io.netty</groupId>
8797
<artifactId>netty-transport-classes-epoll</artifactId>
98+
<version>4.2.4.Final-SNAPSHOT</version>
8899
<optional>true</optional>
89100
</dependency>
90101
<dependency>
91102
<groupId>io.netty</groupId>
92103
<artifactId>netty-transport-classes-io_uring</artifactId>
104+
<version>4.2.4.Final-SNAPSHOT</version>
93105
<optional>true</optional>
94106
</dependency>
95107
<dependency>
96108
<groupId>io.netty</groupId>
97109
<artifactId>netty-transport-classes-kqueue</artifactId>
110+
<version>4.2.4.Final-SNAPSHOT</version>
98111
<optional>true</optional>
99112
</dependency>
100113

@@ -865,12 +878,14 @@
865878
<groupId>io.netty</groupId>
866879
<artifactId>netty-transport-native-epoll</artifactId>
867880
<classifier>linux-x86_64</classifier>
881+
<version>4.2.4.Final-SNAPSHOT</version>
868882
<scope>test</scope>
869883
</dependency>
870884
<dependency>
871885
<groupId>io.netty</groupId>
872886
<artifactId>netty-transport-native-io_uring</artifactId>
873887
<classifier>linux-x86_64</classifier>
888+
<version>4.2.4.Final-SNAPSHOT</version>
874889
<scope>test</scope>
875890
</dependency>
876891
</dependencies>
@@ -889,12 +904,14 @@
889904
<groupId>io.netty</groupId>
890905
<artifactId>netty-transport-native-epoll</artifactId>
891906
<classifier>linux-x86_64</classifier>
907+
<version>4.2.4.Final-SNAPSHOT</version>
892908
<scope>test</scope>
893909
</dependency>
894910
<dependency>
895911
<groupId>io.netty</groupId>
896912
<artifactId>netty-transport-native-io_uring</artifactId>
897913
<classifier>linux-x86_64</classifier>
914+
<version>4.2.4.Final-SNAPSHOT</version>
898915
<scope>test</scope>
899916
</dependency>
900917
</dependencies>
@@ -913,12 +930,14 @@
913930
<groupId>io.netty</groupId>
914931
<artifactId>netty-transport-native-epoll</artifactId>
915932
<classifier>linux-aarch_64</classifier>
933+
<version>4.2.4.Final-SNAPSHOT</version>
916934
<scope>test</scope>
917935
</dependency>
918936
<dependency>
919937
<groupId>io.netty</groupId>
920938
<artifactId>netty-transport-native-io_uring</artifactId>
921939
<classifier>linux-aarch_64</classifier>
940+
<version>4.2.4.Final-SNAPSHOT</version>
922941
<scope>test</scope>
923942
</dependency>
924943
</dependencies>
@@ -937,12 +956,14 @@
937956
<groupId>io.netty</groupId>
938957
<artifactId>netty-resolver-dns-native-macos</artifactId>
939958
<classifier>osx-x86_64</classifier>
959+
<version>4.2.4.Final-SNAPSHOT</version>
940960
<scope>test</scope>
941961
</dependency>
942962
<dependency>
943963
<groupId>io.netty</groupId>
944964
<artifactId>netty-transport-native-kqueue</artifactId>
945965
<classifier>osx-x86_64</classifier>
966+
<version>4.2.4.Final-SNAPSHOT</version>
946967
<scope>test</scope>
947968
</dependency>
948969
</dependencies>
@@ -961,12 +982,14 @@
961982
<groupId>io.netty</groupId>
962983
<artifactId>netty-resolver-dns-native-macos</artifactId>
963984
<classifier>osx-aarch_64</classifier>
985+
<version>4.2.4.Final-SNAPSHOT</version>
964986
<scope>test</scope>
965987
</dependency>
966988
<dependency>
967989
<groupId>io.netty</groupId>
968990
<artifactId>netty-transport-native-kqueue</artifactId>
969991
<classifier>osx-aarch_64</classifier>
992+
<version>4.2.4.Final-SNAPSHOT</version>
970993
<scope>test</scope>
971994
</dependency>
972995
</dependencies>

vertx-core/src/main/java/io/vertx/core/http/impl/HttpServerConnectionInitializer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ public class HttpServerConnectionInitializer {
9191
streamContextSupplier,
9292
connectionHandler,
9393
HttpUtils.fromVertxInitialSettings(true, options.getInitialSettings()),
94+
options.getHttp2RstFloodMaxRstFramePerWindow(),
95+
options.getHttp2RstFloodWindowDuration(),
9496
options.getLogActivity());
9597
} else {
9698
http2ChannelInitalizer = new Http2CodecServerChannelInitializer(

vertx-core/src/main/java/io/vertx/core/http/impl/http2/codec/Http2CodecServerChannelInitializer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public VertxHttp2ConnectionHandler<Http2ServerConnectionImpl> buildHttp2Connecti
7575
.useCompression(compressionManager != null ? compressionManager.options() : null)
7676
.gracefulShutdownTimeoutMillis(0)
7777
.decoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow)
78+
.encoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow)
7879
.useDecompression(options.isDecompressionSupported())
7980
.initialSettings(options.getInitialSettings())
8081
.connectionFactory(connHandler -> {

vertx-core/src/main/java/io/vertx/core/http/impl/http2/codec/Http2ConnectionImpl.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,16 +208,20 @@ public void onPriorityRead(ChannelHandlerContext ctx, int streamId, int streamDe
208208

209209
@Override
210210
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, int padding, boolean endOfStream) throws Http2Exception {
211-
StreamPriority streamPriority = new StreamPriority()
212-
.setDependency(streamDependency)
213-
.setWeight(weight)
214-
.setExclusive(exclusive);
215-
onHeadersRead(streamId, headers, streamPriority, endOfStream);
211+
if (goAwayStatus == null) {
212+
StreamPriority streamPriority = new StreamPriority()
213+
.setDependency(streamDependency)
214+
.setWeight(weight)
215+
.setExclusive(exclusive);
216+
onHeadersRead(streamId, headers, streamPriority, endOfStream);
217+
}
216218
}
217219

218220
@Override
219221
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding, boolean endOfStream) throws Http2Exception {
220-
onHeadersRead(streamId, headers, null, endOfStream);
222+
if (goAwayStatus == null) {
223+
onHeadersRead(streamId, headers, null, endOfStream);
224+
}
221225
}
222226

223227
protected abstract void onHeadersRead(int streamId, Http2Headers headers, StreamPriority streamPriority, boolean endOfStream);

vertx-core/src/main/java/io/vertx/core/http/impl/http2/codec/VertxHttp2ConnectionHandlerBuilder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ public VertxHttp2ConnectionHandlerBuilder<C> decoderEnforceMaxRstFramesPerWindow
5353
return super.decoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow);
5454
}
5555

56+
@Override
57+
public VertxHttp2ConnectionHandlerBuilder<C> encoderEnforceMaxRstFramesPerWindow(int maxRstFramesPerWindow, int secondsPerWindow) {
58+
return super.encoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow);
59+
}
60+
5661
@Override
5762
public VertxHttp2ConnectionHandlerBuilder<C> gracefulShutdownTimeoutMillis(long gracefulShutdownTimeoutMillis) {
5863
return super.gracefulShutdownTimeoutMillis(gracefulShutdownTimeoutMillis);

vertx-core/src/main/java/io/vertx/core/http/impl/http2/multiplex/Http2CustomFrameCodecBuilder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ public Http2CustomFrameCodecBuilder initialSettings(Http2Settings settings) {
3030
return (Http2CustomFrameCodecBuilder) super.initialSettings(settings);
3131
}
3232

33+
@Override
34+
public Http2CustomFrameCodecBuilder encoderEnforceMaxRstFramesPerWindow(int maxRstFramesPerWindow, int secondsPerWindow) {
35+
return (Http2CustomFrameCodecBuilder) super.encoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow);
36+
}
37+
38+
@Override
39+
public Http2CustomFrameCodecBuilder decoderEnforceMaxRstFramesPerWindow(int maxRstFramesPerWindow, int secondsPerWindow) {
40+
return (Http2CustomFrameCodecBuilder) super.decoderEnforceMaxRstFramesPerWindow(maxRstFramesPerWindow, secondsPerWindow);
41+
}
42+
3343
@Override
3444
public Http2CustomFrameCodecBuilder server(boolean isServer) {
3545
return (Http2CustomFrameCodecBuilder) super.server(isServer);

vertx-core/src/main/java/io/vertx/core/http/impl/http2/multiplex/Http2MultiplexServerChannelInitializer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public class Http2MultiplexServerChannelInitializer implements Http2ServerChanne
3434
private final boolean decompressionSupported;
3535
private final Http2Settings initialSettings;
3636
private final Http2MultiplexConnectionFactory connectionFactory;
37+
private final int rstFloodMaxRstFramePerWindow;
38+
private final int rstFloodWindowDuration;
3739
private final boolean logEnabled;
3840

3941
public Http2MultiplexServerChannelInitializer(ContextInternal context,
@@ -44,6 +46,8 @@ public Http2MultiplexServerChannelInitializer(ContextInternal context,
4446
Supplier<ContextInternal> streamContextSupplier,
4547
Handler<HttpServerConnection> connectionHandler,
4648
Http2Settings initialSettings,
49+
int rstFloodMaxRstFramePerWindow,
50+
int rstFloodWindowDuration,
4751
boolean logEnabled) {
4852
Http2MultiplexConnectionFactory connectionFactory = (handler, chctx) -> {
4953
Http2MultiplexServerConnection connection = new Http2MultiplexServerConnection(
@@ -61,6 +65,8 @@ public Http2MultiplexServerChannelInitializer(ContextInternal context,
6165
this.connectionFactory = connectionFactory;
6266
this.compressionManager = compressionManager;
6367
this.decompressionSupported = decompressionSupported;
68+
this.rstFloodMaxRstFramePerWindow = rstFloodMaxRstFramePerWindow;
69+
this.rstFloodWindowDuration = rstFloodWindowDuration;
6470
this.logEnabled = logEnabled;
6571
}
6672

@@ -74,6 +80,8 @@ public void configureHttp2(ContextInternal context, ChannelPipeline pipeline, bo
7480

7581
Http2FrameCodec frameCodec = new Http2CustomFrameCodecBuilder(compressionManager, decompressionSupported)
7682
.server(true)
83+
.decoderEnforceMaxRstFramesPerWindow(rstFloodMaxRstFramePerWindow, rstFloodWindowDuration)
84+
.encoderEnforceMaxRstFramesPerWindow(rstFloodMaxRstFramePerWindow, rstFloodWindowDuration)
7785
.initialSettings(initialSettings)
7886
.logEnabled(logEnabled)
7987
.build();

0 commit comments

Comments
 (0)