Me preguntaba si nginx es capaz de manejar solicitudes http y https en el mismo puerto . [*]
Esto es lo que estoy tratando de hacer. Estoy ejecutando un servidor web (lighttpd) que maneja solicitudes http y un programa en C que sirve una sección particular del árbol de documentos a través de https. Estos dos procesos se ejecutan en el mismo servidor.
En el nivel de firewall, solo puedo tener un puerto que reenvíe el tráfico a este servidor . Entonces, lo que me gustaría hacer es configurar nginx en este servidor para que escuche las solicitudes en un solo puerto y luego:
A) redirige todas las solicitudes http://myhost.com/ * para que vayan a localhost: 8080 (donde lighttpd está escuchando)
B) si un usuario solicita una URL que comienza con, por ejemplo, https: // myhost.com/app, envía esa solicitud a localhost: 8008 (programa C). Tenga en cuenta que en este caso, el tráfico entre el navegador remoto y nginx debe estar encriptado.
¿Crees que esto podría ser posible? Si es así, ¿cómo se puede hacer?
Sé cómo hacer esto usando dos puertos diferentes. El desafío que enfrento es hacer esto con un solo puerto (desafortunadamente, no tengo control sobre la configuración del firewall en este entorno en particular, por lo que es una restricción que no puedo evitar). El uso de técnicas como el puerto inverso hacia adelante a través de ssh para evitar el firewall tampoco funcionará, porque esto debería funcionar para usuarios remotos que no tienen más que un navegador web y un enlace a Internet.
Si esto está más allá de las capacidades de nginx, ¿conoce algún otro producto que pueda cumplir con estos requisitos? (hasta ahora no he tenido éxito al configurar esto con lighttpd y pound). También preferiría evitar Apache (aunque estoy dispuesto a usarlo si es la única opción posible).
Gracias de antemano, Alex
[*] Para ser claros, estoy hablando de manejar conexiones HTTP encriptadas y no encriptadas a través del mismo puerto. No importa si el cifrado se realiza a través de SSL o TLS.
Respuestas:
Según el artículo de Wikipedia sobre códigos de estado, Nginx tiene un código de error personalizado cuando el tráfico http se envía al puerto https (código de error 497)
Y de acuerdo con los documentos de nginx en error_page , puede definir un URI que se mostrará para un error específico.
Por lo tanto, podemos crear una uri a la que se enviarán los clientes cuando se genere el código de error 497.
nginx.conf
Sin embargo, si un cliente realiza una solicitud a través de cualquier otro método, excepto un GET, esa solicitud se convertirá en un GET. Por lo tanto, para preservar el método de solicitud por el que entró el cliente; Usamos redireccionamientos de procesamiento de errores como se muestra en los documentos de nginx en error_page
Y es por eso que usamos la
301 =307
redirección.Usando el archivo nginx.conf que se muestra aquí, podemos hacer que http y https escuchen en el mismo puerto
fuente
Para aquellos que podrían estar buscando:
Agregue
ssl on;
yerror_page 497 $request_uri;
a la definición de su servidor.fuente
ssl on;
yerror_page 497 =200 $request_uri;
a la definición de su servidor. Esto cambiará el código de estado a 200.Si quisiera ser realmente inteligente, podría usar un proxy de conexión para detectar los primeros bytes de la secuencia de datos entrantes y transferir la conexión según el contenido del byte 0: si es 0x16 (el SSL / TLS ' byte de apretón de manos), pase la conexión al lado SSL, si es un carácter alfabético, haga HTTP normal. Se aplica mi comentario sobre la numeración de puertos .
fuente
Sí, es posible, pero necesita parchear el código fuente nginx (HoverHell tiene una solución sin parches). Nginx trata esto como una configuración incorrecta en lugar de una configuración válida.
La variable $ ssl_session_id se puede usar para diferir entre la conexión simple y la conexión SSL.
Parche contra nginx-0.7.65:
Configuración del servidor:
fuente
No creo que haya nada que pueda manejar dos protocolos diferentes en un solo puerto ...
Tengo curiosidad por saber por qué solo puede reenviar un puerto, pero aparte de eso ... no es lo ideal, pero si estuviera en su lugar, serviría todo a través de https.
fuente
No puede admitir tanto HTTP como HTTPS en el mismo puerto, porque ambos extremos de la conexión esperan hablar un cierto idioma, y no son lo suficientemente inteligentes como para saber si el otro extremo está hablando algo más.
Como sugiere su comentario a la respuesta de Wil, podría usar la actualización TLS (creo que las nuevas versiones de nginx lo admiten, aunque no lo he intentado), pero eso no está ejecutando HTTP y HTTPS, solo está ejecutando HTTP con la actualización TLS. El problema sigue siendo la compatibilidad con el navegador: la mayoría de los navegadores (todavía) no lo admiten. Si tiene un grupo limitado de clientes, entonces esta es una posibilidad, sin embargo.
fuente
No estoy seguro de cómo lo logra, pero CUPSD responde tanto a http como a https en el puerto 631. Si nginx no puede hacerlo ahora, tal vez puedan aprender de cómo el equipo de CUPS lo logra, pero CUPS está bajo el GPL, por lo que nginx puede tener que buscar cambiar su licencia si quieren implementar dicha capacidad y no pueden encontrar el código para hacerlo en otro lugar.
fuente
En teoría, podría tener una página web accesible a través de HTTP, que puede abrir un WebSocket en https: 443 en cualquier lugar que desee. El protocolo de enlace inicial de WebSocket es HTTP. Entonces, sí, es posible hacer que una página de aspecto inseguro sea capaz de una comunicación segura. Podrías hacer esto con la Biblioteca Netty .
fuente
Esto finalmente es posible hacerlo correctamente desde 1.15.2. Vea la información aquí .
En su nginx.conf agregue un bloque como este (fuera del bloque http):
Luego puede crear su bloque de servidor normal, pero escuchando en estos puertos diferentes:
De esta manera, el bloque de flujo puede leer previamente y detectar si es TLS o no (en el puerto 8080 en este ejemplo), y luego el proxy lo pasa al puerto del servidor correcto localmente.
fuente