Home > database >  How do I configure Tomcat (behind Apache) without using AJP?
How do I configure Tomcat (behind Apache) without using AJP?

Time:09-17

I am trying to remove the use of AJP from an existing installation for security reasons, but cannot find any info on how to do so.

Specifically, my original Apache config has JKMount directives in it, which I have replaced with ProxyPass and ProxyPassReverse directives, but the original Kerberos authentication doesn't appear to be getting passed through to Tomcat any more.

(I now have mod_proxy_http and mod_proxy enabled.)

Google is definitely not my friend in this case.

CodePudding user response:

There isn't really a standard way to forward the authenticated user name from Apache to Tomcat using mod_proxy_http, but you can easily create one:

  1. Configure Apache 2 to send an X-Forwarded-User header (if we have an authenticated user):
RequestHeader unset X-Forwarded-User
RequestHeader set X-Forwarded-User "expr=%{REMOTE_USER}" "expr=-n %{REMOTE_USER}"
  1. Compile (and put it in $CATALINA_BASE/lib) a Valve on Tomcat's side that will retrieve the X-Forwarded-User from "trusted" hosts:
import java.io.IOException;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import org.apache.catalina.connector.CoyotePrincipal;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;

public class RemoteUserValve extends ValveBase {

    private static String remoteUserHeader = "X-Forwarded-User";
    // Same as in RemoteIpValve 
    private static Pattern internalProxies = Pattern
            .compile("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|"   "192\\.168\\.\\d{1,3}\\.\\d{1,3}|"
                      "169\\.254\\.\\d{1,3}\\.\\d{1,3}|"   "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|"
                      "172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|"   "172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|"
                      "172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}|"   "0:0:0:0:0:0:0:1|::1");

    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        if (internalProxies.matcher(request.getRemoteAddr()).matches()) {
            final String user = request.getHeader(remoteUserHeader);
            if (user != null && !user.isEmpty()) {
                request.setUserPrincipal(new CoyotePrincipal(user));
            }
        }

        getNext().invoke(request, response);
    }
}
  1. Add the valve to servers.xml
<Engine name="Catalina">
    <Valve className="fully.qualified.name.RemoteUserValve" />
    ...
</Engine>

I wouldn't consider this very secure, but it provides the same level of security as the equivalent AJP feature.

  • Related