Hospedar ASP.NET Core en Linux con Nginx

Por Sourabh Shirhatti

Nota

Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión ASP.NET Core 8.0 de este artículo.

En esta guía se explica cómo configurar un entorno de ASP.NET Core listo para producción para Ubuntu, Red Hat Enterprise (RHEL) y SUSE Linux Enterprise Server.

Para información sobre otras distribuciones de Linux compatibles con ASP.NET Core, consulte Requisitos previos para .NET Core en Linux.

En esta guía:

  • Se coloca una aplicación ASP.NET Core existente detrás de un servidor proxy inverso.
  • Se configura el servidor proxy inverso para reenviar las solicitudes al servidor web de Kestrel.
  • Se garantiza que la aplicación web se ejecute al inicio como un demonio.
  • Se configura una herramienta de administración de procesos para ayudar a reiniciar la aplicación web.

Requisitos previos

En cualquier momento futuro tras actualizar el marco de trabajo compartido, reinicie las aplicaciones ASP.NET Core que hospeda el servidor.

Publicar y copiar en la aplicación

Configure la aplicación para una implementación dependiente de Framework.

Si la aplicación se ejecuta localmente en el entorno de desarrollo y no está configurada para realizar conexiones HTTPS seguras, adopte cualquiera de los enfoques siguientes:

  • Configure la aplicación para controlar las conexiones locales seguras. Para obtener más información, vea la sección Configuración de HTTPS.

  • Configure la aplicación para que se ejecute en el punto de conexión no seguro:

    • Desactive el middleware de redireccionamiento HTTPS en el entorno de desarrollo (Program.cs):

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

      Para obtener más información, consulte Usar varios entornos en ASP.NET Core.

    • Quite https://localhost:5001 (si existe) de la propiedad applicationUrl en el archivo Properties/launchSettings.json.

Para más información sobre la configuración por entorno, vea Uso de varios entornos en ASP.NET Core.

Ejecute dotnet publish desde el entorno de desarrollo para empaquetar una aplicación en un directorio (por ejemplo, bin/Release/{TARGET FRAMEWORK MONIKER}/publish, donde el marcador de posición {TARGET FRAMEWORK MONIKER} es el moniker de la plataforma de destino (TFM)) que se pueda ejecutar en el servidor:

dotnet publish --configuration Release

La aplicación también se puede publicar como una implementación independiente si prefiere no mantener .NET Core Runtime en el servidor.

Copie la aplicación de ASP.NET Core en el servidor usando una herramienta que se integre en el flujo de trabajo de la organización (como SCP o SFTP). Es habitual encontrar las aplicaciones web en el directorio var (por ejemplo, var/www/helloapp).

Nota

En un escenario de implementación de producción, un flujo de trabajo de integración continua lleva a cabo la tarea de publicar la aplicación y copiar los recursos en el servidor.

Pruebe la aplicación:

  1. Desde la línea de comandos, ejecute la aplicación: dotnet <app_assembly>.dll.
  2. En un explorador, vaya a http://<serveraddress>:<port> para comprobar que la aplicación funciona en Linux de forma local.

Configurar un servidor proxy inverso

Un proxy inverso es una configuración común para trabajar con aplicaciones web dinámicas. Un proxy inverso finaliza la solicitud HTTP y la reenvía a la aplicación ASP.NET Core.

Usar un servidor proxy inverso

Kestrel resulta muy adecuado para suministrar contenido dinámico de ASP.NET Core. Sin embargo, las funcionalidades de servicio web no son tan completas como las de los servidores, como IIS, Apache o Nginx. Un servidor proxy inverso puede reducir las cargas de trabajo, por ejemplo, suministrar contenido estático, almacenar solicitudes en caché, comprimir solicitudes y finalizar HTTPS desde el servidor HTTP. Un servidor proxy inverso puede residir en un equipo dedicado o se puede implementar junto con un servidor HTTP.

Para los fines de esta guía, se usa una única instancia de Nginx. Se ejecuta en el mismo servidor, junto con el servidor HTTP. En función de requisitos, se puede elegir una configuración diferente.

Dado que el proxy inverso reenvía las solicitudes, use el Middleware de encabezados reenviados desde el paquete Microsoft.AspNetCore.HttpOverrides, que se incluye automáticamente en aplicaciones ASP.NET Core a través del metapaquete Microsoft.AspNetCore.App del marco compartido. El middleware actualiza Request.Scheme, mediante el encabezado X-Forwarded-Proto, para que los URI de redireccionamiento y otras directivas de seguridad funcionen correctamente.

El middleware de encabezados reenviados debe ejecutarse antes de otro middleware. Hacerlo en ese orden garantiza que el middleware que se basa en la información de encabezados reenviados pueda usar los valores de encabezado para procesarlos. Para ejecutar el middleware de encabezados reenviados después del middleware de diagnóstico y control de errores, vea Orden del middleware de encabezados reenviados.

Invoque el método UseForwardedHeaders antes de llamar a otro middleware. Configure el middleware para reenviar los encabezados X-Forwarded-For y X-Forwarded-Proto:

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication();

var app = builder.Build();

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

app.UseAuthentication();

app.MapGet("/", () => "Hello ForwardedHeadersOptions!");

app.Run();

Si no se especifica ningún valor ForwardedHeadersOptions para el middleware, los encabezados predeterminados para reenviar son None.

Los servidores proxy que se ejecutan en direcciones de bucle invertido (127.0.0.0/8 o [::1]), incluida la dirección de localhost (127.0.0.1) estándar, son de confianza de forma predeterminada. Si otras redes o servidores proxy de confianza de la organización tramitan solicitudes entre Internet y el servidor web, agréguelos a la lista de KnownProxies o KnownNetworks con ForwardedHeadersOptions. En el ejemplo siguiente se agrega un servidor proxy de confianza en la dirección IP 10.0.0.100 al middleware de encabezados reenviados KnownProxies:

using Microsoft.AspNetCore.HttpOverrides;
using System.Net;

var builder = WebApplication.CreateBuilder(args);

// Configure forwarded headers
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});

builder.Services.AddAuthentication();

var app = builder.Build();

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

app.UseAuthentication();

app.MapGet("/", () => "10.0.0.100");

app.Run();

Para obtener más información, consulte Configuración de ASP.NET Core para trabajar con servidores proxy y equilibradores de carga.

Instalar Nginx

Use apt-get para instalar Nginx. El instalador crea un script de inicio systemd que ejecuta Nginx como demonio al iniciarse el sistema. Siga las instrucciones de instalación para Ubuntu en Nginx: Official Debian/Ubuntu packages (Nginx: paquetes oficiales de Debian y Ubuntu).

Nota

Si se necesitan módulos de Nginx opcionales, puede que haya que compilar Nginx desde el origen.

Puesto que Nginx se ha instalado por primera vez, ejecute lo siguiente para iniciarlo de forma explícita:

sudo service nginx start

Compruebe que un explorador muestra la página de aterrizaje predeterminada de Nginx. La página de aterrizaje está accesible en http://<server_IP_address>/index.nginx-debian.html.

Configurar Nginx

Para configurar Nginx como proxy inverso para reenviar solicitudes HTTP a la aplicación ASP.NET Core, modifique /etc/nginx/sites-available/default y vuelva a crear el vínculo simbólico. Después de crear el archivo /etc/nginx/sites-available/default, use el siguiente comando para crear el vínculo simbólico:

sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

Abra /etc/nginx/sites-available/default en un editor de texto y reemplace el contenido por el fragmento de contenido siguiente:

http {
  map $http_connection $connection_upgrade {
    "~*Upgrade" $http_connection;
    default keep-alive;
  }

  server {
    listen        80;
    server_name   example.com *.example.com;
    location / {
        proxy_pass         http://127.0.0.1:5000/;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection $connection_upgrade;
        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;
    }
  }
}

Si la aplicación es una aplicación SignalR o Blazor Server, vea Hospedaje y escalado de producción de SignalR en ASP.NET Core y Hospedaje e implementación de aplicaciones de Blazor de ASP.NET Core del lado servidor, respectivamente, para más información.

Cuando no hay ninguna coincidencia de server_name, Nginx usa el servidor predeterminado. Si no se define ningún servidor predeterminado, el primer servidor del archivo de configuración es el servidor predeterminado. Como procedimiento recomendado, agregue un servidor predeterminado específico que devuelva un código de estado de 444 en el archivo de configuración. Un ejemplo de configuración del servidor predeterminado es:

server {
    listen   80 default_server;
    # listen [::]:80 default_server deferred;
    return   444;
}

Con el archivo de configuración anterior y el servidor predeterminado, Nginx acepta tráfico público en el puerto 80 con el encabezado de host example.com o *.example.com. Las solicitudes que no coincidan con estos hosts no se reenviarán al Kestrel. Nginx reenvía las solicitudes coincidentes con Kestrel a http://127.0.0.1:5000/. Para obtener más información, vea este artículo sobre cómo Nginx procesa una solicitud. Para cambiar la IP o el puerto de Kestrel, consulte Kestrel: configuración de punto de conexión.

Advertencia

Si no se especifica una directiva de server_name adecuada, su aplicación se expone a vulnerabilidades de seguridad. Los enlaces de carácter comodín de subdominio (por ejemplo, *.example.com) no presentan este riesgo de seguridad si se controla todo el dominio primario (a diferencia de *.com, que sí es vulnerable). Para obtener más información, consulte RFC 9110: Semántica HTTP (Sección 7.2: Host y :authority).

Una vez establecida la configuración de Nginx, ejecute sudo nginx -t para comprobar la sintaxis de los archivos de configuración. Si la prueba del archivo de configuración es correcta, fuerce a Nginx a recopilar los cambios mediante la ejecución de sudo nginx -s reload.

Para ejecutar la aplicación directamente en el servidor:

  1. Vaya al directorio de la aplicación.
  2. Ejecute la aplicación: dotnet <app_assembly.dll>, donde app_assembly.dll es el nombre de archivo de ensamblado de la aplicación.

Si la aplicación se ejecuta en el servidor, pero no responde a través de Internet, compruebe el firewall del servidor y confirme que el puerto 80 está abierto. Si está usando una máquina virtual Ubuntu de Azure, agregue una regla de grupo de seguridad de red que posibilite el tráfico entrante del puerto 80. No es necesario para habilitar una regla de tráfico saliente en el puerto 80, ya que dicho tráfico se concede automáticamente al habilitar la regla de entrada.

Cuando termine de probar la aplicación, ciérrela con Ctrl+C (Windows) o +C (macOS) en el símbolo del sistema.

Aumentar keepalive_requests

keepalive_requests se puede aumentar para obtener un mayor rendimiento. Para obtener más información, consulte este problema de GitHub.

Supervisión de la aplicación

El servidor está configurado para reenviar las solicitudes realizadas a http://<serveraddress>:80 a la aplicación de ASP.NET Core que se ejecuta en Kestrel en http://127.0.0.1:5000. Sin embargo, Nginx no está configurado para administrar el proceso de Kestrel. Se puede usar systemd para crear un archivo de servicio para iniciar y supervisar la aplicación web subyacente. systemd es un sistema de inicio que proporciona muchas características eficaces para iniciar, detener y administrar procesos.

Crear el archivo de servicio

Cree el archivo de definición de servicio:

sudo nano /etc/systemd/system/kestrel-helloapp.service

El ejemplo siguiente es un archivo de servicio .ini para la aplicación:

[Unit]
Description=Example .NET Web API App running on Linux

[Service]
WorkingDirectory=/var/www/helloapp
ExecStart=/usr/bin/dotnet /var/www/helloapp/helloapp.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_NOLOGO=true

[Install]
WantedBy=multi-user.target

En el ejemplo anterior, el usuario que administra el servicio se especifica mediante la opción User. El usuario (www-data) debe existir y tener la propiedad correcta de los archivos de la aplicación.

Use TimeoutStopSec para configurar el período de tiempo que hay que esperar para que la aplicación se apague después de que reciba la señal de interrupción inicial. Si la aplicación no se apaga en este período, se emite SIGKILL para terminar la aplicación. Proporcione el valor como segundos sin unidad (por ejemplo, 150), un intervalo de tiempo (por ejemplo, 2min 30s) o infinity para deshabilitar el tiempo de expiración. El valor predeterminado de TimeoutStopSec es DefaultTimeoutStopSec en el archivo de configuración del administrador (systemd-system.conf, system.conf.d, systemd-user.conf y user.conf.d). El tiempo de expiración predeterminado para la mayoría de las distribuciones es de 90 segundos.

# The default value is 90 seconds for most distributions.
TimeoutStopSec=90

Linux tiene un sistema de archivos que distingue mayúsculas de minúsculas. Si se establece ASPNETCORE_ENVIRONMENT en Production, se busca en el archivo de configuración appsettings.Production.json, no en appsettings.production.json.

Algunos valores (por ejemplo, cadenas de conexión de SQL) deben ser de escape para que los proveedores de configuración lean las variables de entorno. Use el siguiente comando para generar un valor de escape correctamente para su uso en el archivo de configuración:

systemd-escape "<value-to-escape>"

No se admiten los separadores de dos puntos (:) en los nombres de variable de entorno. Use un subrayado doble (__) en lugar de dos puntos. El proveedor de configuración de variables de entorno convierte doble subrayado en dos puntos cuando las variables de entorno se leen en la configuración. En el ejemplo siguiente, la clave de la cadena de conexión ConnectionStrings:DefaultConnection se establece en el archivo de definición de servicio como ConnectionStrings__DefaultConnection:

Environment=ConnectionStrings__DefaultConnection={Connection String}

Guarde el archivo y habilite el servicio.

sudo systemctl enable kestrel-helloapp.service

Inicie el servicio y compruebe que se está ejecutando.

sudo systemctl start kestrel-helloapp.service
sudo systemctl status kestrel-helloapp.service

◝ kestrel-helloapp.service - Example .NET Web API App running on Linux
    Loaded: loaded (/etc/systemd/system/kestrel-helloapp.service; enabled)
    Active: active (running) since Thu 2016-10-18 04:09:35 NZDT; 35s ago
Main PID: 9021 (dotnet)
    CGroup: /system.slice/kestrel-helloapp.service
            └─9021 /usr/local/bin/dotnet /var/www/helloapp/helloapp.dll

Con el proxy inverso configurado y Kestrel administrado con systemd, la aplicación web está completamente configurada y se puede acceder a ella desde un explorador en la máquina local en http://localhost. También es accesible desde una máquina remota, salvo que haya algún firewall que la pueda estar bloqueando. Al inspeccionar los encabezados de respuesta, el encabezado Server muestra que Kestrel suministra la aplicación ASP.NET Core.

HTTP/1.1 200 OK
Date: Tue, 11 Oct 2016 16:22:23 GMT
Server: Kestrel
Keep-Alive: timeout=5, max=98
Connection: Keep-Alive
Transfer-Encoding: chunked

Ver registros

Dado que la aplicación web que usa Kestrel se administra mediante systemd, todos los procesos y eventos se registran en un diario centralizado. En cambio, este diario incluye todas las entradas de todos los servicios y procesos administrados por systemd. Para ver los elementos específicos de kestrel-helloapp.service, use el siguiente comando:

sudo journalctl -fu kestrel-helloapp.service

Para aumentar el filtrado, las opciones de tiempo como --since today y --until 1 hour ago, o bien una combinación de estas, pueden reducir el número de entradas que se devuelven.

sudo journalctl -fu kestrel-helloapp.service --since "2016-10-18" --until "2016-10-18 04:00"

Protección de datos

Hay varios softwares intermedios de ASP.NET Core que utilizan la pila de protección de datos de ASP.NET Core, incluidos los de autenticación, como el de cookies, y las protecciones de falsificación de solicitud entre sitios (CSRF). Aunque el código de usuario no llame a las API de protección de datos, esta se debe configurar para crear un almacén de claves criptográficas persistente. Si no se configura la protección de datos, las claves se conservan en memoria y se descartan cuando se reinicia la aplicación.

Si el conjunto de claves se almacena en memoria cuando se reinicia la aplicación:

  • Todos los tokens de autenticación basados en cookie se invalidan.
  • Los usuarios tienen que iniciar sesión de nuevo en la siguiente solicitud.
  • Ya no se pueden descifrar los datos protegidos con el conjunto de claves. Esto puede incluir tokens CSRF y cookies de TempData de ASP.NET Core MVC.

Para configurar la protección de datos de modo que sea persistente y permita cifrar el anillo de claves, consulte:

Campos del encabezado de solicitud más largos

La configuración predeterminada del servidor proxy normalmente limita los campos de encabezado de la solicitud a 4 K u 8 K, en función de la plataforma. Una aplicación puede requerir campos con una longitud mayor que la predeterminada (por ejemplo, las aplicaciones que usan Microsoft Entra ID). Si se requieren campos más largos, es necesario ajustar la configuración predeterminada del servidor proxy. Los valores que se aplican dependen del escenario. Para obtener más información, consulte la documentación del servidor.

Advertencia

No aumente los valores predeterminados de los búferes de proxy a menos que sea necesario. El aumento de estos valores incrementa el riesgo de saturación del búfer (desbordamiento) y ataques por denegación de servicio (DoS) realizados por usuarios malintencionados.

Protección de la nube

Habilitar AppArmor

Linux Security Modules (LSM) es una plataforma que forma parte del kernel de Linux desde Linux 2.6. LSM admite diferentes implementaciones de los módulos de seguridad. AppArmor es un LSM que implementa un sistema de control de acceso obligatorio que permite restringir el programa a un conjunto limitado de recursos. Asegúrese de que AppArmor está habilitado y configurado correctamente.

Configuración del firewall

Cierre todos los puertos externos que no se usen. Uncomplicated Firewall (ufw) proporciona un front-end para iptables al proporcionar una CLI para configurar el firewall.

Advertencia

Si tiene algún firewall activado y no está configurado correctamente, este impide el acceso a todo el sistema. Si usa SSH para establecer la conexión y no especifica el puerto SSH correcto, queda bloqueado y no podrá acceder al sistema. El puerto predeterminado es el 22. Para obtener más información, consulte la introducción a UFW y el manual.

Instale ufw y configúrelo para permitir el tráfico en los puertos que convenga.

sudo apt-get install ufw

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

sudo ufw enable

Protección de Nginx

Cambiar el nombre de la respuesta de Nginx

Edite src/http/ngx_http_header_filter_module.c:

static char ngx_http_server_string[] = "Server: Web Server" CRLF;
static char ngx_http_server_full_string[] = "Server: Web Server" CRLF;

Configurar opciones

Configure el servidor con más módulos que sean necesarios. Sopese la posibilidad de usar un firewall de aplicación web como ModSecurity para proteger la aplicación.

Configuración de HTTPS

Configuración de la aplicación para conexiones locales seguras (HTTPS)

El comando dotnet run usa el archivo Properties/launchSettings.json de la aplicación, que la configura para escuchar en las direcciones URL proporcionadas por la propiedad applicationUrl. Por ejemplo, https://localhost:5001;http://localhost:5000.

Configure la aplicación para que use un certificado en el desarrollo para el comando dotnet run o el entorno de desarrollo (F5 o Ctrl+F5 en Visual Studio Code) mediante uno de los siguientes enfoques:

Configure el proxy inverso para conexiones de cliente seguras (HTTPS)

Advertencia

La configuración de seguridad de esta sección es una configuración general que se usará como punto de partida para una personalización adicional. No podemos proporcionar soporte técnico para sistemas operativos, servidores y herramientas de terceros. Utilice la configuración en esta sección bajo su propia responsabilidad. Para obtener más información, vea los siguientes recursos:

  • Configure el servidor para que escuche el tráfico HTTPS en el puerto 443. Para ello, especifique un certificado válido emitido por una entidad de certificados (CA) de confianza.

  • Refuerce la seguridad con algunos de los procedimientos descritos en el siguiente archivo /etc/nginx/nginx.conf.

  • En el siguiente ejemplo no se configura el servidor para redirigir las solicitudes no seguras. Se recomienda usar el middleware de redireccionamiento de HTTPS. Para más información, vea Aplicación de HTTPS en ASP.NET Core.

    Nota

    En entornos de desarrollo en los que la configuración del servidor controla el redireccionamiento seguro en lugar del middleware de redireccionamiento de HTTPS, se recomienda usar redireccionamientos temporales (302) en lugar de permanentes (301). El almacenamiento en caché de vínculos puede producir un comportamiento inestable en los entornos de desarrollo.

  • El hecho de agregar un encabezado Strict-Transport-Security (HSTS) garantiza que todas las solicitudes sucesivas realizadas por el cliente sean a través de HTTPS. Para obtener instrucciones sobre cómo configurar el encabezado Strict-Transport-Security, vea Aplicación de HTTPS en ASP.NET Core.

  • Si HTTPS se va a deshabilitar en el futuro, use uno de los métodos siguientes:

    • No agregue el encabezado HSTS.
    • Elija un valor de max-age corto.

Agregue el archivo de configuración /etc/nginx/proxy.conf:

proxy_redirect          off;
proxy_set_header        Host $host;
proxy_set_header        X-Real-IP $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header        X-Forwarded-Proto $scheme;
client_max_body_size    10m;
client_body_buffer_size 128k;
proxy_connect_timeout   90;
proxy_send_timeout      90;
proxy_read_timeout      90;
proxy_buffers           32 4k;

Reemplace el contenido del archivo de configuración /etc/nginx/nginx.conf por el archivo siguiente. El ejemplo contiene las dos secciones http y server en un archivo de configuración.

http {
    include        /etc/nginx/proxy.conf;
    limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;
    server_tokens  off;

    sendfile on;
    # Adjust keepalive_timeout to the lowest possible value that makes sense 
    # for your use case.
    keepalive_timeout   29;
    client_body_timeout 10; client_header_timeout 10; send_timeout 10;

    upstream helloapp{
        server 127.0.0.1:5000;
    }

    server {
        listen                    443 ssl http2;
        listen                    [::]:443 ssl http2;
        server_name               example.com *.example.com;
        ssl_certificate           /etc/ssl/certs/testCert.crt;
        ssl_certificate_key       /etc/ssl/certs/testCert.key;
        ssl_session_timeout       1d;
        ssl_protocols             TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers off;
        ssl_ciphers               ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
        ssl_session_cache         shared:SSL:10m;
        ssl_session_tickets       off;
        ssl_stapling              off;

        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;

        #Redirects all traffic
        location / {
            proxy_pass http://helloapp;
            limit_req  zone=one burst=10 nodelay;
        }
    }
}

Nota

Las aplicaciones de Blazor WebAssembly requieren un valor de parámetro burst más grande para acomodar el mayor número de solicitudes hechas por una aplicación. Para más información, vea Hospedaje e implementación de ASP.NET Core Blazor WebAssembly.

Nota

El ejemplo anterior deshabilita el grapado del Protocolo de estado de certificados en línea (OCSP). Si está habilitado, confirme que el certificado sea compatible con la característica. Para obtener más información e instrucciones sobre cómo habilitar OCSP, vea las siguientes propiedades en el artículo Módulo ngx_http_ssl_module (documentación de Nginx):

  • ssl_stapling
  • ssl_stapling_file
  • ssl_stapling_responder
  • ssl_stapling_verify

Proteger Nginx frente al secuestro de clic

El secuestro de clic, también conocido como redireccionamiento de interfaz de usuario, es un ataque malintencionado donde al visitante de un sitio web se le engaña para que haga clic en un vínculo o botón de una página distinta de la que actualmente está visitando. Use X-FRAME-OPTIONS para proteger el sitio.

Para mitigar los ataques de secuestro de clic:

  1. Edite el archivo nginx.conf:

    sudo nano /etc/nginx/nginx.conf
    

    Dentro del bloque de código http{}, agregue la línea: add_header X-Frame-Options "SAMEORIGIN";.

  2. Guarde el archivo.

  3. Reinicie Nginx.

Examen de tipo MIME

Este encabezado evita que la mayoría de los exploradores examinen el MIME de una respuesta fuera del tipo de contenido declarado, ya que el encabezado indica al explorador que no reemplace el tipo de contenido de respuesta. Con la opción nosniff, si el servidor indica que el contenido es text/html, el explorador lo representa como text/html.

  1. Edite el archivo nginx.conf:

    sudo nano /etc/nginx/nginx.conf
    

    Dentro del bloque de código http{}, agregue la línea: add_header X-Content-Type-Options "nosniff";.

  2. Guarde el archivo.

  3. Reinicie Nginx.

Sugerencias de Nginx adicionales

Después de actualizar el marco de trabajo compartido en el servidor, reinicie las aplicaciones ASP.NET Core que hospeda el servidor.

Recursos adicionales

En esta guía se explica cómo configurar un entorno de ASP.NET Core listo para producción en un servidor de Ubuntu 16.04. Probablemente estas instrucciones sean válidas también con versiones más recientes de Ubuntu, pero no se han probado con versiones más recientes.

Para información sobre otras distribuciones de Linux compatibles con ASP.NET Core, consulte Requisitos previos para .NET Core en Linux.

Nota

En Ubuntu 14.04, supervisord es la solución recomendada para supervisar el proceso de Kestrel. systemd no está disponible en Ubuntu 14.04. Para obtener instrucciones de Ubuntu 14.04, vea la versión anterior de este tema.

En esta guía:

  • Se coloca una aplicación ASP.NET Core existente detrás de un servidor proxy inverso.
  • Se configura el servidor proxy inverso para reenviar las solicitudes al servidor web de Kestrel.
  • Se garantiza que la aplicación web se ejecute al inicio como un demonio.
  • Se configura una herramienta de administración de procesos para ayudar a reiniciar la aplicación web.

Requisitos previos

En cualquier momento futuro tras actualizar el marco de trabajo compartido, reinicie las aplicaciones ASP.NET Core que hospeda el servidor.

Publicar y copiar en la aplicación

Configure la aplicación para una implementación dependiente de Framework.

Si la aplicación se ejecuta localmente en el entorno de desarrollo y no está configurada para realizar conexiones HTTPS seguras, adopte cualquiera de los enfoques siguientes:

  • Configure la aplicación para controlar las conexiones locales seguras. Para obtener más información, vea la sección Configuración de HTTPS.

  • Configure la aplicación para que se ejecute en el punto de conexión no seguro:

    • Desactive el middleware de redireccionamiento HTTPS en el entorno de desarrollo (Program.cs):

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

      Para obtener más información, consulte Usar varios entornos en ASP.NET Core.

    • Quite https://localhost:5001 (si existe) de la propiedad applicationUrl en el archivo Properties/launchSettings.json.

Para más información sobre la configuración por entorno, vea Uso de varios entornos en ASP.NET Core.

Ejecute dotnet publish desde el entorno de desarrollo para empaquetar una aplicación en un directorio (por ejemplo, bin/Release/{TARGET FRAMEWORK MONIKER}/publish, donde el marcador de posición {TARGET FRAMEWORK MONIKER} es el moniker de la plataforma de destino, o TFM) que se pueda ejecutar en el servidor:

dotnet publish --configuration Release

La aplicación también se puede publicar como una implementación independiente si prefiere no mantener .NET Core Runtime en el servidor.

Copie la aplicación de ASP.NET Core en el servidor usando una herramienta que se integre en el flujo de trabajo de la organización (como SCP o SFTP). Es habitual encontrar las aplicaciones web en el directorio var (por ejemplo, var/www/helloapp).

Nota

En un escenario de implementación de producción, un flujo de trabajo de integración continua lleva a cabo la tarea de publicar la aplicación y copiar los recursos en el servidor.

Pruebe la aplicación:

  1. Desde la línea de comandos, ejecute la aplicación: dotnet <app_assembly>.dll.
  2. En un explorador, vaya a http://<serveraddress>:<port> para comprobar que la aplicación funciona en Linux de forma local.

Configurar un servidor proxy inverso

Un proxy inverso es una configuración común para trabajar con aplicaciones web dinámicas. Un proxy inverso finaliza la solicitud HTTP y la reenvía a la aplicación ASP.NET Core.

Usar un servidor proxy inverso

Kestrel resulta muy adecuado para suministrar contenido dinámico de ASP.NET Core. Sin embargo, las funcionalidades de servicio web no son tan completas como las de los servidores, como IIS, Apache o Nginx. Un servidor proxy inverso puede reducir las cargas de trabajo, por ejemplo, suministrar contenido estático, almacenar solicitudes en caché, comprimir solicitudes y finalizar HTTPS desde el servidor HTTP. Un servidor proxy inverso puede residir en un equipo dedicado o se puede implementar junto con un servidor HTTP.

Para los fines de esta guía, se usa una única instancia de Nginx. Se ejecuta en el mismo servidor, junto con el servidor HTTP. En función de requisitos, se puede elegir una configuración diferente.

Dado que el proxy inverso reenvía las solicitudes, use el middleware de encabezados reenviados del paquete Microsoft.AspNetCore.HttpOverrides. El middleware actualiza Request.Scheme, mediante el encabezado X-Forwarded-Proto, para que los URI de redireccionamiento y otras directivas de seguridad funcionen correctamente.

El middleware de encabezados reenviados debe ejecutarse antes de otro middleware. Hacerlo en ese orden garantiza que el middleware que se basa en la información de encabezados reenviados pueda usar los valores de encabezado para procesarlos. Para ejecutar el middleware de encabezados reenviados después del middleware de diagnóstico y control de errores, vea Orden del middleware de encabezados reenviados.

Invoque el método UseForwardedHeaders que está al principio de Program.cs antes de llamar a otro middleware. Configure el middleware para reenviar los encabezados X-Forwarded-For y X-Forwarded-Proto:

// requires using Microsoft.AspNetCore.HttpOverrides;
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

app.UseAuthentication();

Si no se especifica ningún valor ForwardedHeadersOptions para el middleware, los encabezados predeterminados para reenviar son None.

Los servidores proxy que se ejecutan en direcciones de bucle invertido (127.0.0.0/8 o [::1]), incluida la dirección de localhost (127.0.0.1) estándar, son de confianza de forma predeterminada. Si otras redes o servidores proxy de confianza de la organización tramitan solicitudes entre Internet y el servidor web, agréguelos a la lista de KnownProxies o KnownNetworks con ForwardedHeadersOptions. En el ejemplo siguiente se agrega un servidor proxy de confianza en la dirección IP 10.0.0.100 al middleware de encabezados reenviados KnownProxies en Program.cs:

using System.Net;

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});

Para obtener más información, consulte Configuración de ASP.NET Core para trabajar con servidores proxy y equilibradores de carga.

Instalar Nginx

Use apt-get para instalar Nginx. El instalador crea un script de inicio systemd que ejecuta Nginx como demonio al iniciarse el sistema. Siga las instrucciones de instalación para Ubuntu en Nginx: Official Debian/Ubuntu packages (Nginx: paquetes oficiales de Debian y Ubuntu).

Nota

Si se necesitan módulos de Nginx opcionales, puede que haya que compilar Nginx desde el origen.

Puesto que Nginx se ha instalado por primera vez, ejecute lo siguiente para iniciarlo de forma explícita:

sudo service nginx start

Compruebe que un explorador muestra la página de aterrizaje predeterminada de Nginx. La página de aterrizaje está accesible en http://<server_IP_address>/index.nginx-debian.html.

Configurar Nginx

Para configurar Nginx como un proxy inverso a fin de que reenvíe solicitudes HTTP a nuestra aplicación de ASP.NET Core, modifique /etc/nginx/sites-available/default. Ábralo en un editor de texto y reemplace el contenido por el fragmento de contenido siguiente:

server {
    listen        80;
    server_name   example.com *.example.com;
    location / {
        proxy_pass         http://127.0.0.1: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;
    }
}

Si la aplicación es una aplicación SignalR o Blazor Server, vea Hospedaje y escalado de producción de SignalR en ASP.NET Core y Hospedaje e implementación de aplicaciones de Blazor de ASP.NET Core del lado servidor, respectivamente, para más información.

Cuando no hay ninguna coincidencia de server_name, Nginx usa el servidor predeterminado. Si no se define ningún servidor predeterminado, el primer servidor del archivo de configuración es el servidor predeterminado. Como procedimiento recomendado, agregue un servidor predeterminado específico que devuelva un código de estado de 444 en el archivo de configuración. Un ejemplo de configuración del servidor predeterminado es:

server {
    listen   80 default_server;
    # listen [::]:80 default_server deferred;
    return   444;
}

Con el archivo de configuración anterior y el servidor predeterminado, Nginx acepta tráfico público en el puerto 80 con el encabezado de host example.com o *.example.com. Las solicitudes que no coincidan con estos hosts no se reenviarán al Kestrel. Nginx reenvía las solicitudes coincidentes con Kestrel a http://127.0.0.1:5000. Para obtener más información, vea este artículo sobre cómo Nginx procesa una solicitud. Para cambiar la IP o el puerto de Kestrel, consulte Kestrel: configuración de punto de conexión.

Advertencia

Si no se especifica una directiva de server_name adecuada, su aplicación se expone a vulnerabilidades de seguridad. Los enlaces de carácter comodín de subdominio (por ejemplo, *.example.com) no presentan este riesgo de seguridad si se controla todo el dominio primario (a diferencia de *.com, que sí es vulnerable). Para obtener más información, consulte RFC 9110: Semántica HTTP (Sección 7.2: Host y :authority).

Una vez establecida la configuración de Nginx, ejecute sudo nginx -t para comprobar la sintaxis de los archivos de configuración. Si la prueba del archivo de configuración es correcta, fuerce a Nginx a recopilar los cambios mediante la ejecución de sudo nginx -s reload.

Para ejecutar la aplicación directamente en el servidor:

  1. Vaya al directorio de la aplicación.
  2. Ejecute la aplicación: dotnet <app_assembly.dll>, donde app_assembly.dll es el nombre de archivo de ensamblado de la aplicación.

Si la aplicación se ejecuta en el servidor, pero no responde a través de Internet, compruebe el firewall del servidor y confirme que el puerto 80 está abierto. Si está usando una máquina virtual Ubuntu de Azure, agregue una regla de grupo de seguridad de red que posibilite el tráfico entrante del puerto 80. No es necesario para habilitar una regla de tráfico saliente en el puerto 80, ya que dicho tráfico se concede automáticamente al habilitar la regla de entrada.

Cuando termine de probar la aplicación, ciérrela con Ctrl+C (Windows) o +C (macOS) en el símbolo del sistema.

Supervisión de la aplicación

El servidor está configurado para reenviar las solicitudes realizadas a http://<serveraddress>:80 a la aplicación de ASP.NET Core que se ejecuta en Kestrel en http://127.0.0.1:5000. Sin embargo, Nginx no está configurado para administrar el proceso de Kestrel. Se puede usar systemd para crear un archivo de servicio para iniciar y supervisar la aplicación web subyacente. systemd es un sistema de inicio que proporciona muchas características eficaces para iniciar, detener y administrar procesos.

Crear el archivo de servicio

Cree el archivo de definición de servicio:

sudo nano /etc/systemd/system/kestrel-helloapp.service

El ejemplo siguiente es un archivo de servicio para la aplicación:

[Unit]
Description=Example .NET Web API App running on Ubuntu

[Service]
WorkingDirectory=/var/www/helloapp
ExecStart=/usr/bin/dotnet /var/www/helloapp/helloapp.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_NOLOGO=true

[Install]
WantedBy=multi-user.target

En el ejemplo anterior, el usuario que administra el servicio se especifica mediante la opción User. El usuario (www-data) debe existir y tener la propiedad correcta de los archivos de la aplicación.

Use TimeoutStopSec para configurar el período de tiempo que hay que esperar para que la aplicación se apague después de que reciba la señal de interrupción inicial. Si la aplicación no se apaga en este período, se emite SIGKILL para terminar la aplicación. Proporcione el valor como segundos sin unidad (por ejemplo, 150), un intervalo de tiempo (por ejemplo, 2min 30s) o infinity para deshabilitar el tiempo de expiración. El valor predeterminado de TimeoutStopSec es DefaultTimeoutStopSec en el archivo de configuración del administrador (systemd-system.conf, system.conf.d, systemd-user.conf y user.conf.d). El tiempo de expiración predeterminado para la mayoría de las distribuciones es de 90 segundos.

