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"
diff --git a/doc/configuration.txt b/doc/configuration.txt
index aee1d90..208c432 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -9716,7 +9716,7 @@
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 @@
| | %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 @@
| | %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 8246b35..5f83dbc 100644
--- a/include/proto/ssl_sock.h
+++ b/include/proto/ssl_sock.h
@@ -35,6 +35,8 @@
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 70dc9fa..8c28310 100644
--- a/include/types/log.h
+++ b/include/types/log.h
@@ -91,6 +91,8 @@
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 15ba27b..130c378 100644
--- a/src/log.c
+++ b/src/log.c
@@ -113,6 +113,8 @@
{ "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 @@
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 6c9eae4..9aed915 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -1053,6 +1053,22 @@
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 */