I'm hosting an ASP.NET Core application in out-of-process mode using IIS. My goal is to:
- Configure IIS with an HTTPS binding on a specific port (e.g., 9000) for regular traffic.
- Have Kestrel separately configured on another port (e.g., 9001) specifically for API endpoints using mutual TLS (mTLS).
Here's my problem:
When launching the app via IIS, I consistently receive the following warning in logs:
Microsoft.AspNetCore.Server.Kestrel | Overriding endpoints defined via IConfiguration and/or UseKestrel() because PreferHostingUrls is set to true. Binding to address(es) 'http://localhost:{randomPort}'.
I have tried the following to prevent IIS from overriding my Kestrel configuration:
- Setting
PreferHostingUrls
to false inProgram.cs
:
webBuilder.UseSetting(WebHostDefaults.PreferHostingUrlsKey, "false");
- Setting the environment variable
ASPNETCORE_PREFERHOSTINGURLS
tofalse
directly in the web.config file:
<environmentVariables>
<environmentVariable name="ASPNETCORE_PREFERHOSTINGURLS" value="false" />
</environmentVariables>
Despite these settings, IIS continues to override the Kestrel bindings, forcing Kestrel to listen on a dynamically assigned localhost port.
Question:
- How can I ensure that Kestrel uses the port I explicitly configured (port 9001 with mTLS) without IIS overriding it?
- Is there a proper way to split traffic so that IIS manages HTTPS on one port (9000) and forwards specific paths (like
/api
) to Kestrel, where mTLS is applied?
Thank you for any help or insights!
I'm hosting an ASP.NET Core application in out-of-process mode using IIS. My goal is to:
- Configure IIS with an HTTPS binding on a specific port (e.g., 9000) for regular traffic.
- Have Kestrel separately configured on another port (e.g., 9001) specifically for API endpoints using mutual TLS (mTLS).
Here's my problem:
When launching the app via IIS, I consistently receive the following warning in logs:
Microsoft.AspNetCore.Server.Kestrel | Overriding endpoints defined via IConfiguration and/or UseKestrel() because PreferHostingUrls is set to true. Binding to address(es) 'http://localhost:{randomPort}'.
I have tried the following to prevent IIS from overriding my Kestrel configuration:
- Setting
PreferHostingUrls
to false inProgram.cs
:
webBuilder.UseSetting(WebHostDefaults.PreferHostingUrlsKey, "false");
- Setting the environment variable
ASPNETCORE_PREFERHOSTINGURLS
tofalse
directly in the web.config file:
<environmentVariables>
<environmentVariable name="ASPNETCORE_PREFERHOSTINGURLS" value="false" />
</environmentVariables>
Despite these settings, IIS continues to override the Kestrel bindings, forcing Kestrel to listen on a dynamically assigned localhost port.
Question:
- How can I ensure that Kestrel uses the port I explicitly configured (port 9001 with mTLS) without IIS overriding it?
- Is there a proper way to split traffic so that IIS manages HTTPS on one port (9000) and forwards specific paths (like
/api
) to Kestrel, where mTLS is applied?
Thank you for any help or insights!
Share asked Mar 7 at 20:04 Mselmi AliMselmi Ali 1,2655 gold badges19 silver badges32 bronze badges 1- 1 ASP.NET Core module/IIS wasn't designed for your specific needs, but you can run your web app on Kestrel separately and then use IIS/ARR as reverse proxy. – Lex Li Commented Mar 8 at 8:53
1 Answer
Reset to default 0First create site in iis and set the https binding with 9000 port number
In that site set the rule for the /api url to forward the request to the kestrel:
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="^/api/(.*)" />
<conditions>
</conditions>
<action type="Rewrite" url="https://localhost:9001/{R:1}" logRewrittenUrl="true" />
</rule>
</rules>
</rewrite>
And make sure in your kestrel you have set the https url correctly as shown in this link https://learn.microsoft/en-us/aspnet/core/fundamentals/servers/kestrel/endpoints?view=aspnetcore-9.0
You have set this code in program.cs file:
builder.WebHost.UseSetting(WebHostDefaults.PreferHostingUrlsKey, "false");
builder.WebHost.UseKestrel(options =>
{
options.ListenAnyIP(9001, listenOptions =>
{
listenOptions.UseHttps(new HttpsConnectionAdapterOptions
{
ClientCertificateMode = ClientCertificateMode.RequireCertificate,
SslProtocols = System.Security.Authentication.SslProtocols.Tls12
});
});
});
Your full web.config should look like this:
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\WebApplication3.dll" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" hostingModel=""OutOfProcess">
<environmentVariables>
<environmentVariable name="ASPNETCORE_PREFERHOSTINGURLS" value="false" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</location>
<system.webServer>
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="^/api/(.*)" />
<conditions>
</conditions>
<action type="Rewrite" url="https://localhost:9001/{R:1}" logRewrittenUrl="true" />
</rule>
</rules>
</rewrite>
<tracing>
<traceFailedRequests>
<add path="*">
<traceAreas>
<add provider="ASP" verbosity="Verbose" />
<add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />
<add provider="ISAPI Extension" verbosity="Verbose" />
<add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,FastCGI,WebSocket,ANCM,Rewrite,RequestRouting" verbosity="Verbose" />
</traceAreas>
<failureDefinitions statusCodes="200-600" />
</add>
</traceFailedRequests>
</tracing>
</system.webServer>
You can ignore the failed request tracing part that i have added for testing.