From ffc3fcd6dadbf19c3def3f8aa27e78cf2481c347 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 12 Oct 2012 20:17:54 +0200 Subject: [PATCH] MEDIUM: log: report SSL ciphers and version in logs using logformat %sslc/%sslv These two new log-format tags report the SSL protocol version (%sslv) and the SSL ciphers (%sslc) used for the connection with the client. For instance, to append these information just after the client's IP/port address information on an HTTP log line, use the following configuration : log-format %Ci:%Cp\ %sslv:%sslc\ [%t]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %st\ %B\ %cc\ \ %cs\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ %{+Q}r It will report a line such as the following one : Oct 12 20:47:30 haproxy[9643]: 127.0.0.1:43602 TLSv1:AES-SHA [12/Oct/2012:20:47:30.303] stick2~ stick2/s1 7/0/12/0/19 200 145 - - ---- 0/0/0/0/0 0/0 "GET /?t=0 HTTP/1.0" --- doc/configuration.txt | 30 ++++++++++++++++-------------- include/proto/ssl_sock.h | 2 ++ include/types/log.h | 2 ++ src/log.c | 24 ++++++++++++++++++++++++ src/ssl_sock.c | 16 ++++++++++++++++ 5 files changed, 60 insertions(+), 14 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index aee1d904b0..208c43221e 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -9716,7 +9716,7 @@ and the default TCP format is defined this way : Please refer to the table below for currently defined variables : +---+------+-----------------------------------------------+-------------+ - | H | var | field name (8.2.2 and 8.2.3 for description) | type | + | R | var | field name (8.2.2 and 8.2.3 for description) | type | +---+------+-----------------------------------------------+-------------+ | | %o | special variable, apply flags on all next var | | +---+------+-----------------------------------------------+-------------+ @@ -9733,8 +9733,8 @@ Please refer to the table below for currently defined variables : | | %Sp | server_port | numeric | | | %T | gmt_date_time | date | | | %Tc | Tc | numeric | - | * | %Tq | Tq | numeric | - | * | %Tr | Tr | numeric | + | H | %Tq | Tq | numeric | + | H | %Tr | Tr | numeric | | | %Ts | timestamp | numeric | | | %Tt | Tt | numeric | | | %Tw | Tw | numeric | @@ -9742,30 +9742,32 @@ Please refer to the table below for currently defined variables : | | %b | backend_name | string | | | %bc | beconn | numeric | | | %bq | backend_queue | numeric | - | * | %cc | captured_request_cookie | string | - | * | %rt | http_request_counter | numeric | - | * | %cs | captured_response_cookie | string | + | H | %cc | captured_request_cookie | string | + | H | %rt | http_request_counter | numeric | + | H | %cs | captured_response_cookie | string | | | %f | frontend_name | string | | | %ft | frontend_name_transport ('~' suffix for SSL) | string | | | %fc | feconn | numeric | - | * | %hr | captured_request_headers default style | string | - | * | %hrl | captured_request_headers CLF style | string list | - | * | %hs | captured_response_headers default style | string | - | * | %hsl | captured_response_headers CLF style | string list | + | H | %hr | captured_request_headers default style | string | + | H | %hrl | captured_request_headers CLF style | string list | + | H | %hs | captured_response_headers default style | string | + | H | %hsl | captured_response_headers CLF style | string list | | | %ms | accept date milliseconds | numeric | | | %pid | PID | numeric | - | * | %r | http_request | string | + | H | %r | http_request | string | | | %rc | retries | numeric | | | %s | server_name | string | | | %sc | srv_conn | numeric | | | %sq | srv_queue | numeric | - | * | %st | status_code | numeric | + | S | %sslc| ssl_ciphers (ex: AES-SHA) | string | + | S | %sslv| ssl_version (ex: TLSv1) | string | + | H | %st | status_code | numeric | | | %t | date_time | date | | | %ts | termination_state | string | - | * | %tsc | termination_state with cookie status | string | + | H | %tsc | termination_state with cookie status | string | +---+------+-----------------------------------------------+-------------+ -*: mode http only + R = Restrictions : H = mode http only ; S = SSL only 8.3. Advanced logging options ----------------------------- diff --git a/include/proto/ssl_sock.h b/include/proto/ssl_sock.h index 8246b35630..5f83dbc70d 100644 --- a/include/proto/ssl_sock.h +++ b/include/proto/ssl_sock.h @@ -35,6 +35,8 @@ void ssl_sock_free_certs(struct bind_conf *bind_conf); int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px); int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *px); void ssl_sock_free_all_ctx(struct bind_conf *bind_conf); +const char *ssl_sock_get_cipher_name(struct connection *conn); +const char *ssl_sock_get_proto_version(struct connection *conn); #endif /* _PROTO_SSL_SOCK_H */ diff --git a/include/types/log.h b/include/types/log.h index 70dc9faf5a..8c28310d04 100644 --- a/include/types/log.h +++ b/include/types/log.h @@ -91,6 +91,8 @@ enum { LOG_FMT_REQ, LOG_FMT_HOSTNAME, LOG_FMT_UNIQUEID, + LOG_FMT_SSL_CIPHER, + LOG_FMT_SSL_VERSION, }; /* enum for parse_logformat */ diff --git a/src/log.c b/src/log.c index 15ba27bfac..130c378ca7 100644 --- a/src/log.c +++ b/src/log.c @@ -113,6 +113,8 @@ static const struct logformat_type logformat_keywords[] = { { "rt", LOG_FMT_COUNTER, PR_MODE_HTTP, LW_REQ, NULL }, /* HTTP request counter */ { "H", LOG_FMT_HOSTNAME, PR_MODE_TCP, LW_INIT, NULL }, /* Hostname */ { "ID", LOG_FMT_UNIQUEID, PR_MODE_HTTP, LW_BYTES, NULL }, /* Unique ID */ + { "sslc", LOG_FMT_SSL_CIPHER, PR_MODE_TCP, LW_XPRT, NULL }, /* client-side SSL ciphers */ + { "sslv", LOG_FMT_SSL_VERSION, PR_MODE_TCP, LW_XPRT, NULL }, /* client-side SSL protocol version */ { 0, 0, 0, 0, NULL } }; @@ -1001,7 +1003,29 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis LOGCHAR('"'); last_isspace = 0; break; +#ifdef USE_OPENSSL + case LOG_FMT_SSL_CIPHER: // %sslc + src = NULL; + if (s->listener->xprt == &ssl_sock) + src = ssl_sock_get_cipher_name(&s->si[0].conn); + ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp); + if (ret == NULL) + goto out; + tmplog = ret; + last_isspace = 0; + break; + case LOG_FMT_SSL_VERSION: // %sslv + src = NULL; + if (s->listener->xprt == &ssl_sock) + src = ssl_sock_get_proto_version(&s->si[0].conn); + ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp); + if (ret == NULL) + goto out; + tmplog = ret; + last_isspace = 0; + break; +#endif case LOG_FMT_BACKEND: // %b src = be->id; ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp); diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 6c9eae4fe6..9aed915711 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -1053,6 +1053,22 @@ static void ssl_sock_shutw(struct connection *conn, int clean) SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN); } +/* used for logging, may be changed for a sample fetch later */ +const char *ssl_sock_get_cipher_name(struct connection *conn) +{ + if (!conn->xprt && !conn->xprt_ctx) + return NULL; + return SSL_get_cipher_name(conn->xprt_ctx); +} + +/* used for logging, may be changed for a sample fetch later */ +const char *ssl_sock_get_proto_version(struct connection *conn) +{ + if (!conn->xprt && !conn->xprt_ctx) + return NULL; + return SSL_get_version(conn->xprt_ctx); +} + /***** Below are some sample fetching functions for ACL/patterns *****/ /* boolean, returns true if client cert was present */