简体   繁体   中英

Docker + Asp.net core api + Apache : infinite redirect loop

I am trying to containerize all things related to my web app (Asp.net Core API) using Docker Compose, including SSL Certificates (Certbot) on a VPS OVH Debian+Apache. I have an infinite redirect loop.

If anyone can spot where I am going wrong, I would be extremely grateful!

Docker-compose.yml:

my_app_prod:
        image: "myapp/my-app_prod:latest"
        restart: always
        ports:
          - "83:80"
          - "85:443"
        network_mode: bridge

www.my-domain.com.conf :

<VirtualHost *:*>
    RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>

<VirtualHost *:80>
    ServerName www.my-domain.com
    ProxyPreserveHost On
    
    ProxyPass / http://127.0.0.1:83/
    ProxyPassReverse / http://127.0.0.1:83/
    ProxyPassReverseCookieDomain 127.0.0.1 www.my-domain.com

    RewriteEngine on
    RewriteCond %{SERVER_NAME} =www.my-domain.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

    ErrorLog ${APACHE_LOG_DIR}helloapp-error.log
    CustomLog ${APACHE_LOG_DIR}helloapp-access.log common

</VirtualHost>

www.my-domain.com-le-ssl.conf :

<VirtualHost *:*>
    RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
    RequestHeader set "X-Forwarded-For" expr=%{REMOTE_ADDR}e
</VirtualHost>

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName api.nicepet.fr
    ProxyPreserveHost On

    ProxyPass / http://127.0.0.1:83/
    ProxyPassReverse / http://127.0.0.1:83/
    ProxyPassReverseCookieDomain 127.0.0.1 api.nicepet.fr


SSLCertificateFile /etc/letsencrypt/live/api.nicepet.fr/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/api.nicepet.fr/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Startup.cs:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<PathFilter>();
            services.AddDbContext<ApiNicepetContext>(item => item.UseMySql(Configuration.GetConnectionString("DefaultConnection")));
            
            services.AddControllers(mvcOptions => mvcOptions.EnableEndpointRouting = false);
            services.AddOData();
            //services.AddTransient();
            services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
            {
                builder.AllowAnyOrigin()
                       .AllowAnyMethod()
                       .AllowAnyHeader();
            }));
            
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            var forwardedHeadersOptions = new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
                RequireHeaderSymmetry = false
            };
            forwardedHeadersOptions.KnownNetworks.Clear();
            forwardedHeadersOptions.KnownProxies.Clear();

            app.UseForwardedHeaders(forwardedHeadersOptions);

            app.UseAuthentication();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
               
            }

            //app.UseHttpsRedirection();
            app.UseCors("MyPolicy");
            app.UseMvc(routeBuilder =>
            {
                routeBuilder.EnableDependencyInjection();
                routeBuilder.Select().Filter().Expand();
                routeBuilder.MapODataServiceRoute("OData", "odata", GetEdmModel());
            });
        }

Appsettings.json:

{
  "https_port": 443,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
//…
}

Program.cs:

//...
public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>().UseUrls("http://*:80");
                });

I believe that your application doesn't see that request is already coming over SSL because the reverse proxy you configured is responsible for SSL termination. It tries to redirect all requests to 443 with app.UseHttpsRedirection(); and it goes to the infinite loop.

Try to set up the ForwardedHeaders middleware like it's described in the answer to this question .

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