-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Kestrel: Ability to capture HTTP2 errors #53377
Comments
As you probably already know (but, for the sake of others reading this later), that message indicates that a client is behaving as if it's performing a Rapid Reset attack. One of the reasons we decided to close the connection but not flag the particular client was because the immediate client could be a proxy representing many different users. That reasoning may not apply to your particular server, but it's worth considering. Another thing to note is that the limit is configurable. If you find that the default value is not providing adequate protection (i.e. your CPU is hitting 100% and your proxy is nearly unavailable), you can try reducing |
When you see that log message, the corresponding connection will see a TCP |
Error happens when connection still considered alive, and we have responses to write there.
Correct, and Kestrel actually can't do that itself(there only can be some interface to be implemented for marking clients. actually their src ip even, since connection already broken) So, what i want is easier way to access such things, i currently found that with context replacement in ListenOption.Use i can capture error, but did not tested yet. |
What about using something like a logger provider? internal sealed class RapidResetLoggerProvider : ILoggerProvider
{
public static readonly ILoggerProvider Instance = new RapidResetLoggerProvider();
private RapidResetLoggerProvider() { }
public ILogger CreateLogger(string _categoryName) => RapidResetLogger.Instance;
public void Dispose() { }
private class RapidResetLogger : ILogger
{
public static readonly ILogger Instance = new RapidResetLogger();
private RapidResetLogger() { }
public IDisposable BeginScope<TState>(TState _state) => DummyDisposable.Instance;
public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Debug;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
switch (eventId.Name)
{
case "Http2FlowControlQueueOperationsExceeded":
// Handler goes here
break;
}
}
private sealed class DummyDisposable : IDisposable
{
public static readonly IDisposable Instance = new DummyDisposable();
private DummyDisposable() { }
public void Dispose() { }
}
}
} |
I will prefer context replacement, since logger don't have access to context itself, so there i can't access src ip for example and so on. |
Is there an existing issue for this?
Is your feature request related to a problem? Please describe the problem.
I am using Kestrel with YARP in place of nginx, i did implemented some basic ban with ipset for bad requests.
Once i found much of records in logs:
crit: Microsoft.AspNetCore.Server.Kestrel.Http2[60] Connection id "0HN0HCNL3FVF3" exceeded the output operations maximum queue size. Microsoft.AspNetCore.Connections.ConnectionAbortedException: HTTP/2 connection exceeded the output operations maximum queue size.
CPU load was 100% at that time, and proxy was nearly not avaliable.
i checked sources, and can't find the way to capture such errors(most of such errors are writen into log, and passed as argument to FrameWriter, but not exposed anywhere).
I want to capture such errors and ban addresses which generate too much errors.
Describe the solution you'd like
one of the option i can think of is make and expose IConnectionAbortReasonFeature, which will be added to connection. and can be examined with in connection builder middleware.(after call to next in chain of course), with some kind enum, like it is done in YARP with ForwarderError enum)
Additional context
Currently i found possible way to capture exception, by making wrapping Connectioncontext into own one and overriding Abort method(all other prop and methods just proxy toold context), but i can't see this as good solution.
The text was updated successfully, but these errors were encountered: