Nginx como proxy directo para HTTPS

Nginx como proxy directo para HTTPS

Si bien pude configurar con éxito nginx para representar el tráfico HTTP (usandoesta guía), todos los intentos de enviar solicitudes HTTPS dieron como resultado el código 400 (Solicitud incorrecta).

Los registros de depuración de Nginx no fueron útiles en absoluto:

2013/06/05 14:38:33 [info] 74946#0: *589
    client sent invalid request while reading client request line, client: 127.0.0.1,
    server: google.com, request: "CONNECT google.com:443 HTTP/1.1"

¿Cuáles son estas CONNECTsolicitudes? ¿Es posible realizar proxy_passsolicitudes HTTPS en nginx?

Actualizar

Es necesario agregar que un servidor proxy es parte de mi flujo de trabajo/kit de herramientas de desarrollo web. Es una excelente manera de probar/depurar JavaScript del lado del cliente enproducciónentorno (usando reescrituras antes del proxy).

Además, se puede decir que el lenguaje de configuración de nginx es un lenguaje de programación por derecho propio. ¡Tiene variables!

Respuesta1

Parece que nginx no admite el modo proxy directo con SSL. Necesitarás usar algo comoCalamaren cambio. Aquí hay un enlace con más explicaciones del autor de nginx:HTTPS y nginx como Forward Proxy.

Respuesta2

Solo para aclarar: como escribí en los comentarios de mi blog, nginx no maneja llamadas al método CONNECT que se utilizan para establecer una conexión TCP sin formato a un host remoto a través de un proxy HTTP, lo cual tiene sentido, considerando que se supone que nginx no debe hacerlo. funciona como un proxy de reenvío, pero resulta que funciona bastante bien para HTTP normal de todos modos.

Nginx literalmente no tiene idea de qué hacer con esas llamadas a métodos, es por eso que los mensajes de error en los registros son bastante inútiles. Siempre me he encontrado usando privoxy para HTTPS:http://www.privoxy.org/- También es increíblemente fácil de configurar. Pero aún es imposible filtrar o alterar el contenido de las retransmisiones HTTPS, porque las conexiones HTTPS se manejan con una conexión sin formato a través del método CONNECT y el servidor no tiene idea de lo que está retransmitiendo.

Respuesta3

Si no te importa compilar nginx desde el código fuente, puedes instalarngx_http_proxy_connect_module. Lo siguiente funcionó para mí en Debian 9 "Stretch" en una Raspberry Pi (después de agregar las URL deb-src a /etc/apt/sources.list e hice apt-get update):

cd /tmp &&
apt-get source nginx &&
git clone https://github.com/chobits/ngx_http_proxy_connect_module &&
cd nginx-* &&
patch -p1 < ../ngx_http_proxy_connect_module/proxy_connect.patch &&
sudo apt-get install libpcre3-dev &&
./configure --add-module=/tmp/ngx_http_proxy_connect_module &&
make && sudo make install

Luego edite /usr/local/nginx/conf/nginx.confy haga que se vea así (he incluido un ejemplo de dominios que desea bloquear, que funciona tanto con proxy SSL como sin SSL):

user www-data;
worker_processes auto;
events { }
http {
    server_names_hash_bucket_size 128;
    server {
        listen       8888;
        server_name  spam.example.com *.spam.example.com;
        server_name  spam2.example.com *.spam2.example.com;
        access_log off;
        return 404;
    }
    server {
        listen       8888;
        server_name ~.+;
        proxy_connect;
        proxy_max_temp_file_size 0;
        resolver 8.8.8.8;
        location / {
           proxy_pass http://$http_host;
           proxy_set_header Host $http_host;
        }
    }
}

Entonces corre /usr/local/nginx/sbin/nginx. Coexistirá felizmente con nginxel paquete estándar de Debian si también está ejecutando un servidor web de producción en el puerto 80 y no quiere arriesgarse a alterar eso (pero asegúrese de iniciar la /usr/localversión por separado al arrancar); alternativamente, con más configuración podrías ejecutar ambos servicios desde el nginx que has compilado. Pero si configura su nginx compilado para que se ejecute en un puerto al que su firewall permite el tráfico, tenga en cuenta que tendrá que verificar manualmente las actualizaciones de seguridad de nginx, ya que el sistema de paquetes Debian ya no lo hará por usted.

Respuesta4

A mi equipo le tomó algo de tiempo descubrir cómo hacer que esto funcionara. Finalmente lo logramos incorporando el siguiente fragmento en nginx.conf:

stream {
  map_hash_bucket_size 128;
  map $ssl_preread_server_name $sphere {
    site-01.example.com site-01;
    site-02.example.com site-02;
  }

  upstream site-01 {
    server 192.168.0.1:443;
  }

  upstream site-02 {
    server 192.168.0.2:443;
  }

  server {
    listen 443;
    proxy_pass $sphere;
    ssl_preread on;
  }
}

información relacionada