YARP Not Working, Using .NET Upgrade Assistant

626 views Asked by At

I used the .Net Upgrade Assistant to upgrade our site project from 4.8 to 7. It created a parallel app and I am attempting to follow the steps in a Migrating ASP.NET YouTube series I found. The .net 7 project runs and returns a "hellow world" from a new test controller, but returns 502s when attempting to proxy the old app. The old 4.8 app is unusual in that we have IIS local URLs (i.e. local.foo.com instead of localhost:7000) setup on our local machines using the IIS Express Development Certificate. I did get the migration proxy to work with one of our other apps that uses IIS Express, but I am having difficulty figuring out what configuration might be be missing from either the old or new apps so that the proxy will work.

This is from the debug console:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:7055
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5055
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\PUE.Development\lms\Web.SiteCore
info: Yarp.ReverseProxy.Forwarder.HttpForwarder[9]
      Proxying to https://local.foo.com/ HTTP/2 RequestVersionOrLower no-streaming
info: Yarp.ReverseProxy.Forwarder.HttpForwarder[48]
      Request: An error was encountered before receiving a response.
      System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
    ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch
         at System.Net.Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions)
         at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
         at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
         --- End of inner exception stack trace ---
         at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.AddHttp2ConnectionAsync(QueueItem queueItem)
         at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.HttpConnectionWaiter`1.WaitForConnectionAsync(Boolean async, CancellationToken requestCancellationToken)
         at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
         at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
         at Yarp.ReverseProxy.Forwarder.HttpForwarder.SendAsync(HttpContext context, String destinationPrefix, HttpMessageInvoker httpClient, ForwarderRequestConfig requestConfig, HttpTransformer transformer, CancellationToken cancellationToken)

Here is the code the Upgrade Assistant generated for the new application's Program.cs:


var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSystemWebAdapters();
builder.Services.AddHttpForwarder();

// Add services to the container.
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseAuthorization();
app.UseSystemWebAdapters();

app.MapDefaultControllerRoute();
app.MapForwarder("/{**catch-all}", app.Configuration["ProxyTo"])
    .Add(static builder => ((RouteEndpointBuilder)builder).Order = int.MaxValue);

app.Run();

From debug launch profiles UI

2

There are 2 answers

0
JoxWar On BEST ANSWER

How I wound up solving this was I needed to run both the Core and Framework apps at the same time, I changed it to localhost and gave up on local IIS setup though I have gotten IIS setup on the dev servers, and then the proxy URL to the Framework app needs to be to a https URL using a 40000 port number. In the browser I needed to make sure the Core app was being launched as https as well.

1
Bug Maker On

I was also getting 502 errors in my upgrade. In my case, this was because the upgrade assistant got my initial project config https://localhost:[port] and used that to proxy. The problem is that the cert used on localhost is self-signed so unless you want to do some hacky things to HttpClient, the cert will be rejected as untrusted.

I changed the NET Framework project to instead be configured to HTTP and the NET core has the HTTPS config. So the flow goes browser --> NET Core App (HTTPS) --> NET Framework App (HTTP)

In Web.Config (NET Framework) <httpCookies httpOnlyCookies="true" requireSSL="false" />

In Global.asax.cs (NET Framework) System.Web.Helpers.AntiForgeryConfig.RequireSsl = false;

And finally in my controller classes (NET Framework) I removed [RequireHttps] attributes

Even if this doesn't fit your above scenario exactly, I'd consider adding a new local URL like localinternal.foo.com that is only HTTP and have the new app point to that URL instead of local.foo.com.