Search code examples
sslnginxcustom-error-pagesnginx-config

Can you terminate SSL to serve custom error pages, but re-encrypt before passing to the target server?


I have a development server that's down a lot and I'm trying to use my stable static web server to provide custom error pages on error-ed out connections. However I don't feel comfortable leaving clear-text communication going between the proxy/load-balancer and the dev server. How, or can, I decrypt and re-encrypt communications between client-proxy and proxy-devServer while intercepting any error responses? I have a sample config, but I'm pretty sure I'm misunderstanding it.

 server {
    listen 443;

    #send to the dev server
    proxy_pass 192.168.1.2:443;

    #decrypt downstream ssl
    ssl_certificate     /etc/ssl/certs/frontend.crt;
    ssl_certificate_key /etc/ssl/certs/frontend.key;

    #Serve custom error page
    error_page 500 502 503 504 /custom_50x.html;
    location = /custom_50x.html {
         root /var/www/errors/html;
         internal;
    }

    #Encrypt upstream communication to the dev server
    proxy_ssl  on;
    proxy_ssl_certificate     /etc/ssl/certs/backend.crt;
    proxy_ssl_certificate_key /etc/ssl/certs/backend.key;
}

Solution

  • The Nginx http server cannot pass through SSL connections (AFAIK), so you must terminate SSL at this server. An upstream SSL connection is established by using https:// in the proxy_pass statement. See this document for details.

    For example:

    server {
        listen 443 ssl;
    
        #decrypt downstream ssl
        ssl_certificate     /etc/ssl/certs/frontend.crt;
        ssl_certificate_key /etc/ssl/certs/frontend.key;
    
        location / {
            #send to the dev server
            proxy_pass https://192.168.1.2;
    
            # Using `https` with an IP address, you will need to provide
            # the correct hostname and certificate name to the upstream
            # server. Use `$host` if it's the same name as this server.
    
            proxy_set_header Host $host;
            proxy_ssl_server_name on;
            proxy_ssl_name $host;
        }
    
        #Serve custom error page
        error_page 500 502 503 504 /custom_50x.html;
        location = /custom_50x.html {
            root /var/www/errors/html;
            internal;
        }    
    }
    

    The proxy_ssl directive relates to the stream server only. The proxy_ssl_certificate directives relate to client certificate authentication, which you may or may not require. Also, you were missing an ssl suffix on the listen statement. See this document for more.