Solved

Configuring Apache for forced SSL with Virtual Hosts on a multi-homed box

Posted on 2010-08-12
9
1,437 Views
Last Modified: 2013-12-02
Okay, I am incredibly frustrated.  While I can get individual aspects of this working beautifully, I can't seem to put it all together.   I have a box -- dmz.app.com -- that will host an instance of Apache that is intended to sit in front of three distinct sites -- call them a.app.com, b.app.com and c.app.com.  dmz.app.com is multi-homed, with three public IP addresses (outside.100, outside.101 and outside.102), each of which maps to a unique internal IP address (inside.10, inside.11, inside.12).  The distinct sites are configured through DNS so that a.app.com = outside.100, b.app.com = outside.101 and c.app.com = outside.102.  For each site, there is a dedicated Tomcat server -- call them a-tomcat, b-tomcat and c-tomcat.  The idea is simple; for any request on any of the three *.app.com domains, force the request to use SSL (HTTPS over port 443) and route it to the appropriate *-tomcat server.

Forcing SSL seemed to work with the following rules:

RewriteCond %{SERVER_PORT} !^443$
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

Open in new window


Mapping the requests to the appropriate Tomcat seems to sort of work with the following approach:

# This was needed because Apache couldn't resolve the host uniquely due to the triple-homing
ServerName dmz.app.com

NameVirtualHost inside.11
NameVirtualHost inside.12
NameVirtualHost inside.13

<VirtualHost inside.11>
RewriteEngine On
RewriteOptions Inherit

DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/a"
ServerName a.app.com
ErrorLog "C:/Program Files/Apache Software Foundation/Apache2.2/logs/error.log"
TransferLog "C:/Program Files/Apache Software Foundation/Apache2.2/logs/access.log"
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile "C:/Program Files/Apache Software Foundation/Apache2.2/conf/my.crt"
SSLCertificateKeyFile "C:/Program Files/Apache Software Foundation/Apache2.2/conf/my.key"
<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>
BrowserMatch ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0
CustomLog "C:/Program Files/Apache Software Foundation/Apache2.2/logs/ssl_request.log" \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
<Location "/*/WEB-INF/*">
     deny from all
</Location>

