From f11a98b4afe7cda2e988935e57b1f86ae1c41501 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Tue, 15 Oct 2024 14:45:04 +0100 Subject: [PATCH] Slacken DoS heuristics for clients Motivation: NIO HTTP/2 has some DoS heuristics related to receiving RST_STREAM frames within a certain period of time. However, in gRPC if a server rejects a request it will close the stream early and send a RST_STREAM frame, this makes clients quite likely to trigger the DoS heuristics by accident, resulting in the client closing the connection. Modifications: Decrease the timing window during which we're allowed to receive RST_STREAM frames. Result: Less likely to hit a false positive for DoS limits on the client. --- .../Internal/NIOChannelPipeline+GRPC.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Sources/GRPCNIOTransportCore/Internal/NIOChannelPipeline+GRPC.swift b/Sources/GRPCNIOTransportCore/Internal/NIOChannelPipeline+GRPC.swift index 1254147..b53dd08 100644 --- a/Sources/GRPCNIOTransportCore/Internal/NIOChannelPipeline+GRPC.swift +++ b/Sources/GRPCNIOTransportCore/Internal/NIOChannelPipeline+GRPC.swift @@ -131,6 +131,16 @@ extension ChannelPipeline.SynchronousOperations { HTTP2Setting(parameter: .maxHeaderListSize, value: HPACKDecoder.defaultMaxHeaderListSize), ] + // These rates inform NIO's DoS detection heuristics which typically apply to a server. The + // rate at which RST_STREAM frames are permitted is increased for the client as clients are + // likely to receive 'RST_STREAM' frames if the server rejects RPCs (i.e. the server sends a + // trailers-only response). + // + // The default values are 200 in a 30 second period. Allow the same number of failures in a + // shorter period. + http2.stream.streamResetFrameRateLimit.maximumCount = 200 + http2.stream.streamResetFrameRateLimit.windowLength = .seconds(10) + let connectionHandler = ClientConnectionHandler( eventLoop: self.eventLoop, maxIdleTime: config.connection.maxIdleTime.map { TimeAmount($0) },