# The default value is 90 seconds for most distributions.
TimeoutStopSec=90

Linux tiene un sistema de archivos que distingue mayúsculas de minúsculas. Si se establece ASPNETCORE_ENVIRONMENT en Production, se busca en el archivo de configuración appsettings.Production.json, no en appsettings.production.json.

Algunos valores (por ejemplo, cadenas de conexión de SQL) deben ser de escape para que los proveedores de configuración lean las variables de entorno. Use el siguiente comando para generar un valor de escape correctamente para su uso en el archivo de configuración:

systemd-escape "<value-to-escape>"

No se admiten los separadores de dos puntos (:) en los nombres de variable de entorno. Use un subrayado doble (__) en lugar de dos puntos. El proveedor de configuración de variables de entorno convierte doble subrayado en dos puntos cuando las variables de entorno se leen en la configuración. En el ejemplo siguiente, la clave de la cadena de conexión ConnectionStrings:DefaultConnection se establece en el archivo de definición de servicio como ConnectionStrings__DefaultConnection:

Environment=ConnectionStrings__DefaultConnection={Connection String}

Guarde el archivo y habilite el servicio.

sudo systemctl enable kestrel-helloapp.service

Inicie el servicio y compruebe que se está ejecutando.

sudo systemctl start kestrel-helloapp.service
sudo systemctl status kestrel-helloapp.service

◝ kestrel-helloapp.service - Example .NET Web API App running on Ubuntu
    Loaded: loaded (/etc/systemd/system/kestrel-helloapp.service; enabled)
    Active: active (running) since Thu 2016-10-18 04:09:35 NZDT; 35s ago
Main PID: 9021 (dotnet)
    CGroup: /system.slice/kestrel-helloapp.service
            └─9021 /usr/local/bin/dotnet /var/www/helloapp/helloapp.dll

Con el proxy inverso configurado y Kestrel administrado con systemd, la aplicación web está completamente configurada y se puede acceder a ella desde un explorador en la máquina local en http://localhost. También es accesible desde una máquina remota, salvo que haya algún firewall que la pueda estar bloqueando. Al inspeccionar los encabezados de respuesta, el encabezado Server muestra que Kestrel suministra la aplicación ASP.NET Core.

HTTP/1.1 200 OK
Date: Tue, 11 Oct 2016 16:22:23 GMT
Server: Kestrel
Keep-Alive: timeout=5, max=98
Connection: Keep-Alive
Transfer-Encoding: chunked

Ver registros

Dado que la aplicación web que usa Kestrel se administra mediante systemd, todos los procesos y eventos se registran en un diario centralizado. En cambio, este diario incluye todas las entradas de todos los servicios y procesos administrados por systemd. Para ver los elementos específicos de kestrel-helloapp.service, use el siguiente comando:

sudo journalctl -fu kestrel-helloapp.service

Para aumentar el filtrado, las opciones de tiempo como --since today y --until 1 hour ago, o bien una combinación de estas, pueden reducir el número de entradas que se devuelven.

sudo journalctl -fu kestrel-helloapp.service --since "2016-10-18" --until "2016-10-18 04:00"

Protección de datos

Hay varios softwares intermedios de ASP.NET Core que utilizan la pila de protección de datos de ASP.NET Core, incluidos los de autenticación, como el de cookies, y las protecciones de falsificación de solicitud entre sitios (CSRF). Aunque el código de usuario no llame a las API de protección de datos, esta se debe configurar para crear un almacén de claves criptográficas persistente. Si no se configura la protección de datos, las claves se conservan en memoria y se descartan cuando se reinicia la aplicación.

Si el conjunto de claves se almacena en memoria cuando se reinicia la aplicación:

  • Todos los tokens de autenticación basados en cookie se invalidan.
  • Los usuarios tienen que iniciar sesión de nuevo en la siguiente solicitud.
  • Ya no se pueden descifrar los datos protegidos con el conjunto de claves. Esto puede incluir tokens CSRF y cookies de TempData de ASP.NET Core MVC.

Para configurar la protección de datos de modo que sea persistente y permita cifrar el anillo de claves, consulte:

Campos del encabezado de solicitud más largos

La configuración predeterminada del servidor proxy normalmente limita los campos de encabezado de la solicitud a 4 K u 8 K, en función de la plataforma. Una aplicación puede requerir campos con una longitud mayor que la predeterminada (por ejemplo, las aplicaciones que usan Azure Active Directory). Si se requieren campos más largos, es necesario ajustar la configuración predeterminada del servidor proxy. Los valores que se aplican dependen del escenario. Para obtener más información, consulte la documentación del servidor.

Advertencia

No aumente los valores predeterminados de los búferes de proxy a menos que sea necesario. El aumento de estos valores incrementa el riesgo de saturación del búfer (desbordamiento) y ataques por denegación de servicio (DoS) realizados por usuarios malintencionados.

Protección de la nube

Habilitar AppArmor

Linux Security Modules (LSM) es una plataforma que forma parte del kernel de Linux desde Linux 2.6. LSM admite diferentes implementaciones de los módulos de seguridad. AppArmor es un LSM que implementa un sistema de control de acceso obligatorio que permite restringir el programa a un conjunto limitado de recursos. Asegúrese de que AppArmor está habilitado y configurado correctamente.

Configuración del firewall

Cierre todos los puertos externos que no se usen. Uncomplicated Firewall (ufw) proporciona un front-end para iptables al proporcionar una CLI para configurar el firewall.

Advertencia

Si tiene algún firewall activado y no está configurado correctamente, este impedirá el acceso a todo el sistema. Si usa SSH para establecer la conexión y no especifica el puerto SSH correcto, quedará bloqueado y no podrá acceder al sistema. El puerto predeterminado es el 22. Para obtener más información, consulte la introducción a UFW y el manual.

Instale ufw y configúrelo para permitir el tráfico en los puertos que convenga.

sudo apt-get install ufw

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

sudo ufw enable

Protección de Nginx

Cambiar el nombre de la respuesta de Nginx

Edite src/http/ngx_http_header_filter_module.c:

static char ngx_http_server_string[] = "Server: Web Server" CRLF;
static char ngx_http_server_full_string[] = "Server: Web Server" CRLF;

Configurar opciones

Configure el servidor con más módulos que sean necesarios. Sopese la posibilidad de usar un firewall de aplicación web como ModSecurity para proteger la aplicación.

Configuración de HTTPS

Configuración de la aplicación para conexiones locales seguras (HTTPS)

El comando dotnet run usa el archivo Properties/launchSettings.json de la aplicación, que la configura para escuchar en las direcciones URL proporcionadas por la propiedad applicationUrl. Por ejemplo, https://localhost:5001;http://localhost:5000.

Configure la aplicación para que use un certificado en el desarrollo para el comando dotnet run o el entorno de desarrollo (F5 o Ctrl+F5 en Visual Studio Code) mediante uno de los siguientes enfoques:

Configure el proxy inverso para conexiones de cliente seguras (HTTPS)

Advertencia

La configuración de seguridad de esta sección es una configuración general que se usará como punto de partida para una personalización adicional. No podemos proporcionar soporte técnico para sistemas operativos, servidores y herramientas de terceros. Utilice la configuración en esta sección bajo su propia responsabilidad. Para obtener más información, vea los siguientes recursos:

  • Configure el servidor para que escuche el tráfico HTTPS en el puerto 443. Para ello, especifique un certificado válido emitido por una entidad de certificados (CA) de confianza.

  • Refuerce la seguridad con algunos de los procedimientos descritos en el siguiente archivo /etc/nginx/nginx.conf.

  • En el siguiente ejemplo no se configura el servidor para redirigir las solicitudes no seguras. Se recomienda usar el middleware de redireccionamiento de HTTPS. Para más información, vea Aplicación de HTTPS en ASP.NET Core.

    Nota

    En entornos de desarrollo en los que la configuración del servidor controla el redireccionamiento seguro en lugar del middleware de redireccionamiento de HTTPS, se recomienda usar redireccionamientos temporales (302) en lugar de permanentes (301). El almacenamiento en caché de vínculos puede producir un comportamiento inestable en los entornos de desarrollo.

  • El hecho de agregar un encabezado Strict-Transport-Security (HSTS) garantiza que todas las solicitudes sucesivas realizadas por el cliente sean a través de HTTPS. Para obtener instrucciones sobre cómo configurar el encabezado Strict-Transport-Security, vea Aplicación de HTTPS en ASP.NET Core.

  • Si HTTPS se va a deshabilitar en el futuro, use uno de los métodos siguientes:

    • No agregue el encabezado HSTS.
    • Elija un valor de max-age corto.

Agregue el archivo de configuración /etc/nginx/proxy.conf:

proxy_redirect          off;
proxy_set_header        Host $host;
proxy_set_header        X-Real-IP $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header        X-Forwarded-Proto $scheme;
client_max_body_size    10m;
client_body_buffer_size 128k;
proxy_connect_timeout   90;
proxy_send_timeout      90;
proxy_read_timeout      90;
proxy_buffers           32 4k;

Reemplace el contenido del archivo de configuración /etc/nginx/nginx.conf por el archivo siguiente. El ejemplo contiene las dos secciones http y server en un archivo de configuración.

http {
    include        /etc/nginx/proxy.conf;
    limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;
    server_tokens  off;

    sendfile on;
    # Adjust keepalive_timeout to the lowest possible value that makes sense 
    # for your use case.
    keepalive_timeout   29;
    client_body_timeout 10; client_header_timeout 10; send_timeout 10;

    upstream helloapp{
        server 127.0.0.1:5000;
    }

    server {
        listen                    443 ssl http2;
        listen                    [::]:443 ssl http2;
        server_name               example.com *.example.com;
        ssl_certificate           /etc/ssl/certs/testCert.crt;
        ssl_certificate_key       /etc/ssl/certs/testCert.key;
        ssl_session_timeout       1d;
        ssl_protocols             TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers off;
        ssl_ciphers               ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
        ssl_session_cache         shared:SSL:10m;
        ssl_session_tickets       off;
        ssl_stapling              off;

        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;

        #Redirects all traffic
        location / {
            proxy_pass http://helloapp;
            limit_req  zone=one burst=10 nodelay;
        }
    }
}

Nota

Las aplicaciones de Blazor WebAssembly requieren un valor de parámetro burst más grande para acomodar el mayor número de solicitudes hechas por una aplicación. Para más información, vea Hospedaje e implementación de ASP.NET Core Blazor WebAssembly.

Nota

El ejemplo anterior deshabilita el grapado del Protocolo de estado de certificados en línea (OCSP). Si está habilitado, confirme que el certificado sea compatible con la característica. Para obtener más información e instrucciones sobre cómo habilitar OCSP, vea las siguientes propiedades en el artículo Módulo ngx_http_ssl_module (documentación de Nginx):

  • ssl_stapling
  • ssl_stapling_file
  • ssl_stapling_responder
  • ssl_stapling_verify

Proteger Nginx frente al secuestro de clic

El secuestro de clic, también conocido como redireccionamiento de interfaz de usuario, es un ataque malintencionado donde al visitante de un sitio web se le engaña para que haga clic en un vínculo o botón de una página distinta de la que actualmente está visitando. Use X-FRAME-OPTIONS para proteger el sitio.

Para mitigar los ataques de secuestro de clic:

  1. Edite el archivo nginx.conf:

    sudo nano /etc/nginx/nginx.conf
    

    Agregue la línea add_header X-Frame-Options "SAMEORIGIN";.

  2. Guarde el archivo.

  3. Reinicie Nginx.

Examen de tipo MIME

Este encabezado evita que la mayoría de los exploradores examinen el MIME de una respuesta fuera del tipo de contenido declarado, ya que el encabezado indica al explorador que no reemplace el tipo de contenido de respuesta. Con la opción nosniff, si el servidor indica que el contenido es text/html, el explorador lo representa como text/html.

  1. Edite el archivo nginx.conf:

    sudo nano /etc/nginx/nginx.conf
    

    Agregue la línea add_header X-Content-Type-Options "nosniff";.

  2. Guarde el archivo.

  3. Reinicie Nginx.

Sugerencias de Nginx adicionales

Después de actualizar el marco de trabajo compartido en el servidor, reinicie las aplicaciones ASP.NET Core que hospeda el servidor.

Recursos adicionales

En esta guía se explica cómo configurar un entorno de ASP.NET Core listo para producción en un servidor de Ubuntu 16.04. Probablemente estas instrucciones sean válidas también con versiones más recientes de Ubuntu, pero no se han probado con versiones más recientes.

Para información sobre otras distribuciones de Linux compatibles con ASP.NET Core, consulte Requisitos previos para .NET Core en Linux.

Nota

En Ubuntu 14.04, supervisord es la solución recomendada para supervisar el proceso de Kestrel. systemd no está disponible en Ubuntu 14.04. Para obtener instrucciones de Ubuntu 14.04, vea la versión anterior de este tema.

En esta guía:

  • Se coloca una aplicación ASP.NET Core existente detrás de un servidor proxy inverso.
  • Se configura el servidor proxy inverso para reenviar las solicitudes al servidor web de Kestrel.
  • Se garantiza que la aplicación web se ejecute al inicio como un demonio.
  • Se configura una herramienta de administración de procesos para ayudar a reiniciar la aplicación web.

Requisitos previos

En cualquier momento futuro tras actualizar el marco de trabajo compartido, reinicie las aplicaciones ASP.NET Core que hospeda el servidor.

Publicar y copiar en la aplicación

Configure la aplicación para una implementación dependiente de Framework.

Si la aplicación se ejecuta localmente en el entorno de desarrollo y no está configurada para realizar conexiones HTTPS seguras, adopte cualquiera de los enfoques siguientes:

  • Configure la aplicación para controlar las conexiones locales seguras. Para obtener más información, vea la sección Configuración de HTTPS.

  • Configure la aplicación para que se ejecute en el punto de conexión no seguro:

    • Desactive el middleware de redireccionamiento HTTPS en el entorno de desarrollo (Program.cs):

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

      Para obtener más información, consulte Usar varios entornos en ASP.NET Core.

    • Quite https://localhost:5001 (si existe) de la propiedad applicationUrl en el archivo Properties/launchSettings.json.

Para más información sobre la configuración por entorno, vea Uso de varios entornos en ASP.NET Core.

Ejecute dotnet publish desde el entorno de desarrollo para empaquetar una aplicación en un directorio (por ejemplo, bin/Release/{TARGET FRAMEWORK MONIKER}/publish, donde el marcador de posición {TARGET FRAMEWORK MONIKER} es el moniker de la plataforma de destino, o TFM) que se pueda ejecutar en el servidor:

dotnet publish --configuration Release

La aplicación también se puede publicar como una implementación independiente si prefiere no mantener .NET Core Runtime en el servidor.

Copie la aplicación de ASP.NET Core en el servidor usando una herramienta que se integre en el flujo de trabajo de la organización (como SCP o SFTP). Es habitual encontrar las aplicaciones web en el directorio var (por ejemplo, var/www/helloapp).

Nota

En un escenario de implementación de producción, un flujo de trabajo de integración continua lleva a cabo la tarea de publicar la aplicación y copiar los recursos en el servidor.

Pruebe la aplicación:

  1. Desde la línea de comandos, ejecute la aplicación: dotnet <app_assembly>.dll.
  2. En un explorador, vaya a http://<serveraddress>:<port> para comprobar que la aplicación funciona en Linux de forma local.

Configurar un servidor proxy inverso

Un proxy inverso es una configuración común para trabajar con aplicaciones web dinámicas. Un proxy inverso finaliza la solicitud HTTP y la reenvía a la aplicación ASP.NET Core.

Usar un servidor proxy inverso

Kestrel resulta muy adecuado para suministrar contenido dinámico de ASP.NET Core. Sin embargo, las funcionalidades de servicio web no son tan completas como las de los servidores, como IIS, Apache o Nginx. Un servidor proxy inverso puede reducir las cargas de trabajo, por ejemplo, suministrar contenido estático, almacenar solicitudes en caché, comprimir solicitudes y finalizar HTTPS desde el servidor HTTP. Un servidor proxy inverso puede residir en un equipo dedicado o se puede implementar junto con un servidor HTTP.

Para los fines de esta guía, se usa una única instancia de Nginx. Se ejecuta en el mismo servidor, junto con el servidor HTTP. En función de requisitos, se puede elegir una configuración diferente.

Dado que el proxy inverso reenvía las solicitudes, use el middleware de encabezados reenviados del paquete Microsoft.AspNetCore.HttpOverrides. El middleware actualiza Request.Scheme, mediante el encabezado X-Forwarded-Proto, para que los URI de redireccionamiento y otras directivas de seguridad funcionen correctamente.

El middleware de encabezados reenviados debe ejecutarse antes de otro middleware. Hacerlo en ese orden garantiza que el middleware que se basa en la información de encabezados reenviados pueda usar los valores de encabezado para procesarlos. Para ejecutar el middleware de encabezados reenviados después del middleware de diagnóstico y control de errores, vea Orden del middleware de encabezados reenviados.

Invoque el método UseForwardedHeaders que está al principio de Startup.Configure antes de llamar a otro middleware. Configure el middleware para reenviar los encabezados X-Forwarded-For y X-Forwarded-Proto:

using Microsoft.AspNetCore.HttpOverrides;

...

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

app.UseAuthentication();

Si no se especifica ningún valor ForwardedHeadersOptions para el middleware, los encabezados predeterminados para reenviar son None.

Los servidores proxy que se ejecutan en direcciones de bucle invertido (127.0.0.0/8 o [::1]), incluida la dirección de localhost (127.0.0.1) estándar, son de confianza de forma predeterminada. Si otras redes o servidores proxy de confianza de la organización tramitan solicitudes entre Internet y el servidor web, agréguelos a la lista de KnownProxies o KnownNetworks con ForwardedHeadersOptions. En el ejemplo siguiente se agrega un servidor proxy de confianza en la dirección IP 10.0.0.100 al middleware de encabezados reenviados KnownProxies en Startup.ConfigureServices:

