Mercurial > hg > nginx
view src/core/ngx_resolver.h @ 7360:8f25a44d9add
SSL: logging level of "no suitable key share".
The "no suitable key share" errors are reported by OpenSSL 1.1.1 when
using TLSv1.3 if there are no shared groups (that is, elliptic curves).
In particular, it is easy enough to trigger by using only a single
curve in ssl_ecdh_curve:
ssl_ecdh_curve secp384r1;
and using a different curve in the client:
openssl s_client -connect 127.0.0.1:443 -curves prime256v1
On the client side it is seen as "sslv3 alert handshake failure",
"SSL alert number 40":
0:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:ssl/record/rec_layer_s3.c:1528:SSL alert number 40
It can be also triggered with default ssl_ecdh_curve by using a curve
which is not in the default list (X25519, prime256v1, X448, secp521r1,
secp384r1):
openssl s_client -connect 127.0.0.1:8443 -curves brainpoolP512r1
Given that many clients hardcode prime256v1, these errors might become
a common problem with TLSv1.3 if ssl_ecdh_curve is redefined. Previously
this resulted in not using ECDH with such clients, but with TLSv1.3 it
is no longer possible and will result in a handshake failure.
The SSL_R_NO_SHARED_GROUP error is what BoringSSL returns in the same
situation.
Seen at:
https://serverfault.com/questions/932102/nginx-ssl-handshake-error-no-suitable-key-share
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 25 Sep 2018 13:59:53 +0300 |
parents | 70e65bf8dfd7 |
children | 2a77754cd9fe |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include <ngx_core.h> #ifndef _NGX_RESOLVER_H_INCLUDED_ #define _NGX_RESOLVER_H_INCLUDED_ #define NGX_RESOLVE_A 1 #define NGX_RESOLVE_CNAME 5 #define NGX_RESOLVE_PTR 12 #define NGX_RESOLVE_MX 15 #define NGX_RESOLVE_TXT 16 #if (NGX_HAVE_INET6) #define NGX_RESOLVE_AAAA 28 #endif #define NGX_RESOLVE_SRV 33 #define NGX_RESOLVE_DNAME 39 #define NGX_RESOLVE_FORMERR 1 #define NGX_RESOLVE_SERVFAIL 2 #define NGX_RESOLVE_NXDOMAIN 3 #define NGX_RESOLVE_NOTIMP 4 #define NGX_RESOLVE_REFUSED 5 #define NGX_RESOLVE_TIMEDOUT NGX_ETIMEDOUT #define NGX_NO_RESOLVER (void *) -1 #define NGX_RESOLVER_MAX_RECURSION 50 typedef struct ngx_resolver_s ngx_resolver_t; typedef struct { ngx_connection_t *udp; ngx_connection_t *tcp; struct sockaddr *sockaddr; socklen_t socklen; ngx_str_t server; ngx_log_t log; ngx_buf_t *read_buf; ngx_buf_t *write_buf; ngx_resolver_t *resolver; } ngx_resolver_connection_t; typedef struct ngx_resolver_ctx_s ngx_resolver_ctx_t; typedef void (*ngx_resolver_handler_pt)(ngx_resolver_ctx_t *ctx); typedef struct { struct sockaddr *sockaddr; socklen_t socklen; ngx_str_t name; u_short priority; u_short weight; } ngx_resolver_addr_t; typedef struct { ngx_str_t name; u_short priority; u_short weight; u_short port; } ngx_resolver_srv_t; typedef struct { ngx_str_t name; u_short priority; u_short weight; u_short port; ngx_resolver_ctx_t *ctx; ngx_int_t state; ngx_uint_t naddrs; ngx_addr_t *addrs; } ngx_resolver_srv_name_t; typedef struct { ngx_rbtree_node_t node; ngx_queue_t queue; /* PTR: resolved name, A: name to resolve */ u_char *name; #if (NGX_HAVE_INET6) /* PTR: IPv6 address to resolve (IPv4 address is in rbtree node key) */ struct in6_addr addr6; #endif u_short nlen; u_short qlen; u_char *query; #if (NGX_HAVE_INET6) u_char *query6; #endif union { in_addr_t addr; in_addr_t *addrs; u_char *cname; ngx_resolver_srv_t *srvs; } u; u_char code; u_short naddrs; u_short nsrvs; u_short cnlen; #if (NGX_HAVE_INET6) union { struct in6_addr addr6; struct in6_addr *addrs6; } u6; u_short naddrs6; #endif time_t expire; time_t valid; uint32_t ttl; unsigned tcp:1; #if (NGX_HAVE_INET6) unsigned tcp6:1; #endif ngx_uint_t last_connection; ngx_resolver_ctx_t *waiting; } ngx_resolver_node_t; struct ngx_resolver_s { /* has to be pointer because of "incomplete type" */ ngx_event_t *event; void *dummy; ngx_log_t *log; /* event ident must be after 3 pointers as in ngx_connection_t */ ngx_int_t ident; /* simple round robin DNS peers balancer */ ngx_array_t connections; ngx_uint_t last_connection; ngx_rbtree_t name_rbtree; ngx_rbtree_node_t name_sentinel; ngx_rbtree_t srv_rbtree; ngx_rbtree_node_t srv_sentinel; ngx_rbtree_t addr_rbtree; ngx_rbtree_node_t addr_sentinel; ngx_queue_t name_resend_queue; ngx_queue_t srv_resend_queue; ngx_queue_t addr_resend_queue; ngx_queue_t name_expire_queue; ngx_queue_t srv_expire_queue; ngx_queue_t addr_expire_queue; #if (NGX_HAVE_INET6) ngx_uint_t ipv6; /* unsigned ipv6:1; */ ngx_rbtree_t addr6_rbtree; ngx_rbtree_node_t addr6_sentinel; ngx_queue_t addr6_resend_queue; ngx_queue_t addr6_expire_queue; #endif time_t resend_timeout; time_t tcp_timeout; time_t expire; time_t valid; ngx_uint_t log_level; }; struct ngx_resolver_ctx_s { ngx_resolver_ctx_t *next; ngx_resolver_t *resolver; ngx_resolver_node_t *node; /* event ident must be after 3 pointers as in ngx_connection_t */ ngx_int_t ident; ngx_int_t state; ngx_str_t name; ngx_str_t service; time_t valid; ngx_uint_t naddrs; ngx_resolver_addr_t *addrs; ngx_resolver_addr_t addr; struct sockaddr_in sin; ngx_uint_t count; ngx_uint_t nsrvs; ngx_resolver_srv_name_t *srvs; ngx_resolver_handler_pt handler; void *data; ngx_msec_t timeout; unsigned quick:1; unsigned async:1; unsigned cancelable:1; ngx_uint_t recursion; ngx_event_t *event; }; ngx_resolver_t *ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n); ngx_resolver_ctx_t *ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp); ngx_int_t ngx_resolve_name(ngx_resolver_ctx_t *ctx); void ngx_resolve_name_done(ngx_resolver_ctx_t *ctx); ngx_int_t ngx_resolve_addr(ngx_resolver_ctx_t *ctx); void ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx); char *ngx_resolver_strerror(ngx_int_t err); #endif /* _NGX_RESOLVER_H_INCLUDED_ */