[PATCH] Proxy remote server SSL certificate verification
Maxim Dounin
mdounin at mdounin.ru
Tue Sep 3 13:21:39 UTC 2013
Hello!
On Tue, Sep 03, 2013 at 03:32:58PM +0300, Aviram Cohen wrote:
> Thanks for the comments. The new version with all the fixes is
> attached (and also pasted in this mail).
See below for comments.
[...]
> @@ -2382,6 +2408,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_
> * conf->body_set = NULL;
> * conf->body_source = { 0, NULL };
> * conf->redirects = NULL;
> + * conf->ssl_trusted_certificate = NULL;
> */
>
> conf->upstream.store = NGX_CONF_UNSET;
Nitpicking: ssl_trusted_certificate is ngx_str_t, so it's set
to { 0, NULL } (much like body_source above).
[...]
> + if (conf->upstream.ssl && conf->upstream.ssl_verify) {
> + if (conf->ssl_trusted_certificate.len == 0) {
> + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
> + "no \"proxy_ssl_trusted_certificate\" is "
> + " defined for the \"proxy_ssl_verify\" "
> + "directive");
> +
> + return NGX_CONF_ERROR;
> + }
> + }
> +
> + if (conf->upstream.ssl
> + && ngx_ssl_trusted_certificate(cf, conf->upstream.ssl,
> + &conf->ssl_trusted_certificate,
> + conf->ssl_verify_depth)
> + != NGX_OK)
> + {
> + return NGX_CONF_ERROR;
> + }
Nitpicking: if (conf->upstream.ssl) seems to be common condition,
and probably conf->upstream.ssl_verify too. Merging the two under
something like
if (conf->upstream.ssl && conf->upstream.ssl_verify) {
if (conf->ssl_trusted_certificate.len == 0) {
...
}
if (ngx_ssl_trusted_certificate(...)
!= NGX_OK)
{
...
}
}
should be better.
[...]
> @@ -1319,12 +1319,30 @@ ngx_http_upstream_ssl_handshake(ngx_conn
> {
> ngx_http_request_t *r;
> ngx_http_upstream_t *u;
> -
> + X509 *cert;
> +
> r = c->data;
> u = r->upstream;
>
> if (c->ssl->handshaked) {
> -
> + if (u->conf->ssl_verify) {
> + if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
> + ngx_log_error(NGX_LOG_ERR, c->log, 0,
> + "upstream ssl certificate validation failed");
This seems to lack detailsed error reporting. Logging at least
error returned and X509_verify_cert_error_string() as it's done in
ngx_http_process_request() is really good idea.
> + goto fail;
> + }
> +
> + cert = SSL_get_peer_certificate(c->ssl->connection);
> +
> + if (cert == NULL) {
> + ngx_log_error(NGX_LOG_INFO, c->log, 0,
> + "upstream sent no required SSL certificate");
The "required" is probably not needed. And NGX_LOG_INFO logging
level looks very wrong - while it's used by
ngx_http_process_request(), it's used in a situation which may be
easily triggered by broken/malicious clients, so the "info" level
is appropiate. No certificate from an upstream server deserves at
least "error" level (which is already used in your patch by
previous error message).
> + goto fail;
> + }
> +
> + X509_free(cert);
> + }
> +
> if (u->conf->ssl_session_reuse) {
> u->peer.save_session(&u->peer, u->peer.data);
> }
One more relatively major point: certificate checking seems to
lack any peer name validation. Without it, any certificate issued
by a trusted certificate authority can be used, making it
impossible to use certificate verification to prevent MITM if you
don't control trusted CAs.
I tend to think it's required for initial proxy certificate
verification. Though probably there should be a directive to
switch the off, like in Apache, see
http://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslproxycheckpeername.
Additionally, it might be good idea to introduce an ssl_crl
counterpart for proxy.
> @@ -1332,13 +1350,21 @@ ngx_http_upstream_ssl_handshake(ngx_conn
> c->write->handler = ngx_http_upstream_handler;
> c->read->handler = ngx_http_upstream_handler;
>
> + c = r->connection;
> +
> ngx_http_upstream_send_request(r, u);
>
> + ngx_http_run_posted_requests(c);
> +
> return;
> }
>
> +fail:
> + c = r->connection;
> +
> ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
>
> + ngx_http_run_posted_requests(c);
> }
Nitpicking: I think there should be empty line after "fail:".
BTW, you may want to build patches against mercurial repo, it
already has the posted requests code here. See
http://nginx.org/en/docs/contributing_changes.html
for basic tips.
[...]
--
Maxim Dounin
http://nginx.org/en/donation.html
More information about the nginx-devel
mailing list