1

Contaxt

I currently have an Apache installation with multiple sites via VirtualHosts. My goal is to slowly migrate towards a dockerized setup where one nginx reverse-proxy distributes the requests to dockerized apps.

To start the migration, I created a catch-all in the Apache setup; any request towards a site no longer known by Apache is reverse-proxied to the nginx-proxy docker container. Then, I can add one site to the docker solution, disable it in Apache, and the transition is seemless. This works well for http requests; I'm running into issues for the https requests.

Question

How can I setup apache to not interact with the https requests, but just pass the certificate and encrypted data from nginx? Just transparently pass the requests back and forth?

client <-- https (nginx signed) --> apache <-- https (nginx signed) --> nginx

Other scenarios would be:

Decrypt and re-sign: client <-- https (apache signed) --> apache <-- https (nginx signed) --> nginx

Decrypt in the background: client <-- https (apache signed) --> apache <-- http --> nginx

These seems possible but since nginx serves multiple domains, the apache signature does not match. Also, it does not help in migrating if Apache still needs to do the signing.

Current base config

<VirtualHost *:80>

    ServerName example.com

    ProxyPass / http://127.0.0.1:1001/
    ProxyPassReverse / http://127.0.0.1:1001/
    ProxyPreserveHost On

</VirtualHost>

<VirtualHost *:443>

    ServerName example.com

    ProxyPass / https://127.0.0.1:1002/
    ProxyPassReverse / https://127.0.0.1:1002/
    ProxyPreserveHost On

    # These three lines make Apache sign the requests. Without them I
    # generate SSL_ERROR_RX_RECORD_TOO_LONG errors, but with them the
    # response is always signed with the "example.com" certificate
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

    # This options seems to make sense but I'm unsure what it does
    SSLProxyEngine On

</VirtualHost>
1

If I understood you correctly "endpoint" means the browser client? ("endpoint" usually means a web service endpoint, not the service consumer...)

"Classic" HTTPS would not even allow the scenario you wish to happen. The hostname gets translated via DNS into ip:port(443) of the webserver and then TLS happens, which in early days did completely encrypt the hostname. So your apache, as a man-in-the-middle, would not be able to ever find out which hostname/domainname was requested without owning the certificate and decrypting the TLS traffic.

However. As so often happens, costs (limited public ip ranges) trump principal security. So TLS grew an extension called SNI (codified in 2003 rfc), which many people now rely on, that allows the server to select the right server certificate.

My recommendation

...would be, since you already mentioned that everything works with HTTP, to set up an nginx in front of Apache as an https endpoint...

endpoint <-- front_nginx signed --> front_nginx <-- HTTP --> Apache <-- HTTP --> target_nginx

... and do the SSL migration as a last step from the front-nginx to the target-nginx, derezzing Apache afterwards.

Using SNI

If you want to rely on SNI (which, admittedly, you are probably already doing by your virtual host setup), it might be enough to enable mod_proxy_connect and Disable SSLProxyEngine. Best remove the SSL certificates from apache just to be sure it passes through connections transparently for testing.

Here is this scenario documented usinng haproxy: Can a Reverse Proxy use SNI with SSL pass through?

I have never tried this, so I have no details. Maybe the links I provided help you further.

[Edit:] addendum

(Sorry for the many edits!) Thank you for this question, it made me stumble upon this: https://github.com/Lochnair/xt_tls

which might solve your problem and enable some tricks for me...

  • Thanks - will start by changing endpoint to client before I read on. – TacoV Nov 26 '20 at 8:01
  • Great write-up. I'll start with the mod_proxy_connect route, will report back if I get it working that way. – TacoV Nov 26 '20 at 9:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.