JkMount /* a-worker

JkMount /myapp/ a-worker
JkMount /myapp/* a-worker
JkMount /myapp* a-worker
</VirtualHost>                                  

<VirtualHost inside.12>
RewriteEngine On
RewriteOptions Inherit

DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/b"
ServerName b.app.com
ErrorLog "C:/Program Files/Apache Software Foundation/Apache2.2/logs/error.log"
TransferLog "C:/Program Files/Apache Software Foundation/Apache2.2/logs/access.log"
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile "C:/Program Files/Apache Software Foundation/Apache2.2/conf/my.crt"
SSLCertificateKeyFile "C:/Program Files/Apache Software Foundation/Apache2.2/conf/my.key"
<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>
BrowserMatch ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0
CustomLog "C:/Program Files/Apache Software Foundation/Apache2.2/logs/ssl_request.log" \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
<Location "/*/WEB-INF/*">
     deny from all
</Location>

JkMount /* b-worker

JkMount /myapp/ b-worker
JkMount /myapp/* b-worker
JkMount /myapp* b-worker
</VirtualHost>                                  

<VirtualHost inside.13>
RewriteEngine On
RewriteOptions Inherit

DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/c"
ServerName c.app.com
ErrorLog "C:/Program Files/Apache Software Foundation/Apache2.2/logs/error.log"
TransferLog "C:/Program Files/Apache Software Foundation/Apache2.2/logs/access.log"
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile "C:/Program Files/Apache Software Foundation/Apache2.2/conf/my.crt"
SSLCertificateKeyFile "C:/Program Files/Apache Software Foundation/Apache2.2/conf/my.key"
<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>
BrowserMatch ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0
CustomLog "C:/Program Files/Apache Software Foundation/Apache2.2/logs/ssl_request.log" \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
<Location "/*/WEB-INF/*">
     deny from all
</Location>

JkMount /* c-worker

JkMount /myapp/ c-worker
JkMount /myapp/* c-worker
JkMount /myapp* c-worker
</VirtualHost>                                  

Open in new window


The worker.properties file looks like:

workers.java_home="/Program Files/Java/jdk1.6.0_21"

# The advanced router LB worker
worker.list=a-worker, b-worker, c-worker

# Define workers using ajp13
worker.a-worker.port=8009
worker.a-worker.host=a-tomcat
worker.a-worker.type=ajp13

worker.b-worker.port=8009
worker.b-worker.host=b-tomcat
worker.b-worker.type=ajp13

worker.c-worker.port=8009
worker.c-worker.host=c-tomcat
worker.c-worker.type=ajp13

Open in new window


Putting all of these pieces together yields really inconsistent, funky results.  When I point my browser to https://b.app.com/myapp/ or https://b.app.com/myapp, life is wonderful and happy.  When I point my browser to http://b.app.com/myapp/ or http://b.app.com/myapp, I get a 400 Bad Request (Your browser sent a request that this server could not understand.  Reason: You're speaking plain HTTP to an SSL-enabled server port.  Instead use the HTTPS scheme to access this URL, please.).  But if I point my browser to http://b.app.com or http://b.app.com/ or https://b.app.com or https://b.app.com/, I wind up at https://a.app.com/myapp/!

This cannot possibly be as hard as I seem to have made it.  Can somebody please point me in the direction toward sanity?  Thank you!
0
Comment
Question by:arktech
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 2
  • 2
9 Comments
 

Author Comment

by:arktech
ID: 33433795
To clarify what I mean by "point me in the direction toward sanity", answers to the following will be awarded points:

* The outside.10x -> inside.1x -> y.app.com structure was somewhat unintentional.  Originally, I thought unique external IP addresses were required to support SSL; our hosting provider thought we needed unique internal IP addresses.  Are we overcomplicating this?  Is there a better way?  Would we sacrifice any scalability/flexibility by using a different approach?

* What mod_rewrite techniques have you successfully used to force SSL with multiple virtual hosts?

Thanks!
0
 
LVL 51

Expert Comment

by:Steve Bink
ID: 33435505
0
 

Author Comment

by:arktech
ID: 33435983
I did play with SSLRequireSSL, but it's not really the behavior I was after.  In our current configuration (in which Apache is only sitting in front of one of the three environments), attempts to connect via http: are automatically redirected to the https: URL.  We managed that by including a simple redirect index.html in .htdocs.  Unfortunately, that's where the multi-domain/multi-homed complications are causing problems.  I set up a separate subdirectory for each domain (.htdocs/a, .htdocs/b, .htdocs/c) with an index.html in each that redirects to the https: URL for http: connections.  Unfortunately, attempts to connect to b.app.com get redirected to https://a.app.com, no doubt due to some misconfiguration, but I can't seem to figure it out.
0
Webinar: Aligning, Automating, Winning

Join Dan Russo, Senior Manager of Operations Intelligence, for an in-depth discussion on how Dealertrack, leading provider of integrated digital solutions for the automotive industry, transformed their DevOps processes to increase collaboration and move with greater velocity.

 
LVL 26

Accepted Solution

by:
arober11 earned 500 total points
ID: 33436912
Hi, for a start change the "SERVER_NAME", what you get from a "uname -n"  to "HTTP_HOST", the site name passed in the URL, in you Rewrite, and make the re-direct permanent e.g.

RewriteCond %{SERVER_PORT} !^443$
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

I take it the rules are in the body of the httpd.conf, as they don't appear your Virtualhost definitions.

Once tweaked let us know what's not working.
0
 
LVL 51

Expert Comment

by:Steve Bink
ID: 33439240
The normal rule I use:

RewriteCond %{HTTPS} off
# or
# RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
0
 

Author Comment

by:arktech
ID: 33440719
arober11, you are a shining example of why I love Experts Exchange!  Everything is working perfectly now for all four flavors of https: URLs (https://b.app.com, https://b.app.com/, https://b.app.com/myapp and https://b.app.com/myapp/).  Using the http: form of all four yields the same result as before:

---------------------------------------------------
Bad Request

Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.

    Hint: https://b.app.com/
---------------------------------------------------

Now, given that this response includes a hyperlink to a valid URL, I can live with this.  That said, if you know of an easy fix for it, I'm all ears!
0
 

Author Comment

by:arktech
ID: 33441107
Found it; fixed it!  I changed my NameVirtualHost and VirtualHost directives to explicitly specify a.app.com:443 etc. instead of just a.app.com.  Now all eight permutations are working as intended!  Thank you again for the help!  It's amazing how such a little oversight -- HTTP_HOST vs. SERVER_NAME -- can cause so much hair-pulling.
0
 

Author Closing Comment

by:arktech
ID: 33441113
Fantastic!  Exactly the tip I needed.  Once I had this in place, the rest came together quickly.  Thank you, arober11, for spotting the subtle little mistake that was causing me so much frustration!
0
 
LVL 26

Expert Comment

by:arober11
ID: 33447610
Thanks
0

Featured Post

DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you are running a LAMP infrastructure, this little code snippet is very helpful if you are serving lots of HTML, JavaScript and CSS-related information. The mod_deflate module, which is part of the Apache 2.2 application, provides the DEFLATE…
Hi, in this article I'm going to teach you how to run your own site, and how to let people in (without IP). I'll talk about and explain each step... :) By the way, everything in this Tutorial is completely free and legal. This article is for …
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question