mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Address feedback and some simplification
This commit is contained in:
parent
0f8b6a9fda
commit
80b2a5b86a
2 changed files with 23 additions and 29 deletions
|
@ -201,8 +201,8 @@ similar to a supervisor restart intensity/period.
|
||||||
|
|
||||||
max_cancel_stream_rate ({500, 10000})::
|
max_cancel_stream_rate ({500, 10000})::
|
||||||
|
|
||||||
Maximum cancel stream rate per connection. This can be used to protect
|
Maximum cancel stream rate per connection. This can be used to
|
||||||
against the rapid reset attack (CVE-2023-44487), by limiting the
|
protect against misbehaving or malicious peers, by limiting the
|
||||||
number of streams that the peer can reset over a certain time period.
|
number of streams that the peer can reset over a certain time period.
|
||||||
The rate is expressed as a tuple `{NumCancels, TimeMs}`. This is
|
The rate is expressed as a tuple `{NumCancels, TimeMs}`. This is
|
||||||
similar to a supervisor restart intensity/period.
|
similar to a supervisor restart intensity/period.
|
||||||
|
|
|
@ -576,21 +576,30 @@ early_error(State0=#state{ref=Ref, opts=Opts, peer=Peer},
|
||||||
send_headers(State0, StreamID, fin, StatusCode0, RespHeaders0)
|
send_headers(State0, StreamID, fin, StatusCode0, RespHeaders0)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
rst_stream_frame(State0=#state{streams=Streams0, children=Children0}, StreamID, Reason) ->
|
rst_stream_frame(State=#state{streams=Streams0, children=Children0}, StreamID, Reason) ->
|
||||||
State1 = case maps:take(StreamID, Streams0) of
|
case maps:take(StreamID, Streams0) of
|
||||||
{#stream{state=StreamState}, Streams} ->
|
{#stream{state=StreamState}, Streams} ->
|
||||||
terminate_stream_handler(State0, StreamID, Reason, StreamState),
|
terminate_stream_handler(State, StreamID, Reason, StreamState),
|
||||||
Children = cowboy_children:shutdown(Children0, StreamID),
|
Children = cowboy_children:shutdown(Children0, StreamID),
|
||||||
State0#state{streams=Streams, children=Children};
|
cancel_rate_limit(State#state{streams=Streams, children=Children});
|
||||||
error ->
|
error ->
|
||||||
State0
|
State
|
||||||
end,
|
end.
|
||||||
case cancel_rate(State1) of
|
|
||||||
{ok, State} ->
|
cancel_rate_limit(State0=#state{cancel_rate_num=Num0, cancel_rate_time=Time}) ->
|
||||||
State;
|
case Num0 - 1 of
|
||||||
error ->
|
0 ->
|
||||||
terminate(State1, {connection_error, enhance_your_calm,
|
CurrentTime = erlang:monotonic_time(millisecond),
|
||||||
'Stream cancel rate larger than configuration allows. Flood? (CVE-2023-44487)'})
|
if
|
||||||
|
CurrentTime < Time ->
|
||||||
|
terminate(State0, {connection_error, enhance_your_calm,
|
||||||
|
'Stream cancel rate larger than configuration allows. Flood? (CVE-2023-44487)'});
|
||||||
|
true ->
|
||||||
|
%% When the option has a period of infinity we cannot reach this clause.
|
||||||
|
init_cancel_rate_limiting(State0, CurrentTime)
|
||||||
|
end;
|
||||||
|
Num ->
|
||||||
|
State0#state{cancel_rate_num=Num}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
ignored_frame(State=#state{http2_machine=HTTP2Machine0}) ->
|
ignored_frame(State=#state{http2_machine=HTTP2Machine0}) ->
|
||||||
|
@ -1157,21 +1166,6 @@ reset_rate(State0=#state{reset_rate_num=Num0, reset_rate_time=Time}) ->
|
||||||
{ok, State0#state{reset_rate_num=Num}}
|
{ok, State0#state{reset_rate_num=Num}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
cancel_rate(State0=#state{cancel_rate_num=Num0, cancel_rate_time=Time}) ->
|
|
||||||
case Num0 - 1 of
|
|
||||||
0 ->
|
|
||||||
CurrentTime = erlang:monotonic_time(millisecond),
|
|
||||||
if
|
|
||||||
CurrentTime < Time ->
|
|
||||||
error;
|
|
||||||
true ->
|
|
||||||
%% When the option has a period of infinity we cannot reach this clause.
|
|
||||||
{ok, init_cancel_rate_limiting(State0, CurrentTime)}
|
|
||||||
end;
|
|
||||||
Num ->
|
|
||||||
{ok, State0#state{cancel_rate_num=Num}}
|
|
||||||
end.
|
|
||||||
|
|
||||||
stop_stream(State=#state{http2_machine=HTTP2Machine}, StreamID) ->
|
stop_stream(State=#state{http2_machine=HTTP2Machine}, StreamID) ->
|
||||||
case cow_http2_machine:get_stream_local_state(StreamID, HTTP2Machine) of
|
case cow_http2_machine:get_stream_local_state(StreamID, HTTP2Machine) of
|
||||||
%% When the stream terminates normally (without sending RST_STREAM)
|
%% When the stream terminates normally (without sending RST_STREAM)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue