Skip to content

Instantly share code, notes, and snippets.

Last active November 12, 2022 21:42
Show Gist options
  • Save WhisperingChaos/033699f3b8d0df89ac50ab185b8628b4 to your computer and use it in GitHub Desktop.
Save WhisperingChaos/033699f3b8d0df89ac50ab185b8628b4 to your computer and use it in GitHub Desktop.
NGINX SSL/TLS Reverse Proxy to Upstream SSL servers.
events {
# nginx requires this section even when applying all default values
http {
# Upstream keyword is followed by a url (domain name/IP). This reference encapsulates
# the list of backend servers defined for a virtual proxy. When autnenticating
# a certificate from a backend server, the upstream url is supplied to the
# certificate authentication process instead of the backend server name. See
# the comments associated with proxy_pass below for a detailed discussion.
upstream aaa.domain.tld {
# Included two servers to determine the behavior of SSL parameters.
# The absense of a load balancing property in upstream causes ngnix
# to apply a round robin method to select the next backend server.
# Also, it's unnecessary to create separate virtual server blocks for
# these servers, as nginx has enough information, provided below,
# to establish ssl connections to each backend server.
server aaa.domain.tld:10443;
server bbb.domain.tld:10443; # assigned the same certificate as aaa.domain.tld
server {
# Creating virtual proxy server using nginx.
# The virtual proxy server's FQDN/IP. This name/IP must "match"
# its associated certificate Common Name specified by the ssl_certificate property.
server_name proxy.domain.tld;
# virtual proxy server listens on port 8080 and any connection must
# be encrypted by ssl
listen 8080 ssl;
# Identifies the file containing the virtual proxy server's signed SSL certificate.
# This certificate is presented, when asked, to connections attempting to contact this virtual
# proxy server. After the virtual proxy server provides its signed certificate to a
# connection, the server (foreign) that initiated the connection will typically consume
# the offerred certificate and authenticate it. Authentication requires a foreign
# server to walk it's Certificate Authority chain to locate the root certificate
# which signed the one provided by the virtual proxy server.
ssl_certificate /etc/nginx/ssl/reverseproxy.crt;
# Identifies the file containg the virtual proxy server's private key that's needed
# to encrypt content provided by the virtual server.
ssl_certificate_key /etc/nginx/ssl/reverseproxy.key;
# One or more root Certificates, concatenated into a single file, used by
# the virtual proxy server to verify, when required by "ssl_verify_client on;",
# the certificates presented by foreign servers attempting to connect to
# this virtual proxy server.
ssl_client_certificate /etc/nginx/ssl/rootCA.pem;
# A switch that enables/disables the virtual proxy server's certificate authentication
# behavior. When "on", a foreign server attempting to connect with the virtual proxy
# server must provide a certificate whose signer (root certificate) exists in the
# list of root certificates specified by ssl_client_certificate.
# The "off" value below allows this virtual server to accept any ssl connection.
# Including ones potentially compromised by a Man In Middle attack.
# Note other settings besides on/off are possible see nginx documentation.
ssl_verify_client off;
# The root ("/") location specifier matches all urls/uris directed to the
# virtual proxy server.
location / {
# References the upstream block, identified by the specified url, that lists all the
# virtual servers (backend servers) located in this nginx.conf file that this virtual
# proxy server can forward requests to. Urls prefixed with "https:" protocol
# direct nginx to establish a ssl connection to the backend server selected
# by nginx to fulfill a request forwarded by the virtual proxy server.
# When attempting a ssl connection and "proxy_ssl_verify on;", the virtual proxy server inspects the certificate
# provided by the selected backend server, however, instead of using the url
# assigned to this backend server, as it appears in the upstream block, the url
# defined by proxy_pass (the upstream url block name) is supplied by nginx to the
# certificate authentication process. If the backend certificate Common Name
# fails to match the one defined by proxy_pass then the authentication process
# generates the error: "upstream SSL certificate does not match "<proxy_pass_url> while SSL handshaking to upstream, client:...".
# Therefore, one must either change the proxy_pass url so it can match every
# certificate Common Name defined for each backend server, or change every
# backend certificate Common Name so it will match the url specified by the
# proxy_pass property.
proxy_pass https://aaa.domain.tld;
# Defines the ssl certificate that this virtual proxy server: "proxy.domain.tld"
# will present to the backend servers identified by proxy_pass. This certificate
# can be different than the one defined outside this location block, however,
# the same "reverseproxy.crt" file was used to avoid managing yet another
# certificate.
proxy_ssl_certificate /etc/nginx/ssl/reverseproxy.crt;
# Defines the private key associated to the proxy_ssl_certificate.
# This private key encrypts the content forwarded by this proxy to
# the backend servers.
proxy_ssl_certificate_key /etc/nginx/ssl/reverseproxy.key;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
# Defines the CA chain of one or more root certificates to search when authenticating
# certificates provided by the backend servers. Ensures that the
# virtual proxy server communicates directly with an authentic backend server.
proxy_ssl_trusted_certificate /etc/nginx/ssl/rootCA.pem;
# Directs the virtual proxy server to authentic the certificate provided by
# each backend server using the root certificates enumerated by
# the proxy_ssl_trusted_certificate list.
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
Copy link

While creating NGINX ssl reverse proxy, encountered error 'upstream SSL certificate does not match "<proxy_pass_url> while SSL handshaking to upstream, client...' . Initially thought NGINX would provide the selected upstream server's url to the certificate authentication process, however, NGINX supplies the url specified by proxy_pass as this name. Therefore, if the selected upstream server's certificate Common Name fails to "match" the url specified by proxy_pass, the certificate authentication process issues the above message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment