How to Fix Apache VirtualHost SSL Proxy Issues with mod_proxy and Tomcat


2 views

When setting up Apache as a reverse proxy for Tomcat with SSL, many developers encounter the frustrating scenario where direct access to the backend (https://host.example.org:8443) works fine, but the proxied connection (https://host.example.org) fails unexpectedly. The symptoms typically include:


# Apache error.log shows:
proxy: no HTTP 0.9 request (with no host line) on incoming request...

# Tomcat access.log shows corrupted request:
"?O^A^C / HTTP/1.1" 302

The core issue stems from SSL protocol handling between Apache's mod_proxy and the backend server. When SSLProxyEngine is enabled, Apache needs additional configuration to properly terminate SSL and forward requests to the backend.

Here's a complete VirtualHost configuration that resolves the SSL proxy issues:


<VirtualHost *:443>
    ServerName host.example.org
    
    SSLEngine On
    SSLProxyEngine On
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem
    
    # Important SSL proxy settings
    SSLProxyVerify none
    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off
    
    # Proxy configuration
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyVia On
    RequestHeader set X-Forwarded-Proto "https"
    
    # The crucial ProxyPass directive
    ProxyPass / https://localhost:8443/ retry=0 timeout=30
    ProxyPassReverse / https://localhost:8443/
    
    # Logging
    ErrorLog ${APACHE_LOG_DIR}/ssl_proxy_error.log
    CustomLog ${APACHE_LOG_DIR}/ssl_proxy_access.log combined
</VirtualHost>

SSLProxyVerify none: Disables certificate verification between Apache and Tomcat when they're on the same host
ProxyPreserveHost On: Maintains the original host header
RequestHeader set X-Forwarded-Proto "https": Informs Tomcat about the original protocol

For complete solution, ensure your Tomcat's server.xml includes proper SSL connector:


<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
           keystoreFile="/path/to/keystore.jks"
           keystorePass="password"
           clientAuth="false" sslProtocol="TLS"
           proxyName="host.example.org" proxyPort="443"/>

If issues persist, try these diagnostic steps:
1. Test with curl -v https://host.example.org
2. Check both Apache and Tomcat logs simultaneously
3. Temporarily disable firewall to rule out connectivity issues
4. Verify time synchronization between servers

Remember to restart Apache after configuration changes:
sudo systemctl restart apache2


When configuring Apache as a reverse proxy with SSL termination for backend applications (like Tomcat running on different ports), you might encounter connection issues where:

  • The direct backend URL (e.g., https://host.example.org:8443) works
  • The proxied SSL URL (https://host.example.org) fails with connection interruption
  • Apache error logs show "proxy: no HTTP 0.9 request" warnings
  • Backend access logs display garbled request methods (e.g., "?O^A^C")

The key problems in the original configuration are:

  1. Missing SSL certificate configuration for the VirtualHost
  2. Potential SSL protocol mismatch between Apache and backend
  3. Improper ProxyPass directive for HTTPS backend

Here's a corrected VirtualHost configuration that handles SSL proxying properly:

<VirtualHost 1.2.3.4:443>
    ServerName host.example.org
    
    # SSL Configuration
    SSLEngine on
    SSLProtocol all -SSLv2 -SSLv3
    SSLCipherSuite HIGH:!aNULL:!MD5
    SSLCertificateFile /etc/ssl/certs/example.org.crt
    SSLCertificateKeyFile /etc/ssl/private/example.org.key
    SSLCertificateChainFile /etc/ssl/certs/example.org.ca-bundle
    
    # Proxy Configuration
    SSLProxyEngine On
    SSLProxyVerify none
    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off
    
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / https://localhost:8443/
    ProxyPassReverse / https://localhost:8443/
    
    # Required headers for proper backend communication
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port "443"
</VirtualHost>

1. SSL Directives: Essential for the frontend SSL termination

2. SSLProxy Settings: Controls how Apache handles SSL to the backend server

3. Header Modifications: Ensures the backend application receives correct protocol information

If the issue persists:

  1. Verify SELinux/apparmor isn't blocking proxy connections
  2. Check Apache modules are properly loaded:
a2enmod ssl
a2enmod proxy
a2enmod proxy_http
a2enmod headers

3. Test backend connectivity independently:

curl -vk https://localhost:8443/

For applications requiring WebSockets or special protocols:

<Location />
    ProxyPass wss://localhost:8443/
    ProxyPassReverse wss://localhost:8443/
    ProxyPassReverseCookieDomain localhost host.example.org
</Location>