Reputation: 1347
We have recently migrated an ASP.NET MVC 5 application to ASP.NET Core 2.2.
Everything seems to be working fine, however we are getting the following exception on a fairly regular basis (about three times a second, more on that in a moment):
BadHttpRequestException: Invalid Host header: '~^appname.*$'
Module "Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException", line 0, col 0, in Throw
Void Throw(Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.RequestRejectionReason, System.String)
Module "Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection", line 95, col 0, in EnsureHostHeaderExists
Void EnsureHostHeaderExists()
Module "Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection", line 196, col 0, in TryParseRequest
Boolean TryParseRequest(System.IO.Pipelines.ReadResult, Boolean ByRef)
Module "Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol+<ProcessRequests>d__185`1", line 170, col 0, in MoveNext
Void MoveNext()
Module "System.Runtime.ExceptionServices.ExceptionDispatchInfo", line 12, col 0, in Throw
Void Throw()
Module "System.Runtime.CompilerServices.TaskAwaiter", line 46, col 0, in HandleNonSuccessAndDebuggerNotification
Void HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
Module "Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol+<ProcessRequestsAsync>d__184`1", line 135, col 0, in MoveNext
Void MoveNext()
In consulting with a member of our ops team it's clear that we have three instances of HAProxy all checking each node of our application about once a second.
Every request to this application would flow as follows:
HAProxy -> Nginx -> Kestrel/ASP.NET Core application
My question is, how can I determine what is going on here?
Upvotes: 5
Views: 1994
Reputation: 1347
The current version of Kestrel (we're using ASP.NET Core 2.2) does not support HTTP access logging.
See this issue: Support access logging with Common Log Format/Extended Log Format
In order to track down the issue I had to have our ops team review our nginx logs (nginx is the reverse proxy we're using) to determine where requests with the invalid host header were coming from.
The issue turned out to be a mal-configured status checking application.
Upvotes: 3
Reputation: 1265
I guess you should pass there some valid Url, or asterisk, or forward slash
The code responsible for parsing is here https://github.com/aspnet/KestrelHttpServer/blob/b8a1c04ffbeee6c60a74766142ff3e2e6779d701/src/Kestrel.Core/Internal/Http/Http1Connection.cs
public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
{
Debug.Assert(target.Length != 0, "Request target must be non-zero length");
var ch = target[0];
if (ch == ByteForwardSlash)
{
// origin-form.
// The most common form of request-target.
// https://tools.ietf.org/html/rfc7230#section-5.3.1
OnOriginFormTarget(method, version, target, path, query, customMethod, pathEncoded);
}
else if (ch == ByteAsterisk && target.Length == 1)
{
OnAsteriskFormTarget(method);
}
else if (target.GetKnownHttpScheme(out var scheme))
{
OnAbsoluteFormTarget(target, query);
}
else
{
// Assume anything else is considered authority form.
// FYI: this should be an edge case. This should only happen when
// a client mistakenly thinks this server is a proxy server.
OnAuthorityFormTarget(method, target);
}
Method = method != HttpMethod.Custom
? HttpUtilities.MethodToString(method) ?? string.Empty
: customMethod.GetAsciiStringNonNullCharacters();
_httpVersion = version;
Debug.Assert(RawTarget != null, "RawTarget was not set");
Debug.Assert(Method != null, "Method was not set");
Debug.Assert(Path != null, "Path was not set");
Debug.Assert(QueryString != null, "QueryString was not set");
Debug.Assert(HttpVersion != null, "HttpVersion was not set");
}
For example, we send in Host header the host of LoadBalancer like dc-lb.company-dc.lan, in your scenario I guess it should be the hostname of your HAProxy instance
Upvotes: 1