Rico Suter's blog.
 


The following steps describe how to set up an Azure Web App for Container to act as a Nginx reverse proxy to an other application. I used this to redirect all HTTP calls from a public domain into an internal Azure VM. The benefit is that this way you can still use App Service specific features like certificate handling or the AD-based authentication; and also SSL termination is handled by the proxy (the application runs only on HTTP).

Create Web App for Containers

In the Azure Portal create a new Web App for Containers resource:

Choose “Docker Container” as Publish method and “Linux” as Operating System:

Setup Nginx container

In the newly created Web App for Containers go to the Deployment Center and choose “nginx:latest” as Docker image:

Map storage with configuration

Next, create a new Azure Storage and a new storage container (e.g. nginx). In this container create a new nginx.config file:

events {}
http {
    server {
        location / {
            proxy_pass http://yourtargethost/;

            proxy_set_header X-Forwarded-Host mynginxsample.azurewebsites.net;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            proxy_pass_request_headers on;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
        }
    }
}

mynginxsample.azurewebsites.net is the public host address the external clients will use; http://yourtargethost/ is the host where the requests should be redirected to. The following headers are needed so that the target application knows the original host name:

proxy_set_header X-Forwarded-Host mynginxsample.azurewebsites.net;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

To support web socket connection pass through, use the following options (required for e.g. SignalR):

proxy_pass_request_headers on;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";

In the App Service, go to Configuration and create a new Path Mapping with the Mount path /etc/nginx:

Optional: Enable forwarded header processing in ASP.NET Core

In ASP.NET Core you need to enable the processing of forwarded headers (X-Forwarded-*), so that the application uses the correct public host names. To enable the feature, add the following configuration code:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = ForwardedHeaders.All;

        // allow all (for security reasons, this should only be used when 
        // only the proxy can access the application directly)
        options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("0.0.0.0"), 0));
    });

    ...
}

Then enable the configuration in the HTTP pipeline with:

public void Configure(IApplicationBuilder app, IHostEnvironment env, ILogger<Startup> logger)
{
    app.UseForwardedHeaders();

    ...
}

The code above should only be executed when the application is actually running behind a proxy (i.e. consider putting it behind a configuration flag). For more information see Configure ASP.NET Core to work with proxy servers and load balancers.

Restart the app

Now restart the app so that the configuration is picked up and you should have the Nginx proxy running.



Discussion