using System.Net;

...

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});

Para obtener más información, consulte Configuración de ASP.NET Core para trabajar con servidores proxy y equilibradores de carga.

Instalar Nginx

Use apt-get para instalar Nginx. El instalador crea un script de inicio systemd que ejecuta Nginx como demonio al iniciarse el sistema. Siga las instrucciones de instalación para Ubuntu en Nginx: Official Debian/Ubuntu packages (Nginx: paquetes oficiales de Debian y Ubuntu).

Nota

Si se necesitan módulos de Nginx opcionales, puede que haya que compilar Nginx desde el origen.

Puesto que Nginx se ha instalado por primera vez, ejecute lo siguiente para iniciarlo de forma explícita:

sudo service nginx start

Compruebe que un explorador muestra la página de aterrizaje predeterminada de Nginx. La página de aterrizaje está accesible en http://<server_IP_address>/index.nginx-debian.html.

Configurar Nginx

Para configurar Nginx como un proxy inverso a fin de que reenvíe solicitudes HTTP a nuestra aplicación de ASP.NET Core, modifique /etc/nginx/sites-available/default. Ábralo en un editor de texto y reemplace el contenido por el fragmento de contenido siguiente:

server {
    listen        80;
    server_name   example.com *.example.com;
    location / {
        proxy_pass         http://127.0.0.1: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;
    }
}

Si la aplicación es una aplicación SignalR o Blazor Server, vea Hospedaje y escalado de producción de SignalR en ASP.NET Core y Hospedaje e implementación de aplicaciones de Blazor de ASP.NET Core del lado servidor, respectivamente, para más información.

Cuando no hay ninguna coincidencia de server_name, Nginx usa el servidor predeterminado. Si no se define ningún servidor predeterminado, el primer servidor del archivo de configuración es el servidor predeterminado. Como procedimiento recomendado, agregue un servidor predeterminado específico que devuelva un código de estado de 444 en el archivo de configuración. Un ejemplo de configuración del servidor predeterminado es:

server {
    listen   80 default_server;
    # listen [::]:80 default_server deferred;
    return   444;
}

Con el archivo de configuración anterior y el servidor predeterminado, Nginx acepta tráfico público en el puerto 80 con el encabezado de host example.com o *.example.com. Las solicitudes que no coincidan con estos hosts no se reenviarán al Kestrel. Nginx reenvía las solicitudes coincidentes con Kestrel a http://127.0.0.1:5000. Para obtener más información, vea este artículo sobre cómo Nginx procesa una solicitud. Para cambiar la IP o el puerto de Kestrel, consulte Kestrel: configuración de punto de conexión.

Advertencia

Si no se especifica una directiva de server_name adecuada, su aplicación se expone a vulnerabilidades de seguridad. Los enlaces de carácter comodín de subdominio (por ejemplo, *.example.com) no presentan este riesgo de seguridad si se controla todo el dominio primario (a diferencia de *.com, que sí es vulnerable). Para obtener más información, consulte RFC 9110: Semántica HTTP (Sección 7.2: Host y :authority).

Una vez establecida la configuración de Nginx, ejecute sudo nginx -t para comprobar la sintaxis de los archivos de configuración. Si la prueba del archivo de configuración es correcta, fuerce a Nginx a recopilar los cambios mediante la ejecución de sudo nginx -s reload.

Para ejecutar la aplicación directamente en el servidor:

  1. Vaya al directorio de la aplicación.
  2. Ejecute la aplicación: dotnet <app_assembly.dll>, donde app_assembly.dll es el nombre de archivo de ensamblado de la aplicación.

Si la aplicación se ejecuta en el servidor, pero no responde a través de Internet, compruebe el firewall del servidor y confirme que el puerto 80 está abierto. Si está usando una máquina virtual Ubuntu de Azure, agregue una regla de grupo de seguridad de red que posibilite el tráfico entrante del puerto 80. No es necesario para habilitar una regla de tráfico saliente en el puerto 80, ya que dicho tráfico se concede automáticamente al habilitar la regla de entrada.

Cuando termine de probar la aplicación, ciérrela con Ctrl+C (Windows) o +C (macOS) en el símbolo del sistema.

Supervisión de la aplicación

El servidor está configurado para reenviar las solicitudes realizadas a http://<serveraddress>:80 a la aplicación de ASP.NET Core que se ejecuta en Kestrel en http://127.0.0.1:5000. Sin embargo, Nginx no está configurado para administrar el proceso de Kestrel. Se puede usar systemd para crear un archivo de servicio para iniciar y supervisar la aplicación web subyacente. systemd es un sistema de inicio que proporciona muchas características eficaces para iniciar, detener y administrar procesos.

Crear el archivo de servicio

Cree el archivo de definición de servicio:

sudo nano /etc/systemd/system/kestrel-helloapp.service

El ejemplo siguiente es un archivo de servicio para la aplicación:

[Unit]
Description=Example .NET Web API App running on Ubuntu

[Service]
WorkingDirectory=/var/www/helloapp
ExecStart=/usr/bin/dotnet /var/www/helloapp/helloapp.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

En el ejemplo anterior, el usuario que administra el servicio se especifica mediante la opción User. El usuario (www-data) debe existir y tener la propiedad correcta de los archivos de la aplicación.

Use TimeoutStopSec para configurar el período de tiempo que hay que esperar para que la aplicación se apague después de que reciba la señal de interrupción inicial. Si la aplicación no se apaga en este período, se emite SIGKILL para terminar la aplicación. Proporcione el valor como segundos sin unidad (por ejemplo, 150), un intervalo de tiempo (por ejemplo, 2min 30s) o infinity para deshabilitar el tiempo de expiración. El valor predeterminado de TimeoutStopSec es DefaultTimeoutStopSec en el archivo de configuración del administrador (systemd-system.conf, system.conf.d, systemd-user.conf y user.conf.d). El tiempo de expiración predeterminado para la mayoría de las distribuciones es de 90 segundos.

# The default value is 90 seconds for most distributions.
TimeoutStopSec=90

Linux tiene un sistema de archivos que distingue mayúsculas de minúsculas. Si se establece ASPNETCORE_ENVIRONMENT en Production, se busca en el archivo de configuración appsettings.Production.json, no en appsettings.production.json.

Algunos valores (por ejemplo, cadenas de conexión de SQL) deben ser de escape para que los proveedores de configuración lean las variables de entorno. Use el siguiente comando para generar un valor de escape correctamente para su uso en el archivo de configuración:

systemd-escape "<value-to-escape>"

No se admiten los separadores de dos puntos (:) en los nombres de variable de entorno. Use un subrayado doble (__) en lugar de dos puntos. El proveedor de configuración de variables de entorno convierte doble subrayado en dos puntos cuando las variables de entorno se leen en la configuración. En el ejemplo siguiente, la clave de la cadena de conexión ConnectionStrings:DefaultConnection se establece en el archivo de definición de servicio como ConnectionStrings__DefaultConnection:

Environment=ConnectionStrings__DefaultConnection={Connection String}

Guarde el archivo y habilite el servicio.

sudo systemctl enable kestrel-helloapp.service

Inicie el servicio y compruebe que se está ejecutando.

sudo systemctl start kestrel-helloapp.service
sudo systemctl status kestrel-helloapp.service

◝ kestrel-helloapp.service - Example .NET Web API App running on Ubuntu
    Loaded: loaded (/etc/systemd/system/kestrel-helloapp.service; enabled)
    Active: active (running) since Thu 2016-10-18 04:09:35 NZDT; 35s ago
Main PID: 9021 (dotnet)
    CGroup: /system.slice/kestrel-helloapp.service
            └─9021 /usr/local/bin/dotnet /var/www/helloapp/helloapp.dll

Con el proxy inverso configurado y Kestrel administrado con systemd, la aplicación web está completamente configurada y se puede acceder a ella desde un explorador en la máquina local en http://localhost. También es accesible desde una máquina remota, salvo que haya algún firewall que la pueda estar bloqueando. Al inspeccionar los encabezados de respuesta, el encabezado Server muestra que Kestrel suministra la aplicación ASP.NET Core.

HTTP/1.1 200 OK
Date: Tue, 11 Oct 2016 16:22:23 GMT
Server: Kestrel
Keep-Alive: timeout=5, max=98
Connection: Keep-Alive
Transfer-Encoding: chunked

Ver registros

Dado que la aplicación web que usa Kestrel se administra mediante systemd, todos los procesos y eventos se registran en un diario centralizado. En cambio, este diario incluye todas las entradas de todos los servicios y procesos administrados por systemd. Para ver los elementos específicos de kestrel-helloapp.service, use el siguiente comando:

sudo journalctl -fu kestrel-helloapp.service

Para aumentar el filtrado, las opciones de tiempo como --since today y --until 1 hour ago, o bien una combinación de estas, pueden reducir el número de entradas que se devuelven.

sudo journalctl -fu kestrel-helloapp.service --since "2016-10-18" --until "2016-10-18 04:00"

Protección de datos

Hay varios softwares intermedios de ASP.NET Core que utilizan la pila de protección de datos de ASP.NET Core, incluidos los de autenticación, como el de cookies, y las protecciones de falsificación de solicitud entre sitios (CSRF). Aunque el código de usuario no llame a las API de protección de datos, esta se debe configurar para crear un almacén de claves criptográficas persistente. Si no se configura la protección de datos, las claves se conservan en memoria y se descartan cuando se reinicia la aplicación.

Si el conjunto de claves se almacena en memoria cuando se reinicia la aplicación:

  • Todos los tokens de autenticación basados en cookie se invalidan.
  • Los usuarios tienen que iniciar sesión de nuevo en la siguiente solicitud.
  • Ya no se pueden descifrar los datos protegidos con el conjunto de claves. Esto puede incluir tokens CSRF y cookies de TempData de ASP.NET Core MVC.

Para configurar la protección de datos de modo que sea persistente y permita cifrar el anillo de claves, consulte:

Campos del encabezado de solicitud más largos

La configuración predeterminada del servidor proxy normalmente limita los campos de encabezado de la solicitud a 4 K u 8 K, en función de la plataforma. Una aplicación puede requerir campos con una longitud mayor que la predeterminada (por ejemplo, las aplicaciones que usan Azure Active Directory). Si se requieren campos más largos, es necesario ajustar la configuración predeterminada del servidor proxy. Los valores que se aplican dependen del escenario. Para obtener más información, consulte la documentación del servidor.

Advertencia

No aumente los valores predeterminados de los búferes de proxy a menos que sea necesario. El aumento de estos valores incrementa el riesgo de saturación del búfer (desbordamiento) y ataques por denegación de servicio (DoS) realizados por usuarios malintencionados.

Protección de la nube

Habilitar AppArmor

Linux Security Modules (LSM) es una plataforma que forma parte del kernel de Linux desde Linux 2.6. LSM admite diferentes implementaciones de los módulos de seguridad. AppArmor es un LSM que implementa un sistema de control de acceso obligatorio que permite restringir el programa a un conjunto limitado de recursos. Asegúrese de que AppArmor está habilitado y configurado correctamente.

Configuración del firewall

Cierre todos los puertos externos que no se usen. Uncomplicated Firewall (ufw) proporciona un front-end para iptables al proporcionar una CLI para configurar el firewall.

Advertencia

Si tiene algún firewall activado y no está configurado correctamente, este impedirá el acceso a todo el sistema. Si usa SSH para establecer la conexión y no especifica el puerto SSH correcto, quedará bloqueado y no podrá acceder al sistema. El puerto predeterminado es el 22. Para obtener más información, consulte la introducción a UFW y el manual.

Instale ufw y configúrelo para permitir el tráfico en los puertos que convenga.

sudo apt-get install ufw

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

sudo ufw enable

Protección de Nginx

Cambiar el nombre de la respuesta de Nginx

Edite src/http/ngx_http_header_filter_module.c:

static char ngx_http_server_string[] = "Server: Web Server" CRLF;
static char ngx_http_server_full_string[] = "Server: Web Server" CRLF;

Configurar opciones

Configure el servidor con más módulos que sean necesarios. Sopese la posibilidad de usar un firewall de aplicación web como ModSecurity para proteger la aplicación.

Configuración de HTTPS

Configuración de la aplicación para conexiones locales seguras (HTTPS)

El comando dotnet run usa el archivo Properties/launchSettings.json de la aplicación, que la configura para escuchar en las direcciones URL proporcionadas por la propiedad applicationUrl. Por ejemplo, https://localhost:5001;http://localhost:5000.

Configure la aplicación para que use un certificado en el desarrollo para el comando dotnet run o el entorno de desarrollo (F5 o Ctrl+F5 en Visual Studio Code) mediante uno de los siguientes enfoques:

Configure el proxy inverso para conexiones de cliente seguras (HTTPS)

Advertencia

La configuración de seguridad de esta sección es una configuración general que se usará como punto de partida para una personalización adicional. No podemos proporcionar soporte técnico para sistemas operativos, servidores y herramientas de terceros. Utilice la configuración en esta sección bajo su propia responsabilidad. Para obtener más información, vea los siguientes recursos:

  • Configure el servidor para que escuche el tráfico HTTPS en el puerto 443. Para ello, especifique un certificado válido emitido por una entidad de certificados (CA) de confianza.

  • Refuerce la seguridad con algunos de los procedimientos descritos en el siguiente archivo /etc/nginx/nginx.conf.

  • En el siguiente ejemplo no se configura el servidor para redirigir las solicitudes no seguras. Se recomienda usar el middleware de redireccionamiento de HTTPS. Para más información, vea Aplicación de HTTPS en ASP.NET Core.

    Nota

    En entornos de desarrollo en los que la configuración del servidor controla el redireccionamiento seguro en lugar del middleware de redireccionamiento de HTTPS, se recomienda usar redireccionamientos temporales (302) en lugar de permanentes (301). El almacenamiento en caché de vínculos puede producir un comportamiento inestable en los entornos de desarrollo.

  • El hecho de agregar un encabezado Strict-Transport-Security (HSTS) garantiza que todas las solicitudes sucesivas realizadas por el cliente sean a través de HTTPS. Para obtener instrucciones sobre cómo configurar el encabezado Strict-Transport-Security, vea Aplicación de HTTPS en ASP.NET Core.

  • Si HTTPS se va a deshabilitar en el futuro, use uno de los métodos siguientes:

    • No agregue el encabezado HSTS.
    • Elija un valor de max-age corto.

Agregue el archivo de configuración /etc/nginx/proxy.conf:

proxy_redirect          off;
proxy_set_header        Host $host;
proxy_set_header        X-Real-IP $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header        X-Forwarded-Proto $scheme;
client_max_body_size    10m;
client_body_buffer_size 128k;
proxy_connect_timeout   90;
proxy_send_timeout      90;
proxy_read_timeout      90;
proxy_buffers           32 4k;

Reemplace el contenido del archivo de configuración /etc/nginx/nginx.conf por el archivo siguiente. El ejemplo contiene las dos secciones http y server en un archivo de configuración.

http {
    include        /etc/nginx/proxy.conf;
    limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;
    server_tokens  off;

    sendfile on;
    # Adjust keepalive_timeout to the lowest possible value that makes sense 
    # for your use case.
    keepalive_timeout   29;
    client_body_timeout 10; client_header_timeout 10; send_timeout 10;

    upstream helloapp{
        server 127.0.0.1:5000;
    }

    server {
        listen                    443 ssl http2;
        listen                    [::]:443 ssl http2;
        server_name               example.com *.example.com;
        ssl_certificate           /etc/ssl/certs/testCert.crt;
        ssl_certificate_key       /etc/ssl/certs/testCert.key;
        ssl_session_timeout       1d;
        ssl_protocols             TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers off;
        ssl_ciphers               ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
        ssl_session_cache         shared:SSL:10m;
        ssl_session_tickets       off;
        ssl_stapling              off;

        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;

        #Redirects all traffic
        location / {
            proxy_pass http://helloapp;
            limit_req  zone=one burst=10 nodelay;
        }
    }
}

Nota

Las aplicaciones de Blazor WebAssembly requieren un valor de parámetro burst más grande para acomodar el mayor número de solicitudes hechas por una aplicación. Para más información, vea Hospedaje e implementación de ASP.NET Core Blazor WebAssembly.

Nota

El ejemplo anterior deshabilita el grapado del Protocolo de estado de certificados en línea (OCSP). Si está habilitado, confirme que el certificado sea compatible con la característica. Para obtener más información e instrucciones sobre cómo habilitar OCSP, vea las siguientes propiedades en el artículo Módulo ngx_http_ssl_module (documentación de Nginx):

  • ssl_stapling
  • ssl_stapling_file
  • ssl_stapling_responder
  • ssl_stapling_verify

Proteger Nginx frente al secuestro de clic

El secuestro de clic, también conocido como redireccionamiento de interfaz de usuario, es un ataque malintencionado donde al visitante de un sitio web se le engaña para que haga clic en un vínculo o botón de una página distinta de la que actualmente está visitando. Use X-FRAME-OPTIONS para proteger el sitio.

Para mitigar los ataques de secuestro de clic:

  1. Edite el archivo nginx.conf:

    sudo nano /etc/nginx/nginx.conf
    

    Agregue la línea add_header X-Frame-Options "SAMEORIGIN";.

  2. Guarde el archivo.

  3. Reinicie Nginx.

Examen de tipo MIME

Este encabezado evita que la mayoría de los exploradores examinen el MIME de una respuesta fuera del tipo de contenido declarado, ya que el encabezado indica al explorador que no reemplace el tipo de contenido de respuesta. Con la opción nosniff, si el servidor indica que el contenido es text/html, el explorador lo representa como text/html.

  1. Edite el archivo nginx.conf:

    sudo nano /etc/nginx/nginx.conf
    

    Agregue la línea add_header X-Content-Type-Options "nosniff";.

  2. Guarde el archivo.

  3. Reinicie Nginx.

Sugerencias de Nginx adicionales

Después de actualizar el marco de trabajo compartido en el servidor, reinicie las aplicaciones ASP.NET Core que hospeda el servidor.

Recursos adicionales