Cómo activar HTTP/2 en Nginx

La versión 2 del protocolo de Transferencia de Hipertexto comenzó a ser una realidad hace ya cuatro años, cuando oficialmente se envió el borrador del protocolo a la IETF (Grupo de Trabajo de Ingeniería de Internet). A partir de ese momento surgía la tan esperada actualización del protocolo HTTP/1.1 en la World Wide Web, estándar que lleva con nosotros desde el siglo pasado (1999).

Podríamos hablar mucho sobre este protocolo, pero os diré que a grandes rasgos su objetivo es reducir la latencia y mejorar la carga de páginas web, algo que es una realidad porque está comprobado que permite porcentajes de carga un 60% mejores en HTTP y 55% en HTTPS respecto a HTTP/1.1. Todo ello gracias a que se establece una única conexión, lo que permite servir múltiples solicitudes/respuestas en paralelo. ¿Qué significa esto? Se pueden procesar en paralelo todas las peticiones de objetos CSS, HTML, JavaScript, imágenes, vídeos, audio en una única conexión en lugar de una a una con varias conexiones… ¡multiplexación!

Además, se elimina información redundante del protocolo, compresión de las cabeceras para reducir la información transmitida, prioridad de flujos, servicio ‘server push’ (también conocido como cache push, que da la posibilidad al servidor de enviar información al usuario antes de que la pida, así la procesa de forma inmediata cuando lo requiere), etc.

¿Cómo podemos habilitar HTTP/2 en Nginx?

Pues no puede ser más sencillo. Se activa a nivel de bloque server y únicamente hay que añadir la propiedad «http2» en el listener correspondiente. A continuación tenéis un ejemplo de un listener HTTPS de nginx con HTTP/2 activo:

server {
[...]
    listen 443 ssl http2; 
[...]
}

De esta forma, los navegadores o clientes que soporten HTTP/2 usarán este protocolo, en caso contrario seguirán conectando con HTTP/1.1 sin ningún problema.

En versiones actuales precompiladas el módulo ya viene cargado por defecto, así que no es necesario instalar nada extra, lo podéis comprobar lanzando un nginx -V:

# nginx -V
nginx version: nginx/1.14.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx
--modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf
--error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log
--pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock 
--http-client-body-temp-path=/var/cache/nginx/client_temp
--http-proxy-temp-path=/var/cache/nginx/proxy_temp
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp 
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp
--http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx
--group=nginx --with-compat --with-file-aio --with-threads
--with-http_addition_module --with-http_auth_request_module
--with-http_dav_module --with-http_flv_module --with-http_gunzip_module
--with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module
--with-http_realip_module --with-http_secure_link_module
--with-http_slice_module --with-http_ssl_module --with-http_stub_status_module
--with-http_v2_module --with-mail
--with-mail_ssl_module --with-stream --with-stream_realip_module
--with-stream_ssl_module --with-stream_ssl_preread_module
--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2
-fexceptions -fstack-protector-strong --param=ssp-buffer-size=4

Como podéis observar, he puesto en negrita la evidencia en la salida del comando anterior, así que si vosotros habéis instalado Nginx compilando a mano, esa sería la opción de compilación que activaría HTTP/2: --with-http_v2_module.

Para afinar algo más la configuración, echad un vistazo a las directivas disponibles en la documentación oficial de Nginx.

¿Cómo verificar que HTTP/2 funciona?

Tras reiniciar Nginx, podéis verificar con cUrl que está activo correctamente:

# curl -sI https://rm-rf.es -o/dev/null -w '%{http_version}\n'
2

Si devuelve un 2 es que está utilizando el nuevo protocolo, en caso contrario devolverá 1.1:

# curl -sI https://rm-rf.es -o/dev/null -w '%{http_version}\n'
1.1

Con las herramientas de desarrollo del navegador también podéis verlo, simplemente consultad las cabeceras HTTP en la sección «Network» (Firefox):

Web Developer Firefox HTTP Network Headers

A partir de aquí, el siguiente paso es optimizar tanto el rendimiento como la seguridad tanto del protocolo como de toda la parte de SSL/TLS. Lo veremos en otro artículo de forma más detenida.