简体   繁体   中英

EDIT: NGINX reverse proxy ASP.NET Core 5.0: localhost:5000 closes connection but www.google.com works

I'm trying to deploy my ASP.NET web Application (with .NET 5.0 and ASP.NET MVC) to an debian 10 server with NGINX. I followed Microsoft's tutorial and after numerous testings can't find something that will work.

My current NGINX configuration:

server {
    listen  80 default_server;

    location / {
        proxy_pass          http://localhost:5000;
        proxy_http_version  1.1;
        proxy_set_header    Upgrade $http_upgrade;
        proxy_set_header    Connection keep-alive;
        proxy_set_header    Host $host;
        proxy_cache_bypass  $http_upgrade;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto $scheme;
    }
}

Querying localhost with curl -v localhost:5000 gives me HTTP 307 redirect.

Querying curl -v --insecure https://localhost:5001 returns the actual content of my webpage, so kestrel is running fine.

My Startup.cs looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

using SmapOneUpdater.Frontend.Model.Sortenumbuchung.Data;

namespace SmapOneUpdater.Frontend
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders =
                    ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
            });
            services.AddDbContext<SortenumbuchungContext>(options =>
                    options.UseSqlite(Configuration.GetConnectionString("SortenumbuchungContext")));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseForwardedHeaders();
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Overview}/{action=Index}/{id?}");
            });
        }
    }
}

Connecting to the ip-address of my server returns "This site can't be reached xxxx unexpectedly closed the connection" after some loading. and it automatically changes the url to xxxx:5001 which should be wrong since I'm not trying to directly access port 5001, or am I?

Nevertheless, I'm pretty sure it's not my NGINX configuration, since my browser somehow gets the information that he needs port 5001 AND because if I change the proxy_pass to https://www.google.com it works and redirects me to google

EDIT: SOLVED

The problem was inside my Properties/launchSettings.json. I had the applicationUrl set to http://localhost:5000;https://localhost:5001 It seems like ASP then only allows connections which call localhost (or 127.0.0.1). Since I couldn't reach kestrel from the server when calling it by ip. After that, I had to change nginx to forward the servers IP address, so the accessing client won't try to access localhost:5001 but the servers IP address with port 5001.

I'm setting the urls on the runtime environment now with the --urls command. So my call looks like this:

dotnet /path/to/application/dll --urls "http://*:5000;https://*:5001"

As for NGINX, after reading TheRoadrunner's answer, I changed the config to redirect HTTP requests to HTTPS. Following the tutorial from NGINX I also created a self signed ssl certificate with:

openssl req -x509 -subj /CN=localhost -days 365 -set_serial 2 -newkey rsa:4096 -keyout /etc/nginx/cert.key -nodes -out /etc/nginx/cert.pem

My working NGINX config looks like this:

server {
    listen 80;

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;

    ssl_certificate /etc/nginx/cert.pem;
    ssl_certificate_key /etc/nginx/cert.key;

    location / {
        proxy_pass          https://192.168.4.156:5001;
        proxy_set_header    Host $http_host;
        proxy_set_header    X-Real-IP               $remote_addr;
        proxy_set_header    X-Forwarded-For         $proxy_add_x_forwarded_for;
    }
}

Interestengly enough, with this working configuration the port in my url bar in the browser does not show, that it's accessing port 5001

How did I found out

Maybe this will be interesting for some readers. I figured the issue out, by creating a local debian instance with virtualbox. I configured it just as my real server. But I installed GNOME, because I wanted to make sure, whether I can actually see the page with a local browser or not (In retrospective, I probably could've achieved this with curl).

It seemed interesting to me, since the redirect worked on the vm. entering localhost:80 in firefox redirected me to localhost:5001 and I saw the page. After some testing I tried it with the IP of the VM and had the exact same issue as on the other machines. So I tried to change the application URL.

I think this is interesting, since it seems so obvious, but was never mentioned in the documentation. As a proxy/nginx/webdev newbie I was not exactly sure how all of this works. Especially since the documentation mentions to redirect HTTPS to http://localhost:5000

I think you need two sections in your nginx config one for port 80 that redirects to the other on 443.

Something like:

server {
    listen 80;
   
    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    
    location / {
        http://localhost:5000
        proxy_set_header    Host                $http_host;
        proxy_set_header    X-Real-IP           $remote_addr;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    }
}

In addition you will have to handle certificates to avoid browser warnings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM