MEDIUM: ssl: new sample fetch method to get curve name

Adds a new sample fetch method to get the curve name used in the
key agreement to enable better observability. In OpenSSLv3, the function
`SSL_get_negotiated_group` returns the NID of the curve and from the NID,
we get the curve name by passing the NID to OBJ_nid2sn. This was not
available in v1.1.1. SSL_get_curve_name(), which returns the curve name
directly was merged into OpenSSL master branch last week but will be available
only in its next release.
This commit is contained in:
Mariam John 2023-07-17 08:22:59 -05:00 committed by William Lallemand
parent e3e4e00063
commit 00b7b49a46
3 changed files with 107 additions and 0 deletions

View File

@ -20722,6 +20722,11 @@ ssl_bc_client_random : binary
sent using ephemeral ciphers. This requires OpenSSL >= 1.1.0, or BoringSSL. sent using ephemeral ciphers. This requires OpenSSL >= 1.1.0, or BoringSSL.
It can be used in a tcp-check or an http-check ruleset. It can be used in a tcp-check or an http-check ruleset.
ssl_bc_curve : string
Returns the name of the curve used in the key agreement when the outgoing
connection was made over an SSL/TLS transport layer. This requires
OpenSSL >= 3.0.0.
ssl_bc_err : integer ssl_bc_err : integer
When the outgoing connection was made over an SSL/TLS transport layer, When the outgoing connection was made over an SSL/TLS transport layer,
returns the ID of the last error of the first error stack raised on the returns the ID of the last error of the first error stack raised on the
@ -21057,6 +21062,11 @@ ssl_fc_cipherlist_xxh : integer
"tune.ssl.capture-buffer-size" is set greater than 0, however the hash take "tune.ssl.capture-buffer-size" is set greater than 0, however the hash take
into account all the data of the cipher list. into account all the data of the cipher list.
ssl_fc_curve : string
Returns the name of the curve used in the key agreement when the incoming
connection was made over an SSL/TLS transport layer. This requires
OpenSSL >= 3.0.0.
ssl_fc_ecformats_bin : binary ssl_fc_ecformats_bin : binary
Return the binary form of the client hello supported elliptic curve point Return the binary form of the client hello supported elliptic curve point
formats. The maximum returned value length is limited by the shared capture formats. The maximum returned value length is limited by the shared capture

View File

@ -0,0 +1,51 @@
#REGTEST_TYPE=devel
varnishtest "Test the ssl_fc_curve/ssl_bc_curve sample fetches"
feature cmd "$HAPROXY_PROGRAM -cc 'feature(OPENSSL) && ssllib_name_startswith(OpenSSL) && openssl_version_atleast(3.0.0)'"
feature ignore_unknown_macro
server s1 -repeat 3 {
rxreq
txresp
} -start
haproxy h1 -conf {
global
tune.ssl.default-dh-param 2048
tune.ssl.capture-buffer-size 1
crt-base ${testdir}
defaults
mode http
option httplog
log stderr local0 debug err
option logasap
timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
listen clear-lst
bind "fd@${clearlst}"
balance roundrobin
http-response add-header x-ssl-bc-curve-name %[ssl_bc_curve]
server s1 "${tmpdir}/ssl.sock" ssl verify none crt ${testdir}/client.ecdsa.pem
listen ssl-lst
mode http
http-response add-header x-ssl-fc-curve-name %[ssl_fc_curve]
bind "${tmpdir}/ssl.sock" ssl crt ${testdir}/common.pem ca-file ${testdir}/set_cafile_rootCA.crt verify optional curves X25519:P-256:P-384
server s1 ${s1_addr}:${s1_port}
} -start
client c1 -connect ${h1_clearlst_sock} {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-ssl-fc-curve-name == "X25519"
expect resp.http.x-ssl-bc-curve-name == "X25519"
} -run

View File

@ -1304,6 +1304,46 @@ smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const ch
return 1; return 1;
} }
/*
* string, returns the EC curve used for key agreement on the
* front and backend connection.
*
* The function to get the curve name (SSL_get_negotiated_group) is only available
* in OpenSSLv3 onwards and not for previous versions.
*/
#if (HA_OPENSSL_VERSION_NUMBER >= 0x3000000fL)
static int
smp_fetch_ssl_fc_ec(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct connection *conn;
SSL *ssl;
int nid;
if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL;
else
conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
smp->strm ? sc_conn(smp->strm->scb) : NULL;
ssl = ssl_sock_get_ssl_object(conn);
if (!ssl)
return 0;
nid = SSL_get_negotiated_group(ssl);
if (!nid)
return 0;
smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
if (!smp->data.u.str.area)
return 0;
smp->data.type = SMP_T_STR;
smp->flags |= SMP_F_VOL_SESS | SMP_F_CONST;
smp->data.u.str.data = strlen(smp->data.u.str.area);
return 1;
}
#endif
/* string, returns the used cipher if front conn. transport layer is SSL. /* string, returns the used cipher if front conn. transport layer is SSL.
* This function is also usable on backend conn if the fetch keyword 5th * This function is also usable on backend conn if the fetch keyword 5th
* char is 'b'. * char is 'b'.
@ -2174,6 +2214,9 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
{ "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV }, { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
#endif #endif
{ "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV }, { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
#if (HA_OPENSSL_VERSION_NUMBER >= 0x3000000fL)
{ "ssl_bc_curve", smp_fetch_ssl_fc_ec, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
#endif
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) #if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
{ "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV }, { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
#endif #endif
@ -2223,6 +2266,9 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
{ "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
{ "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI }, { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
{ "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
#if (HA_OPENSSL_VERSION_NUMBER >= 0x3000000fL)
{ "ssl_fc_curve", smp_fetch_ssl_fc_ec, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
#endif
{ "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
{ "ssl_fc_has_early", smp_fetch_ssl_fc_has_early, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_fc_has_early", smp_fetch_ssl_fc_has_early, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
{ "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },