skip to Main Content

My apache2 can no longer connect (by ajp) to my Spring boot’s embedded tomcat after upgrading Spring boot’s version from 2.1.4 to 2.3.2.

It shows the following 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/

I have my dev environment set up this way :

  • an Angular app (node server running on 4200)

  • a spring boot backend (ajp connector set up on tomcat on port 8500)

  • a frontal apache2 server (on a docker container) set up to redirect requests to both apps :

    <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"
    

and I access my web app by a domain name on my /etc/hosts : myapp.develop

this is my spring boot tomcat’s configuration

   Connector connector = new Connector("AJP/1.3");
   connector.setScheme("http");
   connector.setPort(8500);
   connector.setSecure(false);
   connector.setAllowTrace(false);
   ((AbstractAjpProtocol) connector.getProtocolHandler()).setSecretRequired(false);

in the app.properties :

tomcat.ajp.port=8500
tomcat.ajp.remoteauthentication=false
tomcat.ajp.enabled=true

and this is tomcat logs :

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]

I’m doubting that this change :

  • In 8.5.51 onwards, the default listen address of the AJP Connector was changed to the loopback address rather than all addresses.

is what causing me this problem but I don’t know how to solve it.

2

Answers


  1. I’ve never seen a connector being set up in code like this, it’s rather been declared in server.xml

    However, your code is

    Connector connector = new Connector("AJP/1.3");
    connector.setScheme("http");
    connector.setPort(8500);
    connector.setSecure(false);
    connector.setAllowTrace(false);
    ((AbstractAjpProtocol) connector.getProtocolHandler()).setSecretRequired(false);
    

    and later on you state that you know about this breaking change

    In 8.5.51 onwards, the default listen address of the AJP Connector was changed to the loopback address rather than all addresses.

    Combining both: You never set the listening address in your code – so you might be using the default. And as you’re trying to forward to a non-loopback address, there’d be no way to reach the server this way.

    An anonymous editor of this answer suggested connector.setAttribute("address", "0.0.0.0");, but personally, I’d prefer to keep it in server.xml: Connectors typically aren’t configured and changed at runtime, and having your administrators editing a textfile is so much more convenient in day-to-day-operations.

    Login or Signup to reply.
  2. I faced a similar issue upon upgrading the tomcat version. Adding below mentioned properties to the ajp connector helped my case.

    connector.setProperty("address","0.0.0.0");
    connector.setProperty("allowedRequestAttributesPattern",".*");
    ((AbstractAjpProtocol)connector.getProtocolHandler()).setSecretRequired(false);
    

    Detailed Explanation:

    To your doubt:

    In 8.5.51 onwards, the default listen address of the AJP Connector was
    changed to the loopback address rather than all addresses.

    Prior to this update, the tomcat AJP connector was willing to accept requests from any IP address, and so it wasn’t required to explicitly specify "address" property. But after this update, default behavior is that the AJP connector is willing to accept requests only made as localhost (loopback). Use below listed "address" property to expand the listening range to not only the loopback address

    connector.setProperty("address","0.0.0.0"); // OR connector.setProperty("address","::");
    

    Use below property to enable all types of request attributes (unless you have the header info, in that case enable the specific ones). Requests with unrecognized request attributes will be rejected with a 403 response:

    connector.setProperty("allowedRequestAttributesPattern",".*"); 
    

    Use "secretRequired" property to define if a secret is required to be exchanged with the HTTP server so as to allow requests via ajp. If yes, then set the "secret" property as well. Otherwise the requests will fail with 403.

    ((AbstractAjpProtocol)connector.getProtocolHandler()).setSecretRequired(false);
    

    Reference: Apache Tomcat 8 Configuration Reference

    Use of the AJP protocol requires additional security considerations
    because it allows greater direct manipulation of Tomcat’s internal
    data structures than the HTTP connectors. Particular attention should
    be paid to the values used for the address, secret, secretRequired and
    allowedRequestAttributesPattern attributes.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search