GNU/Linux >> Tutoriales Linux >  >> Debian

Ejecute Apache, Nginx y HAProxy en el mismo servidor (Debian, Ubuntu, CentOS)

Si es administrador de un servidor, probablemente tenga un servidor web de su elección, como Apache o Nginx. Apache es un servidor web muy conocido desde la década de 1990. Nginx se desarrolló por primera vez en 2004 y ganó terreno rápidamente debido a su uso ligero de memoria y su rápida velocidad de procesamiento para archivos HTML estáticos.

Tanto Apache como Nginx admiten alojamiento virtual, lo que significa que puede alojar varios sitios web o aplicaciones web en el mismo servidor. Sin embargo, encontrará situaciones en las que tiene un servidor web existente en ejecución, pero una aplicación web en particular requiere el uso de un servidor web diferente. El puerto 80 o 443 en la dirección IP pública solo puede ser utilizado por un proceso. Si Apache está usando el puerto, entonces Nginx no puede usarlo (ni vincularse a él). Entonces, ¿qué puedes hacer?

Puede configurar Nginx como un proxy inverso para Apache, de modo que Nginx pueda redirigir las solicitudes HTTP a Apache. En mi experiencia, descubrí que esta no siempre es la mejor manera porque una vez causó problemas extraños que no puedo solucionar. En su lugar, prefiero usar HAProxy como proxy inverso para Nginx y Apache . HAProxy es un servidor proxy y equilibrador de carga gratuito de código abierto y alta disponibilidad para aplicaciones basadas en TCP y HTTP.

Ejecute Apache, Nginx y HAProxy en el mismo servidor

Así es como funciona.

  • Nginx escucha en 127.0.0.1:80 y 127.0.0.1:443
  • Apache escucha en 127.0.0.2:80 y 127.0.0.2:443
  • HAProxy escucha en los puertos 80 y 443 de la dirección IP pública. Redirige la solicitud HTTP en el puerto 80 al puerto 443. Cuando llega una solicitud al puerto 443, elegirá entre Nginx y Apache analizando el encabezado SNI (indicación del nombre del servidor) en la solicitud HTTPS.

En realidad, Cloudflare (un proveedor de CDN) también usa el encabezado SNI para determinar cómo enrutar las solicitudes HTTPS a los servidores de origen.

Paso 1:detener Nginx y Apache

Para detener Nginx en Debian, Ubuntu y CentOS, ejecute

sudo systemctl stop nginx

Para detener Apache en Debian/Ubuntu, ejecute

sudo systemctl stop apache2

Para detener Apache en CentOS, ejecute

sudo systemctl stop httpd

Paso 2:cambiar el puerto de escucha en Nginx

Necesitamos hacer que Nginx escuche en 127.0.0.1:80. Abra sus archivos de configuración de Nginx en /etc/nginx/conf.d/ o /etc/nginx/sites-enabled/ y busque la siguiente línea.

listen 80;

Cámbialo a

listen 127.0.0.1:80;

Si https está habilitado en el bloque del servidor Nginx, busque también

listen 443 ssl;

Y cambiarlo a

listen 127.0.0.1:443 ssl;

El archivo de configuración principal de Nginx /etc/nginx/nginx.conf podría incluir un host virtual predeterminado escuchando en el puerto 80 o 443, por lo que es posible que también deba editar este archivo.

Reinicie Nginx para que los cambios surtan efecto.

sudo systemctl restart nginx

Paso 3:cambie el puerto de escucha en Apache

Necesitamos hacer que Apache escuche en 127.0.0.2:80.

Debian/Ubuntu

En Debian y Ubuntu, edite el /etc/apache2/ports.conf archivo.

sudo nano /etc/apache2/ports.conf

Cambiar

Listen 80
Listen 443

Para

Listen 127.0.0.2:80
Listen 127.0.0.2:443

Guarde y cierre el archivo. Vaya también a /etc/apache2/sites-enabled/ directorio, edite los archivos del host virtual. Cambiar

<VirtualHost *:80>

Para

<VirtualHost 127.0.0.2:80>

Si hay host virtual SSL, entonces también cambie

<VirtualHost *:443>

Para

<VirtualHost 127.0.0.2:443>

Reinicie Apache.

sudo systemctl restart apache2

Cent OS

En CentOS, edite el /etc/httpd/conf/httpd.conf archivo.

sudo nano /etc/httpd/conf/httpd.conf

Buscar

Listen 80

Cámbialo a

Listen 127.0.0.2:80

