Configuring Apache as HTTPS-to-HTTP Reverse Proxy: Solving 301 Redirect Issues


4 views

When setting up Apache as a reverse proxy to forward HTTPS requests to an HTTP backend (thirdparty.com in this case), you might encounter unexpected 301 redirects. This typically happens when:

  • The backend server responds with absolute URLs containing its own domain
  • Apache's proxy modules aren't properly configured to rewrite URLs
  • SSLProxyEngine directives are missing or misconfigured

Here's the corrected VirtualHost configuration that handles HTTPS-to-HTTP proxying without 301 redirects:


<VirtualHost *:443>
    ServerName mydomain.com
    SSLEngine on
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem

    SSLProxyEngine On
    ProxyRequests Off
    ProxyPreserveHost Off
    RequestHeader set X-Forwarded-Proto "https"

    # Important for URL rewriting
    SetOutputFilter proxy-html
    ProxyHTMLExtended On
    
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    ProxyPass /proxy/ http://thirdparty.com/app/ nocanon
    ProxyPassReverse /proxy/ http://thirdparty.com/app/
    
    <Location /proxy/>
        ProxyHTMLEnable On
        ProxyHTMLURLMap http://thirdparty.com/app/ /proxy/
        ProxyHTMLURLMap / /proxy/
        ProxyHTMLURLMap https://thirdparty.com/app/ /proxy/
        RequestHeader unset Accept-Encoding
    </Location>
</VirtualHost>

nocanon: Prevents Apache from canonicalizing URLs which could trigger redirects

ProxyPreserveHost Off: Ensures the Host header is set to the backend server's domain

RequestHeader set X-Forwarded-Proto: Informs the backend about the original HTTPS request

Multiple ProxyHTMLURLMap: Handles all possible URL variations from the backend

If you still experience issues:

  1. Enable verbose logging:
  2. 
    LogLevel debug
    ErrorLog /var/log/apache2/proxy_error.log
    CustomLog /var/log/apache2/proxy_access.log combined
    
  3. Test with curl to examine headers:
  4. 
    curl -v -k -H "Host: mydomain.com" https://mydomain.com/proxy/
    
  5. Check backend responses directly:
  6. 
    curl -v http://thirdparty.com/app/
    

For complex scenarios, consider these additions:


# Handle WebSocket connections
ProxyPass /proxy/ws/ ws://thirdparty.com/app/ws/
ProxyPassReverse /proxy/ws/ ws://thirdparty.com/app/ws/

# Cookie path rewriting
ProxyPassReverseCookiePath /app/ /proxy/

When trying to set up Apache as a reverse proxy to forward HTTPS traffic from https://mydomain.com/proxy/ to an HTTP backend at http://thirdparty.com/app/, you might encounter an infinite 301 redirect loop. This happens because the backend server tries to redirect HTTP requests, while Apache is already handling HTTPS.

Here's the proper VirtualHost configuration that solves this issue:


<VirtualHost *:443>
    ServerName mydomain.com
    SSLEngine on
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem
    
    SSLProxyEngine On
    ProxyRequests Off
    ProxyPreserveHost On
    
    # Fix for 301 redirects
    ProxyPass /proxy/ http://thirdparty.com/app/ nocanon
    ProxyPassReverse /proxy/ http://thirdparty.com/app/
    
    # HTML content rewriting
    SetOutputFilter proxy-html
    ProxyHTMLExtended On
    
    <Location /proxy/>
        ProxyHTMLEnable On
        ProxyHTMLURLMap http://thirdparty.com/app/ /proxy/
        ProxyHTMLURLMap / /proxy/
        RequestHeader unset Accept-Encoding
    </Location>
</VirtualHost>

The critical elements that make this work:

  • nocanon parameter prevents URL canonicalization that could cause redirects
  • ProxyPreserveHost On maintains the original host header
  • RequestHeader unset Accept-Encoding prevents gzip encoding issues
  • Proper SSL configuration for the frontend

After implementing these changes, test with curl to verify no redirects occur:


curl -vk https://mydomain.com/proxy/

Look for these indicators of success:

  • HTTP 200 response code
  • No Location header in the response
  • Content from the backend server appears correctly

If you still encounter problems:

  1. Check Apache error logs: tail -f /var/log/httpd/error_log
  2. Verify mod_proxy and mod_proxy_html are loaded: httpd -M | grep proxy
  3. Test backend connectivity: curl -v http://thirdparty.com/app/
  4. Ensure SELinux isn't blocking connections: setsebool -P httpd_can_network_connect 1