<!-- review: finished -->

<a id="ssl-config"></a>

# Configuración SSL

Para configurar un servidor HTTPS, el parámetro [ssl](https://es.angie.software//angie/docs/configuration/modules/http/index.md#listen) debe estar habilitado en los sockets de escucha dentro del bloque [server](https://es.angie.software//angie/docs/configuration/modules/http/index.md#server), y se deben especificar las ubicaciones de los archivos del certificado del servidor y de la clave privada:

```nginx
server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
#...
}
```

El certificado del servidor es una entidad pública. Se envía a cada cliente que se conecta al servidor. La clave privada es una entidad segura y debe almacenarse en un archivo con acceso restringido; sin embargo, debe ser legible por el proceso maestro de Angie. La clave privada también puede almacenarse en el mismo archivo que el certificado.

```nginx
ssl_certificate     www.example.com.cert;
ssl_certificate_key www.example.com.cert;
```

En ese caso, los derechos de acceso al archivo también deben estar restringidos. Aunque el certificado y la clave se almacenan en un único archivo, solo se envía el certificado al cliente.

Las directivas [ssl_protocols](https://es.angie.software//angie/docs/configuration/modules/http/http_ssl.md#ssl-protocols) y [ssl_ciphers](https://es.angie.software//angie/docs/configuration/modules/http/http_ssl.md#ssl-ciphers) pueden usarse para limitar las conexiones e incluir únicamente las versiones y cifrados fuertes de SSL/TLS. Por defecto, Angie utiliza:

```nginx
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
```

Por lo tanto, configurarlas explícitamente generalmente no es necesario.

<a id="https-optimization"></a>

## Optimización del Servidor HTTPS

Las operaciones SSL consumen recursos adicionales de CPU. En sistemas multiprocesador, se deben ejecutar varios [procesos de trabajo](https://es.angie.software//angie/docs/configuration/modules/core.md#worker-processes), no menos de la cantidad de núcleos de CPU disponibles. La operación más intensiva en CPU es el handshake SSL. Hay dos formas de minimizar el número de estas operaciones por cliente: la primera es habilitando conexiones [keepalive](https://es.angie.software//angie/docs/configuration/modules/http/index.md#keepalive-timeout) para enviar varias solicitudes a través de una única conexión, y la segunda es reutilizar los parámetros de sesión SSL para evitar handshakes SSL en conexiones paralelas y subsiguientes. Las sesiones se almacenan en una caché de sesiones SSL compartida entre los trabajadores y configurada por la directiva [ssl_session_cache](https://es.angie.software//angie/docs/configuration/modules/http/http_ssl.md#ssl-session-cache). Un megabyte de la caché contiene aproximadamente 4000 sesiones. El tiempo de espera predeterminado de la caché es de 5 minutos. Puede aumentarse utilizando la directiva [ssl_session_timeout](https://es.angie.software//angie/docs/configuration/modules/http/http_ssl.md#ssl-session-timeout). Aquí hay una configuración de ejemplo optimizada para un sistema multinúcleo con una caché de sesiones compartida de 10 megabytes:

```nginx
worker_processes auto;

http {
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    server {
        listen              443 ssl;
        server_name         www.example.com;
        keepalive_timeout   70;

        ssl_certificate     www.example.com.crt;
        ssl_certificate_key www.example.com.key;
        ssl_protocols       TLSv1.2 TLSv1.3;
        ssl_ciphers         HIGH:!aNULL:!MD5;
    #...
```

<a id="certificate-chaining"></a>

## Cadenas de Certificados SSL

Algunos navegadores pueden quejarse de un certificado firmado por una autoridad certificadora reconocida, mientras que otros navegadores pueden aceptar el certificado sin problemas. Esto ocurre porque la autoridad emisora ha firmado el certificado del servidor utilizando un certificado intermedio que no está presente en la base de certificados de autoridades certificadoras de confianza reconocidas distribuida con un navegador particular. En este caso, la autoridad proporciona un conjunto de certificados encadenados que deben concatenarse al certificado firmado del servidor. El certificado del servidor debe aparecer antes que los certificados encadenados en el archivo combinado:

```console
$ cat www.example.com.crt bundle.crt > www.example.com.chained.crt
```

El archivo resultante debe utilizarse con la directiva [ssl_certificate](https://es.angie.software//angie/docs/configuration/modules/http/http_ssl.md#ssl-certificate):

```nginx
server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.chained.crt;
    ssl_certificate_key www.example.com.key;
#...
}
```

Si el certificado del servidor y el conjunto se concatenaron en el orden incorrecto, Angie no se inicia y muestra un mensaje de error:

> SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed
> : (SSL: error:0B080074:x509 certificate routines:
>   X509_check_private_key:key values mismatch)

Esto ocurre porque Angie intentó usar la clave privada con el primer certificado del conjunto en lugar del certificado del servidor.

Los navegadores generalmente almacenan certificados intermedios que reciben, firmados por autoridades de confianza, por lo que los navegadores que se utilizan habitualmente pueden ya tener los certificados intermedios requeridos y no quejarse de un certificado enviado sin un conjunto encadenado. Para asegurar que el servidor envía la cadena de certificados completa, se puede utilizar la utilidad de línea de comandos **openssl**, por ejemplo:

```console
$ openssl s_client -connect www.godaddy.com:443

Certificate chain
 0 s:/C=US/ST=Arizona/L=Scottsdale/1.3.6.1.4.1.311.60.2.1.3=US
     /1.3.6.1.4.1.311.60.2.1.2=AZ/O=GoDaddy.com, Inc
     /OU=MIS Department/CN=www.GoDaddy.com
     /serialNumber=0796928-7/2.5.4.15=V1.0, Clause 5.(b)
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
     /OU=http://certificates.godaddy.com/repository
     /CN=Go Daddy Secure Certification Authority
     /serialNumber=07969287
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
     /OU=http://certificates.godaddy.com/repository
     /CN=Go Daddy Secure Certification Authority
     /serialNumber=07969287
   i:/C=US/O=The Go Daddy Group, Inc.
     /OU=Go Daddy Class 2 Certification Authority
 2 s:/C=US/O=The Go Daddy Group, Inc.
     /OU=Go Daddy Class 2 Certification Authority
   i:/L=ValiCert Validation Network/O=ValiCert, Inc.
     /OU=ValiCert Class 2 Policy Validation Authority
     /CN=http://www.valicert.com//emailAddress=info@valicert.com
```

En este ejemplo, el sujeto ("s") del certificado del servidor www.GoDaddy.com #0 está firmado por un emisor ("i") que a su vez es el sujeto del certificado #1, que está firmado por un emisor que a su vez es el sujeto del certificado #2, que está firmado por el emisor conocido ValiCert, Inc. cuyo certificado está almacenado en la base de certificados integrada de los navegadores.

Si no se ha añadido un conjunto de certificados, solo se mostrará el certificado del servidor #0.

<a id="compact-server"></a>

## Un Único Servidor HTTP/HTTPS

Es posible configurar un único servidor que maneje tanto peticiones HTTP como HTTPS:

```nginx
server {
    listen              80;
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
#...
}
```

<a id="name-based-https-servers"></a>

## Servidores HTTPS Basados en Nombres

Un problema común surge al configurar dos o más servidores HTTPS escuchando en una única dirección IP:

```nginx
server {
    listen          443 ssl;
    server_name     www.example.com;
    ssl_certificate www.example.com.crt;
#...
}

server {
    listen          443 ssl;
    server_name     www.example.org;
    ssl_certificate www.example.org.crt;
#...
}
```

Con esta configuración, un navegador recibe el certificado del servidor predeterminado, es decir, www.example.com, independientemente del nombre de servidor solicitado. Esto es causado por el comportamiento del protocolo SSL. La conexión SSL se establece antes de que el navegador envíe una solicitud HTTP, y Angie no conoce el nombre del servidor solicitado. Por lo tanto, solo puede ofrecer el certificado del servidor predeterminado.

<a id="https-separate-ips"></a>

El método más antiguo y robusto para resolver el problema es asignar una dirección IP separada para cada servidor HTTPS:

```nginx
server {
    listen          192.168.1.1:443 ssl;
    server_name     www.example.com;
    ssl_certificate www.example.com.crt;
#...
}

server {
    listen          192.168.1.2:443 ssl;
    server_name     www.example.org;
    ssl_certificate www.example.org.crt;
#...
}
```

<a id="an-ssl-certificate-with-multiple-names"></a>

## Un Certificado SSL con Múltiples Nombres

Existen otras formas que permiten compartir una única dirección IP entre varios servidores HTTPS. Sin embargo, todas ellas tienen sus inconvenientes. Una forma es usar un certificado con varios nombres en el campo `SubjectAltName` del certificado, por ejemplo, `www.example.com` y `www.example.org`. Sin embargo, la longitud del campo `SubjectAltName` es limitada.

Otra forma es usar un certificado con un nombre comodín, por ejemplo, `*.example.org`. Un certificado comodín protege todos los subdominios del dominio especificado, pero solo en un nivel. Este certificado coincide con `www.example.org` pero no coincide con `example.org` ni con `www.sub.example.org`. Estos dos métodos también se pueden combinar. Un certificado puede contener nombres exactos y comodín en el campo `SubjectAltName`, por ejemplo, `example.org` y `*.example.org`.

Es mejor colocar un archivo de certificado con varios nombres y su archivo de clave privada en el nivel de configuración `http` para heredar una única copia en memoria en todos los servidores:

```nginx
ssl_certificate     common.crt;
ssl_certificate_key common.key;

server {
    listen          443 ssl;
    server_name     www.example.com;
#...
}

server {
    listen          443 ssl;
    server_name     www.example.org;
#...
}
```

<a id="sni"></a>

## Indicación de Nombre de Servidor

Una solución más genérica para ejecutar varios servidores HTTPS en una única dirección IP es la extensión TLS Server Name Indication (SNI, [RFC 6066](https://datatracker.ietf.org/doc/html/rfc6066.html)), que permite a un navegador pasar el nombre del servidor solicitado durante el handshake SSL, y por lo tanto, el servidor sabrá qué certificado debe usar para la conexión. SNI es actualmente compatible con la mayoría de los navegadores modernos, aunque puede no ser utilizado por algunos clientes antiguos o especiales.

Si Angie fue compilado con soporte para SNI, entonces Angie mostrará esto al ejecutarse con el interruptor `-V`:

```console
$ angie -V
...
TLS SNI support enabled
...
```

Sin embargo, si Angie habilitado para SNI está vinculado dinámicamente a una biblioteca OpenSSL sin soporte para SNI, Angie mostrará una advertencia:

> Angie fue compilado con soporte para SNI, sin embargo, ahora está vinculado
> dinámicamente a una biblioteca OpenSSL que no tiene soporte para tlsext,
> por lo tanto SNI no está disponible
