How to Fix “Bad Gateway” Error When Configuring Apache SSL Reverse Proxy to Tomcat


14 views

When setting up Apache as an SSL reverse proxy for Tomcat, a common error encountered is:

Bad Gateway
The proxy server received an invalid response from an upstream server.

For a proper SSL reverse proxy setup, you need:

  • Correct SSL certificates configured in Apache
  • Proper proxy directives (ProxyPass/ProxyPassReverse)
  • Correct Tomcat connector configuration
  • Consistent scheme (https) and port settings

The working configuration should include these critical elements:

LoadModule ssl_module modules/mod_ssl.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

<VirtualHost *:443>
    SSLEngine On
    SSLProxyEngine On
    
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem
    SSLCertificateChainFile /path/to/chain.pem

    ServerName yourdomain.com
    
    ProxyRequests Off
    ProxyPreserveHost On
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port "443"
    
    ProxyPass / http://localhost:8080/ retry=0 timeout=30
    ProxyPassReverse / http://localhost:8080/
</VirtualHost>

The Tomcat server.xml needs these adjustments:

<Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    proxyName="yourdomain.com"
    proxyPort="443"
    scheme="https"
    secure="true"
    URIEncoding="UTF-8"/>

If you still encounter the Bad Gateway error:

  1. Verify Apache can reach Tomcat: curl http://localhost:8080
  2. Check Apache error logs: tail -f /var/log/httpd/error_log
  3. Ensure all required modules are loaded
  4. Test SSL connection independently first
  5. Verify firewall isn't blocking internal connections

For production environments, consider adding:

# Enable SSL session caching
SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout 300

# Stronger ciphers
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:!aNULL:!MD5:!RC4
SSLHonorCipherOrder on

Remember to restart both Apache and Tomcat after configuration changes:

sudo service httpd restart
sudo service tomcat restart

When implementing SSL termination with Apache in front of Tomcat, the configuration requires careful coordination between several components:

Apache (SSL Termination) → Proxy → Tomcat (Backend)

Your setup needs to properly handle these aspects:

  • SSL certificate chain verification
  • Header preservation through proxy
  • Port and scheme consistency
  • Protocol compatibility

Looking at your provided setup, here's the improved version with critical fixes:

<VirtualHost _default_:443>
    SSLEngine On
    SSLProxyEngine On
    SSLProxyVerify none
    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off
    
    SSLCertificateFile /etc/pki/tls/learn2gether/cert-6090205098829887.pem
    SSLCertificateKeyFile /etc/pki/tls/learn2gether/private_key_unlocked.pem
    SSLCertificateChainFile /etc/pki/tls/learn2gether/rubca-chain.pem
    
    # Modern SSL configuration
    SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5
    
    ServerName www.learn2gether.rubel.rub.de
    ServerAlias learn2gether.rubel.rub.de
    
    ProxyRequests Off
    ProxyPreserveHost On
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port "443"
    
    ProxyPass / http://localhost:8080/ retry=0
    ProxyPassReverse / http://localhost:8080/
</VirtualHost>

The key changes that resolve the Bad Gateway error:

  1. Changed proxy target from HTTPS to HTTP (Tomcat should handle plain HTTP)
  2. Added forwarding headers to maintain scheme information
  3. Simplified SSL configuration with modern security standards
  4. Removed conflicting directives like DocumentRoot in SSL vhost

The corresponding Tomcat connector should look like this:

<Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="443"
    proxyPort="443"
    proxyName="www.learn2gether.rubel.rub.de"
    scheme="https"
    secure="true" />

After implementing these changes, verify with:

# Check Apache syntax
apachectl configtest

# Test SSL handshake
openssl s_client -connect www.learn2gether.rubel.rub.de:443 -servername www.learn2gether.rubel.rub.de

# Check headers
curl -v -k -H "Host: www.learn2gether.rubel.rub.de" https://localhost/
  • Mismatched proxy protocols (HTTPS vs HTTP)
  • Missing or incorrect forwarding headers
  • Certificate chain issues
  • Port conflicts between services