5 Replies Latest reply on Feb 18, 2014 7:14 AM by Jean-Frederic Clere

    SSL termination at web server with mod_cluster

    Petr H Newbie

      Hello,

      I'm trying to get the following scenario to fully work (for performance reasons etc):

      Client -> HTTPS -> HTTPD+mod_cluster -> HTTP -> JBoss

       

      I've got it almost working (just had to set ProxyPreserveHost On to avoid totally incorrect redirects to be generated).

       

      But there's a problem with the fact that in this scenario, JBoss doesn't know that the request was originally secure via HTTPS because web server translated them into requests to JBoss http connector (that has scheme=http and secure=false) and all the original request information is lost.

       

      Because of this, the request is incorrectly treated as insecure etc... Any response that will have absolute URL generated will refer to the plain HTTP which will cause mixed content (partially encrypted) in better case.

       

      Another app servers such as WebLogic ans WebSphere are ready for such scenario as they support special header that can tell them that the original request was HTTPS, but I haven't found anything for JBoss. I tried X-Forwarded-Proto, but that doesn't work. Setting connector's secure flag to true forces SSL between HTTPD and JBoss so that isn't the way as well (and it wouldn't be flexible at all anyway)

       

      Is there any decent way how to get this to work?

       

      mod_cluster 1.2.6, JBoss EAP 6.2.0

        • 1. Re: SSL termination at web server with mod_cluster
          Jean-Frederic Clere Master

          There are 2 ways to get that work:

          1 - use ajp (the ssl information is forwarded by the protocol itself

          2 - use the SSLValve See https://community.jboss.org/wiki/SSLModproxyForwarding

          1 of 1 people found this helpful
          • 2. Re: SSL termination at web server with mod_cluster
            Petr H Newbie

            1. Yes, but I can't use AJP because the web server in use doesn't have mod_proxy_ajp (It's IBM HTTP Server and it doesn't come with any AJP support)

            2. But how can I use SSLValve (or generally any valve) in JBoss - and I mean globally so it would be systematic solution - not just per web app (jboss-web.xml)?

            EDIT: I found this Add a Global Valve in AS7 (7.2.x) - it isn't be most elegant solution I'd hope for, but I'll try at least that.

            But how does it work when it comes to tell the servlet container that the original request was SSL as it seems to support headers SSL_CLIENT_CERT, SSL_CIPHER, SSL_SESSION_ID, SSL_CIPHER_USEKEYSIZE which aren't those I really care about in this case. I just need to ensure that the JBoss knows that the request should be treated as secure via HTTPS even though it arrived to its insecure HTTP connector.

            • 3. Re: SSL termination at web server with mod_cluster
              Jean-Frederic Clere Master

              2) - Probably HTTPS needs to be forwarded too and request.setSecure(${HTTPS}) should be added to the valve. Something like:

                 String strhttps = mygetHeader(request, "https");

                 if (strhttps != null && strhttps.equals("true") {

                    request.setSecure(true);

                 }

                 If that helps create a JIRA.

              1 of 1 people found this helpful
              • 4. Re: SSL termination at web server with mod_cluster
                Petr H Newbie

                Well, yes I had to modify the SSLValve as it didn't handle that case, then it got me somewhere, see below:

                - I downloaded the sources for the SSLValve from here: http://maven.repository.redhat.com/techpreview/all/org/jboss/web/jbossweb/7.2.2.Final-redhat-1/

                - had to rename the SSLValve to SSLValve2 due to likely conflict with the default one

                - then added the following piece in there, note that the logging messages are just a simple randomly picked stuff to get something logged for verification purposes, they should be removed normally:

                    // BEGIN: SSL Termination patch
                    strcert0 = mygetHeader(request, "https");
                    if (strcert0 != null && strcert0.equals("true")) {
                        CatalinaLogger.VALVES_LOGGER.managerInvalidSessionTimeout("REQUEST HTTPS header true");
                        request.setSecure(true);
                        // use request.coyoteRequest.scheme instead of request.setScheme() because request.setScheme() is no-op in Tomcat 6.0
                        request.getCoyoteRequest().scheme().setString("https");
                        CatalinaLogger.VALVES_LOGGER.managerInvalidSessionTimeout("REQUEST isSecure: " + request.isSecure());
                        CatalinaLogger.VALVES_LOGGER.managerInvalidSessionTimeout("REQUEST scheme: " + request.getScheme());
                    }
                    // END: SSL Termination patch

                - then installed this in the jar as module and added to the web subsystem similarly to https://community.jboss.org/wiki/AddAGlobalValveInAS772x

                - that gives much better results (when request header HTTPS is set to true) and seems to be the way.

                 

                Note that when checking for the possible solutions I found that there's already a similar mechanism in the RemoteIpValve:

                        if (protocolHeader != null) {
                            String protocolHeaderValue = request.getHeader(protocolHeader);
                            if (protocolHeaderValue == null) {
                                // don't modify the secure,scheme and serverPort attributes
                                // of the request
                            } else if (protocolHeaderHttpsValue.equalsIgnoreCase(protocolHeaderValue)) {
                                request.setSecure(true);
                                // use request.coyoteRequest.scheme instead of request.setScheme() because request.setScheme() is no-op in Tomcat 6.0
                                request.getCoyoteRequest().scheme().setString("https");
                              
                                request.setServerPort(httpsServerPort);
                            } else {
                                request.setSecure(false);
                                // use request.coyoteRequest.scheme instead of request.setScheme() because request.setScheme() is no-op in Tomcat 6.0
                                request.getCoyoteRequest().scheme().setString("http");
                              
                                request.setServerPort(httpServerPort);
                            }
                        }

                I'll test that as well though I'm not sure if that will work without puttinh the RemoteIpValve.class into a separate module (which is mentioned as a requirement at Add a Global Valve in AS7 (7.2.x))

                The question now is whether it's better to request the modification of the SSLValve (e.g. should I open a JIRA request for that), or if it's better to use the existing RemoteIpValve solution for such SSL termination cases.

                 

                Update: So I tried the RemoteIpValve right from the JBoss module and it seems to work as well:

                            <valve name="remoteip-valve" module="org.jboss.as.web" class-name="org.apache.catalina.valves.RemoteIpValve">
                                <param param-name="protocolHeader" param-value="HTTPS"/>
                                <param param-name="protocolHeaderHttpsValue" param-value="true"/>
                            </valve>
                • 5. Re: SSL termination at web server with mod_cluster
                  Jean-Frederic Clere Master

                  Well for what you need the RemoteIpValve looks to be enough.