Solved

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

Posted on 2010-08-12
9
1,442 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
Migrating Your Company's PCs

To keep pace with competitors, businesses must keep employees productive, and that means providing them with the latest technology. This document provides the tips and tricks you need to help you migrate an outdated PC fleet to new desktops, laptops, and tablets.

 
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

Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

Question has a verified solution.

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

Over the last year I have answered a couple of basic URL rewriting questions several times so I thought I might as well have a stab at: explaining the basics, providing a few useful links and consolidating some of the most common queries into a sing…
SSL stands for “Secure Sockets Layer” and an SSL certificate is a critical component to keeping your website safe, secured, and compliant. Any ecommerce website must have an SSL certificate to ensure the safe handling of sensitive information like…
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…

623 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