Apache no puede conectarse al nuevo tomcat 9 ajp
Mi apache2 ya no puede conectarse (mediante ajp) al tomcat integrado de Spring Boot después de actualizar la versión de Spring Boot de 2.1.4 a 2.3.2.
Muestra el siguiente error:
[proxy:error] [pid xxxx ] (111)Connection refused: AH00957: AJP: attempt to connect to 10.0.75.1:8500 (10.0.75.1) failed
[proxy_ajp:error] [pid xxxx ] [client xxx ] AH00896: failed to make connection to backend: 10.0.75.1, referer: http://myapp.develop/home/
Tengo mi entorno de desarrollo configurado de esta manera:
una aplicación Angular (servidor de nodo que se ejecuta en 4200)
un backend de arranque de resorte (conector ajp configurado en tomcat en el puerto 8500)
un servidor apache2 frontal (en un contenedor docker) configurado para redirigir las solicitudes a ambas aplicaciones:
<VirtualHost *:80> ServerName myapp.develop ProxyPass "/home" "http://10.0.75.1:4200/home" ProxyPassReverse "/home" "http://10.0.75.1:4200/home" ProxyPass "/backend" "ajp://10.0.75.1:8500/backend" ProxyPassReverse "/backend" "ajp://10.0.75.1:8500/backend"
y accedo a mi aplicación web mediante un nombre de dominio en mi /etc/hosts: myapp.develop
esta es la configuración de mi spring boot tomcat
Connector connector = new Connector("AJP/1.3");
connector.setScheme("http");
connector.setPort(8500);
connector.setSecure(false);
connector.setAllowTrace(false);
((AbstractAjpProtocol) connector.getProtocolHandler()).setSecretRequired(false);
en la aplicación.propiedades:
tomcat.ajp.port=8500
tomcat.ajp.remoteauthentication=false
tomcat.ajp.enabled=true
y esto es registros de Tomcat:
o.s.b.w.e.t.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 8500 (http)
o.a.c.h.Http11NioProtocol : Initializing ProtocolHandler ["http-nio-8080"]
o.a.c.a.AjpNioProtocol : Initializing ProtocolHandler ["ajp-nio-127.0.0.1-8500"]
o.a.c.c.StandardService : Starting service [Tomcat]
o.a.c.c.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.37]
Estoy dudando que este cambio:
- A partir de la versión 8.5.51, la dirección de escucha predeterminada del conector AJP se cambió a la dirección de bucle invertido en lugar de a todas las direcciones.
es lo que me causa este problema, pero no sé cómo resolverlo.
Respuestas
Enfrenté un problema similar al actualizar la versión de Tomcat. Agregar las propiedades mencionadas a continuación al conector ajp ayudó a mi caso.
connector.setProperty("address","0.0.0.0");
connector.setProperty("allowedRequestAttributesPattern",".*");
((AbstractAjpProtocol)connector.getProtocolHandler()).setSecretRequired(false);
Explicación detallada:
A tu duda:
A partir de la versión 8.5.51, la dirección de escucha predeterminada del conector AJP se cambió a la dirección de bucle invertido en lugar de a todas las direcciones.
Antes de esta actualización, el conector Tomcat AJP estaba dispuesto a aceptar solicitudes de cualquier dirección IP, por lo que no era necesario especificar explícitamente la propiedad "dirección". Pero después de esta actualización, el comportamiento predeterminado es que el conector AJP está dispuesto a aceptar solicitudes realizadas solo como host local (bucle invertido). Use la propiedad de "dirección" que se muestra a continuación para expandir el rango de escucha no solo a la dirección de bucle invertido
connector.setProperty("address","0.0.0.0"); // OR connector.setProperty("address","::");
Use la propiedad a continuación para habilitar todos los tipos de atributos de solicitud (a menos que tenga la información del encabezado, en ese caso, habilite los específicos). Las solicitudes con atributos de solicitud no reconocidos se rechazarán con una respuesta 403:
connector.setProperty("allowedRequestAttributesPattern",".*");
Utilice la propiedad "secretRequired" para definir si es necesario intercambiar un secreto con el servidor HTTP para permitir solicitudes a través de ajp. En caso afirmativo, configure también la propiedad "secreta". De lo contrario, las solicitudes fallarán con 403.
((AbstractAjpProtocol)connector.getProtocolHandler()).setSecretRequired(false);
Referencia: Referencia de configuración de Apache Tomcat 8
El uso del protocolo AJP requiere consideraciones de seguridad adicionales porque permite una mayor manipulación directa de las estructuras de datos internas de Tomcat que los conectores HTTP. Se debe prestar especial atención a los valores utilizados para los atributos address , secret , secretRequired y allowRequestAttributesPattern .
Nunca he visto un conector configurado en un código como este, más bien se ha declarado en server.xml
Sin embargo, su código es
Connector connector = new Connector("AJP/1.3");
connector.setScheme("http");
connector.setPort(8500);
connector.setSecure(false);
connector.setAllowTrace(false);
((AbstractAjpProtocol) connector.getProtocolHandler()).setSecretRequired(false);
y luego dices que sabes sobre este cambio radical
A partir de la versión 8.5.51, la dirección de escucha predeterminada del conector AJP se cambió a la dirección de bucle invertido en lugar de a todas las direcciones.
Combinando ambos: nunca establece la dirección de escucha en su código, por lo que podría estar usando el valor predeterminado. Y como está tratando de reenviar a una dirección que no sea de bucle invertido, no habría forma de llegar al servidor de esta manera.
Un editor anónimo de esta respuesta sugirió connector.setAttribute("address", "0.0.0.0");
, pero personalmente, preferiría mantenerlo en server.xml: los conectores generalmente no se configuran ni cambian en el tiempo de ejecución, y hacer que sus administradores editen un archivo de texto es mucho más conveniente en el día a -día-operaciones.