Guarde y cierre el archivo. Luego vaya a /etc/httpd/conf.d/ directorio, edite los archivos del host virtual. Cambiar

<VirtualHost *:80>

Para

<VirtualHost 127.0.0.2:80>

Si hay host virtual SSL, entonces también cambie

<VirtualHost *:443>

Para

<VirtualHost 127.0.0.2:443>

En el /etc/httpd/conf.d/ssl.conf archivo, hay

Listen 443 https

Cámbialo por:

Listen 127.0.0.2:443 https

Guarde y cierre el archivo. Reinicie Apache para que los cambios surtan efecto.

sudo systemctl restart httpd

Paso 4:Configurar HAProxy

Instale HAProxy en su distribución.

Debian/Ubuntu

sudo apt install haproxy

CentOS

sudo dnf install haproxy

Edite el archivo de configuración de HAProxy.

sudo nano /etc/haproxy/haproxy.cfg

Agregue el siguiente fragmento de código al final del archivo, lo que hará que HAPorxy escuche en el puerto 80 de la dirección IP pública y redirija las solicitudes HTTP en el puerto 80 al puerto 443. Reemplace 12.34.56.78 con la dirección IP pública de su servidor.

frontend http
    bind 12.34.56.78:80
    mode http
    redirect scheme https code 301

Ahora también necesitamos agregar un front-end HTTPS.

frontend https
    bind 12.34.56.78:443
    mode tcp
    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }

Luego defina los back-ends de Nginx y Apache. El check El parámetro le dice a HAProxy que realice controles de salud en el back-end enviando un paquete TCP.

backend nginx
    mode tcp
    option ssl-hello-chk
    server nginx 127.0.0.1:443 check

backend apache
    mode tcp
    option ssl-hello-chk
    server apache 127.0.0.2:443 check

Puede definir un back-end predeterminado con:

default_backend nginx

Usaremos el encabezado SNI en la solicitud HTTPS para redirigir al back-end correcto. Por ejemplo, si Nginx está sirviendo domain1.com y Apache está sirviendo domain2.com , luego agrega las siguientes dos líneas. También puede utilizar subdominios, siempre que sean diferentes.

use_backend nginx if { req_ssl_sni -i domain1.com }
use_backend apache if { req_ssl_sni -i domain2.com }

Tenga en cuenta que el default_backend y use_backend las directivas deben colocarse sobre las definiciones de back-end.

frontend http
    bind 12.34.56.78:80
    mode http
    redirect scheme https code 301

frontend https
    bind 12.34.56.78:443
    mode tcp
    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }

    default_backend nginx

    use_backend nginx if { req_ssl_sni -i domain1.com }
    use_backend apache if { req_ssl_sni -i domain2.com }

backend nginx
    mode tcp
    option ssl-hello-chk
    server nginx 127.0.0.1:443 check

backend apache
    mode tcp
    option ssl-hello-chk
    server apache 127.0.0.2:443 check

En la configuración anterior, utilizamos la función SNI (Indicación de nombre de servidor) en TLS para diferenciar el tráfico HTTPS.

  • Cuando domain1.com está en TLS Client Hello, HAProxy redirige el tráfico a nginx backend.
  • Cuando domain2.com está en TLS Client Hello, HAProxy redirige el tráfico a apache backend.

Si el cliente no especifica el nombre del servidor en TLS Client Hello, HAproxy utilizará el backend predeterminado (nginx).

Guarde y cierre el archivo. Luego reinicie HAproxy.

sudo systemctl restart haproxy

Ahora Apache, Nginx y HAProxy pueden ejecutarse en el mismo servidor.

Cómo reenviar la dirección IP del cliente al backend

De forma predeterminada, Apache y Nginx solo pueden ver la dirección IP de HAProxy. Para obtener la dirección IP real del cliente, asegúrese de agregar send-proxy-v2 opción en la definición de back-end de HAProxy como se muestra a continuación.

backend nginx
    mode tcp
    option ssl-hello-chk
    server nginx 127.0.0.1:443 send-proxy-v2 check

backend apache
    mode tcp
    option ssl-hello-chk
    server apache 127.0.0.2:443 send-proxy-v2 check

También necesitamos agregar alguna configuración en Nginx y Apache para que funcione; de ​​lo contrario, no se podrá acceder a su sitio web.

Nginx

Agregar proxy_protocol en Nginx listen directiva como a continuación.

listen 127.0.0.2:443 ssl http2 proxy_protocol;

Luego agregue las siguientes dos directivas en Nginx http { } bloque en /etc/nginx/nginx.conf archivo.

set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;

Guarde y cierre el archivo. Luego recarga Nginx.

sudo systemctl reload nginx

Nota :si su sitio web se ejecuta detrás de Cloudflare CDN, debe cambiar real_ip_header proxy_protocol; a real_ip_header CF-Connecting-IP; para mostrar la dirección IP real del cliente. También puede agregar este real_ip_header directiva al archivo de bloque del servidor individual para anular la configuración global en /etc/nginx/nginx.conf archivo.

Finalmente, reinicie HAProxy.

sudo systemctl restart haproxy

Apache

Si usa Apache en Debian/Ubuntu, debe habilitar remoteip módulo. (Este módulo está habilitado en CentOS de forma predeterminada).

sudo a2enmod remoteip

Luego agregue las siguientes 3 líneas en su archivo de configuración de host virtual de Apache.

RemoteIPProxyProtocol On
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 127.0.0.1

Así.

<VirtualHost 127.0.0.2:443>
    ServerName www.example.com
    RemoteIPProxyProtocol On
    RemoteIPHeader X-Forwarded-For
    RemoteIPTrustedProxy 127.0.0.1

Guarde y cierre el archivo. Entonces también necesitamos cambiar el combined formato de registro. Edite el archivo de configuración principal de Apache.

sudo nano /etc/apache2/apache2.conf

o

sudo nano /etc/httpd/conf/httpd.conf

Busque la siguiente línea.

LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

Reemplázalo con:

LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

Guarde y cierre el archivo. Luego reinicie Apache para que los cambios surtan efecto.

sudo systemctl restart apache2

o

sudo systemctl restart httpd

Nota que el RemoteIPProxyProtocol On La directiva solo está disponible en Apache 2.4.31 y posteriores. Para verificar su versión de Apache, ejecute

sudo apache2 -v

o

sudo httpd -v

Ubuntu 18.04 se envía con Apache 2.4.29. Si su versión de Apache no cumple con este requisito, debe eliminar send-proxy-v2 en la definición de back-end de HAProxy. CentOS 8 viene con Apache 2.4.37.

Finalmente, reinicie HAProxy.

sudo systemctl restart haproxy

Cómo agregar nuevos servidores virtuales

Si tiene servidores web Apache y Nginx, solo necesita dos backends:uno para Apache y otro para Nginx.

Cuando necesite agregar otro dominio (o subdominio), no necesita agregar un nuevo backend en HAProxy. En su lugar, debe crear un nuevo host virtual para el nuevo dominio (o subdominio) en Apache o Nginx, luego use el use_backend directiva en HAProxy para redirigir el tráfico al backend correcto.

frontend http
    bind 12.34.56.78:80
    mode http
    redirect scheme https code 301

frontend https
    bind 12.34.56.78:443
    mode tcp
    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }

    default_backend nginx

    use_backend nginx if { req_ssl_sni -i domain1.com }
    use_backend nginx if { req_ssl_sni -i sub.domain1.com }
    use_backend apache if { req_ssl_sni -i domain2.com }
    use_backend apache if { req_ssl_sni -i sub.domain2.com }

backend nginx
    mode tcp
    option ssl-hello-chk
    server nginx 127.0.0.1:443 check

backend apache
    mode tcp
    option ssl-hello-chk
    server apache 127.0.0.2:443 check

Recomiendo usar apache y nginx como los nombres de back-end como en el código anterior, para que sepa qué servidor web aloja qué aplicación.

Obtención del nuevo certificado SSL de Let's Encrypt

desafío http-01

Primero, debe comprender cómo usar el autenticador Certbot apache y nginx para obtener el certificado TLS.

  • Habilite correctamente HTTPS en Apache con Let's Encrypt en Ubuntu
  • Habilite correctamente HTTPS en Nginx con Let's Encrypt en Ubuntu

El autenticador Certbot apache y nginx usa http-01 desafío, que funciona en el puerto TCP 80. Debido a que HAProxy está usando el puerto TCP 80, Certbot http-01 es probable que el desafío fracase. Sin embargo, puede hacer que funcione con el siguiente método.

  1. Habilite el host SSL en Apache o Nginx con un certificado autofirmado o un certificado para otro dominio.
  2. Luego, use el autenticador Certbot apache y nginx como de costumbre.

Este método funciona porque el Certbot http-01 el desafío se puede redirigir desde el puerto TCP 80 al puerto TCP 443, y Certbot acepta certificados no válidos en el puerto 443.

desafío dns-01

