mirror of
https://github.com/thib8956/nginx-proxy
synced 2025-02-24 01:38:15 +00:00
fix: reject SSL handshake rather than using empty certificate
This commit is contained in:
parent
76873746f3
commit
712a7ef176
@ -568,7 +568,7 @@ The default behavior for the proxy when port 80 and 443 are exposed is as follow
|
||||
|
||||
- If a virtual host has a usable cert, port 80 will redirect to 443 for that virtual host so that HTTPS is always preferred when available.
|
||||
- If the virtual host does not have a usable cert, but `default.crt` and `default.key` exist, those will be used as the virtual host's certificate and the client browser will receive a 500 error.
|
||||
- If the virtual host does not have a usable cert, and `default.crt` and `default.key` do not exist, TLS negotiation will fail (see [Missing Certificate](#missing-certificate) below).
|
||||
- If the virtual host does not have a usable cert, and `default.crt` and `default.key` do not exist, SSL handshake will be rejected (see [Missing Certificate](#missing-certificate) below).
|
||||
|
||||
To serve traffic in both SSL and non-SSL modes without redirecting to SSL, you can include the environment variable `HTTPS_METHOD=noredirect` (the default is `HTTPS_METHOD=redirect`). You can also disable the non-SSL site entirely with `HTTPS_METHOD=nohttp`, or disable the HTTPS site with `HTTPS_METHOD=nohttps`. `HTTPS_METHOD` can be specified on each container for which you want to override the default behavior or on the proxy container to set it globally. If `HTTPS_METHOD=noredirect` is used, Strict Transport Security (HSTS) is disabled to prevent HTTPS users from being redirected by the client. If you cannot get to the HTTP site after changing this setting, your browser has probably cached the HSTS policy and is automatically redirecting you back to HTTPS. You will need to clear your browser's HSTS cache or use an incognito window / different browser.
|
||||
|
||||
@ -584,26 +584,32 @@ If no matching certificate is found for a given virtual host, nginx-proxy will:
|
||||
- force enable HTTP; i.e. `HTTPS_METHOD` will switch to `noredirect` if it was set to `nohttp` or `redirect`.
|
||||
If this switch to HTTP is not wanted set `ENABLE_HTTP_ON_MISSING_CERT=false` (default is `true`).
|
||||
|
||||
If the default certificate is also missing, nginx-proxy will configure nginx to accept HTTPS connections but fail the TLS negotiation. Client browsers will render a TLS error page. As of March 2023, web browsers display the following error messages:
|
||||
If the default certificate is also missing, nginx-proxy will configure nginx to reject the SSL handshake. Client browsers will render a TLS error page. As of October 2024, web browsers display the following error messages:
|
||||
|
||||
- Chrome:
|
||||
#### Chrome:
|
||||
|
||||
> This site can't provide a secure connection
|
||||
> This site can’t be reached
|
||||
>
|
||||
> example.test sent an invalid response.
|
||||
> The web page at https://example.test/ might be temporarily down or it may have moved permanently to a new web address.
|
||||
>
|
||||
> Try running Connectivity Diagnostics.
|
||||
>
|
||||
> `ERR_SSL_PROTOCOL_ERROR`
|
||||
> `ERR_SSL_UNRECOGNIZED_NAME_ALERT`
|
||||
|
||||
- Firefox:
|
||||
#### Firefox:
|
||||
|
||||
> Secure Connection Failed
|
||||
>
|
||||
> An error occurred during a connection to example.test.
|
||||
> Peer reports it experienced an internal error.
|
||||
> An error occurred during a connection to example.test. SSL peer has no certificate for the requested DNS name.
|
||||
>
|
||||
> Error code: `SSL_ERROR_INTERNAL_ERROR_ALERT` "TLS error".
|
||||
> Error code: `SSL_ERROR_UNRECOGNIZED_NAME_ALERT`
|
||||
>
|
||||
> - The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
|
||||
> - Please contact the website owners to inform them of this problem.
|
||||
|
||||
#### Safari:
|
||||
|
||||
> Safari Can't Open the Page
|
||||
>
|
||||
> Safari can't open the page "https://example.test" because Safari can't establish a secure connection to the server "example.test".
|
||||
|
||||
⬆️ [back to table of contents](#table-of-contents)
|
||||
|
||||
|
32
nginx.tmpl
32
nginx.tmpl
@ -710,16 +710,8 @@ server {
|
||||
ssl_certificate /etc/nginx/certs/default.crt;
|
||||
ssl_certificate_key /etc/nginx/certs/default.key;
|
||||
{{- else }}
|
||||
# No default.crt certificate found for this vhost, so force nginx to emit a
|
||||
# TLS error if the client connects via https.
|
||||
{{- /* See the comment in the main `server` directive for rationale. */}}
|
||||
ssl_ciphers aNULL;
|
||||
set $empty "";
|
||||
ssl_certificate data:$empty;
|
||||
ssl_certificate_key data:$empty;
|
||||
if ($https) {
|
||||
return 444;
|
||||
}
|
||||
# No default certificate found, so reject SSL handshake;
|
||||
ssl_reject_handshake on;
|
||||
{{- end }}
|
||||
|
||||
{{- if (exists "/usr/share/nginx/html/errors/50x.html") }}
|
||||
@ -854,24 +846,8 @@ server {
|
||||
return 500;
|
||||
}
|
||||
{{- else }}
|
||||
# No certificate found for this vhost, so force nginx to emit a TLS error if
|
||||
# the client connects via https.
|
||||
{{- /*
|
||||
* The alternative is to not provide an https server for this
|
||||
* vhost, which would either cause the user to see the wrong
|
||||
* vhost (if there is another vhost with a certificate) or a
|
||||
* connection refused error (if there is no other vhost with a
|
||||
* certificate). A TLS error is easier to troubleshoot, and is
|
||||
* safer than serving the wrong vhost. Also see
|
||||
* <https://serverfault.com/a/1044022>.
|
||||
*/}}
|
||||
ssl_ciphers aNULL;
|
||||
set $empty "";
|
||||
ssl_certificate data:$empty;
|
||||
ssl_certificate_key data:$empty;
|
||||
if ($https) {
|
||||
return 444;
|
||||
}
|
||||
# No certificate for this vhost nor default certificate found, so reject SSL handshake.
|
||||
ssl_reject_handshake on;
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
@ -21,7 +21,7 @@ def get(docker_compose, nginxproxy, want_err_re):
|
||||
|
||||
@backoff.on_exception(
|
||||
backoff.constant,
|
||||
requests.exceptions.RequestException,
|
||||
requests.exceptions.SSLError,
|
||||
giveup=lambda e: want_err_re and want_err_re.search(str(e)),
|
||||
interval=.3,
|
||||
max_tries=30,
|
||||
@ -32,7 +32,7 @@ def get(docker_compose, nginxproxy, want_err_re):
|
||||
return _get
|
||||
|
||||
|
||||
INTERNAL_ERR_RE = re.compile("TLSV1_ALERT_INTERNAL_ERROR")
|
||||
INTERNAL_ERR_RE = re.compile("TLSV1_UNRECOGNIZED_NAME")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("compose_file,url,want_code,want_err_re", [
|
||||
@ -97,5 +97,5 @@ def test_fallback(get, url, want_code, want_err_re):
|
||||
r = get(url)
|
||||
assert r.status_code == want_code
|
||||
else:
|
||||
with pytest.raises(requests.exceptions.RequestException, match=want_err_re):
|
||||
with pytest.raises(requests.exceptions.SSLError, match=want_err_re):
|
||||
get(url)
|
||||
|
Loading…
x
Reference in New Issue
Block a user