También puede usar el certbot dns-01 desafío, que funciona mediante la creación de un registro TXT temporal para su dominio para certificar que realmente posee este dominio, por lo que puede omitir el puerto TCP 80 y el puerto TCP 443. La desventaja de este método es que no todos los registradores de dominio son compatibles.

Primero, debe instalar el complemento DNS de Certbot. Son varios complementos de DNS disponibles en el repositorio de software de Debian y Ubuntu, que puede encontrar con

apt search python3-certbot-dns

Salida:

python3-certbot-dns-cloudflare/bionic,bionic 0.23.0-1 all
Cloudflare DNS plugin for Certbot

python3-certbot-dns-digitalocean/bionic,bionic 0.23.0-1 all
DigitalOcean DNS plugin for Certbot

python3-certbot-dns-dnsimple/bionic,bionic 0.23.0-1 all
DNSimple DNS plugin for Certbot

python3-certbot-dns-google/bionic,bionic 0.23.0-1 all
Google DNS plugin for Certbot

python3-certbot-dns-rfc2136/bionic,bionic 0.23.0-1 all
RFC 2136 DNS plugin for Certbot

python3-certbot-dns-route53/bionic,bionic 0.23.0-1 all
Route53 DNS plugin for Certbot

En CentOS 8, puede encontrar complementos de DNS de Certbot en el repositorio de EPEL. Tenga en cuenta que debe instalar Certbot desde el repositorio predeterminado de CentOS.

sudo dnf install certbot

Encuentre complementos de DNS en el repositorio de EPEL.

sudo dnf install epel-release
dnf search certbot-dns

Salida:

python3-certbot-dns-ovh.noarch : OVH DNS Authenticator plugin for Certbot
python3-certbot-dns-nsone.noarch : NS1 DNS Authenticator plugin for Certbot
python3-certbot-dns-gehirn.noarch : Gehirn Infrastructure Service DNS Authenticator plugin for Certbot
python3-certbot-dns-google.noarch : Google Cloud DNS Authenticator plugin for Certbot
python3-certbot-dns-linode.noarch : Linode DNS Authenticator plugin for Certbot
python3-certbot-dns-luadns.noarch : LuaDNS Authenticator plugin for Certbot
python3-certbot-dns-rfc2136.noarch : RFC 2136 DNS Authenticator plugin for Certbot
python3-certbot-dns-route53.noarch : Route53 DNS Authenticator plugin for Certbot
python3-certbot-dns-cloudxns.noarch : CloudXNS DNS Authenticator plugin for Certbot
python3-certbot-dns-dnsimple.noarch : DNSimple DNS Authenticator plugin for Certbot
python3-certbot-dns-cloudflare.noarch : Cloudflare DNS Authenticator plugin for Certbot
python3-certbot-dns-cloudflare.noarch : Cloudflare DNS Authenticator plugin for Certbot
python3-certbot-dns-dnsmadeeasy.noarch : DNS Made Easy DNS Authenticator plugin for Certbot
python3-certbot-dns-sakuracloud.noarch : Sakura Cloud DNS Authenticator plugin for Certbot

Instale uno de estos complementos según el servicio de alojamiento de DNS que esté utilizando. Estoy usando Cloudflare, así que usaré Cloudflare como ejemplo. Ejecute el siguiente comando para instalar python3-certbot-dns-cloudflare paquete en Debian/Ubuntu.

sudo apt install python3-certbot-dns-cloudflare

Luego crea un archivo de configuración para Cloudflare.

sudo nano /etc/letsencrypt/cloudflare.ini

Necesitamos agregar la dirección de correo electrónico de nuestra cuenta de Cloudflare y la clave API en este archivo.

# Cloudflare API credentials used by Certbot
dns_cloudflare_email = [email protected]
dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567

Puede encontrar su clave API de Cloudflare en https://dash.cloudflare.com/profile . Tenga en cuenta que el complemento Certbot Cloudflare actualmente no es compatible con los "tokens API" de Cloudflare, así que asegúrese de usar la "clave API global" para la autenticación.

Guarde y cierre el archivo. La clave API omite la autenticación de dos factores de Cloudflare, por lo que solo debe permitir que el usuario raíz lea este archivo.

sudo chmod 600 /etc/letsencrypt/cloudflare.ini

Ahora ejecute certbot.

sudo certbot --agree-tos -a dns-cloudflare -i nginx --redirect --hsts --staple-ocsp --email [email protected] -d www.your-domain.com,your-domain.com

En el comando anterior, especificamos que usaremos dns-cloudflare como autenticador para obtener un nuevo certificado TLS y usar nginx complemento para crear el bloque del servidor HTTPS. Si usa Apache, reemplace nginx con apache .

Este comando le pedirá que ingrese la ruta del .ini archivo, ingrese /etc/letsencrypt/cloudflare.ini y presione la tecla Intro.

Después de obtener e instalar el certificado SSL en el archivo de configuración del servidor web. Debe hacer que escuche en 127.0.0.1:443 o 127.0.0.2:443. Por ejemplo, si usa Nginx, busque

listen 443 ssl

Y cambiarlo a

listen 127.0.0.1:443 ssl http2

Además, cambie el puerto 80 a

listen 127.0.0.1:80;

Guarde y cierre el archivo. Luego reinicie su servidor web.

Errores comunes

1 nombre de dominio incorrecto

Si tiene varios hosts virtuales de Nginx en un servidor y cuando escribe un nombre de dominio, el navegador web lo lleva a otro nombre de dominio alojado en el mismo servidor, es posible que uno de los nombres de archivo de su host virtual de Nginx no termine. con el .conf extensión de nombre de archivo, por lo que Nginx no cargó este host virtual. También podría ser que haya establecido un registro AAAA para el nombre de dominio, pero no configuró Nginx para servir el nombre de dominio en IPv6.

Lo anterior también se aplica al servidor web Apache.

2 Violación del protocolo de red

Si configura el send-proxy-v2 encabezado en HAProxy, pero no habilitó proxy_protocol en Nginx o Apache, su sitio web mostrará el siguiente error.

The site  has experienced a network protocol violation that cannot be repaired.

Recuerde reiniciar Nginx/Apache después de realizar cambios en el archivo de configuración.

3 PR_CONNECT_RESET_ERROR

Si habilita proxy_protocol en Nginx o Apache, pero no configuró send-proxy-v2 encabezado en HAProxy, entonces su sitio web mostrará este error.

secure connection failed. PR_CONNECT_RESET_ERROR

Y encontrará el siguiente mensaje de error en el registro de errores de Nginx o Apache.

broken header while reading PROXY protocol

Recuerde reiniciar Nginx/Apache después de realizar cambios en el archivo de configuración.

También tenga en cuenta que si habilita proxy protocol en un archivo de host virtual Apache/Nginx, entonces también está implícitamente habilitado para todos los demás hosts virtuales. Y no he encontrado una forma de deshabilitar proxy_protocol para host virtual individual. Dado que está ejecutando Apache y Nginx en el mismo servidor, una solución es que solo habilite el protocolo proxy en Nginx y no lo habilite en Apache. Si un host virtual no necesita obtener la dirección IP real del cliente, configúrelo para usar Apache.

Actualizar :Se me ocurrió que puede configurar un nuevo host virtual Apache/Nginx en otra dirección de loopback como 127.0.0.4. De esta forma, el nuevo host virtual no habilitará el protocolo proxy.

4PR_END_OF_FILE_ERROR

Si habilitó el protocolo proxy en Apache/Nginx, pero intenta acceder al host virtual directamente (sin pasar por HAProxy), verá el siguiente error.

PR_END_OF_FILE_ERROR

5 SSL_ERROR_SYSCALL

Si usa el comando curl:

curl -I https://example.com

Y te encuentras con el siguiente error

curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to example.com:443

Probablemente se deba a que no configuró la definición de servidor para este dominio.


Debian
  1. Cómo instalar Apache Hadoop en CentOS 7, Ubuntu 18.04 y Debian 9

  2. Cómo configurar el servidor DHCP en CentOS 7 / Ubuntu 18.04 / 16.04 / Debian 9

  3. Cómo instalar Puppet 6.x en Ubuntu 18.04 / Ubuntu 16.04 y Debian 9

  4. Debian:¿cómo ejecutar programas de 32 bits en un Debian/ubuntu de 64 bits?

  5. Instalar Apache en CentOS 8

Cómo instalar Apache Maven en Ubuntu 18.04 / Ubuntu 16.04 y Debian 9

Cómo instalar FileRun en Ubuntu 20.04 con Apache/Nginx

Instalar Roundcube Webmail en Ubuntu 18.04 con Apache/Nginx

Instalar Roundcube Webmail en Ubuntu 20.04 con Apache/Nginx

Cómo instalar InvoiceNinja en un servidor Ubuntu 18.04 con Apache/Nginx

Cómo instalar InvoiceNinja en un servidor Ubuntu 20.04 con Apache/Nginx