nghttpx: Add log variables related to SSL/TLS connection
This commit add following 3 log variables to SSL/TLS connection: $ssl_cipher, $ssl_protocol, $ssl_session_id. If no information is available for them, '-' is produced for each.
This commit is contained in:
parent
b06e339dbb
commit
197493afd4
|
@ -269,27 +269,6 @@ void Client::report_progress() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
const char *get_tls_protocol(SSL *ssl) {
|
|
||||||
auto session = SSL_get_session(ssl);
|
|
||||||
|
|
||||||
switch (session->ssl_version) {
|
|
||||||
case SSL2_VERSION:
|
|
||||||
return "SSLv2";
|
|
||||||
case SSL3_VERSION:
|
|
||||||
return "SSLv3";
|
|
||||||
case TLS1_2_VERSION:
|
|
||||||
return "TLSv1.2";
|
|
||||||
case TLS1_1_VERSION:
|
|
||||||
return "TLSv1.1";
|
|
||||||
case TLS1_VERSION:
|
|
||||||
return "TLSv1";
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void print_server_tmp_key(SSL *ssl) {
|
void print_server_tmp_key(SSL *ssl) {
|
||||||
// libressl does not have SSL_get_server_tmp_key
|
// libressl does not have SSL_get_server_tmp_key
|
||||||
|
@ -333,7 +312,7 @@ void Client::report_tls_info() {
|
||||||
if (worker->id == 0 && !worker->tls_info_report_done) {
|
if (worker->id == 0 && !worker->tls_info_report_done) {
|
||||||
worker->tls_info_report_done = true;
|
worker->tls_info_report_done = true;
|
||||||
auto cipher = SSL_get_current_cipher(ssl);
|
auto cipher = SSL_get_current_cipher(ssl);
|
||||||
std::cout << "Protocol: " << get_tls_protocol(ssl) << "\n"
|
std::cout << "Protocol: " << ssl::get_tls_protocol(ssl) << "\n"
|
||||||
<< "Cipher: " << SSL_CIPHER_get_name(cipher) << std::endl;
|
<< "Cipher: " << SSL_CIPHER_get_name(cipher) << std::endl;
|
||||||
print_server_tmp_key(ssl);
|
print_server_tmp_key(ssl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1345,6 +1345,9 @@ Logging:
|
||||||
* $alpn: ALPN identifier of the protocol which generates
|
* $alpn: ALPN identifier of the protocol which generates
|
||||||
the response. For HTTP/1, ALPN is always http/1.1,
|
the response. For HTTP/1, ALPN is always http/1.1,
|
||||||
regardless of minor version.
|
regardless of minor version.
|
||||||
|
* $ssl_cipher: cipher used for SSL/TLS connection.
|
||||||
|
* $ssl_protocol: protocol for SSL/TLS connection.
|
||||||
|
* $ssl_session_id: session ID for SSL/TLS connection.
|
||||||
|
|
||||||
Default: )" << DEFAULT_ACCESSLOG_FORMAT << R"(
|
Default: )" << DEFAULT_ACCESSLOG_FORMAT << R"(
|
||||||
--errorlog-file=<PATH>
|
--errorlog-file=<PATH>
|
||||||
|
|
|
@ -733,6 +733,8 @@ std::string construct_absolute_request_uri(Downstream *downstream) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ClientHandler::write_accesslog(Downstream *downstream) {
|
void ClientHandler::write_accesslog(Downstream *downstream) {
|
||||||
|
nghttp2::ssl::TLSSessionInfo tls_info;
|
||||||
|
|
||||||
upstream_accesslog(
|
upstream_accesslog(
|
||||||
get_config()->accesslog_format,
|
get_config()->accesslog_format,
|
||||||
LogSpec{
|
LogSpec{
|
||||||
|
@ -747,6 +749,7 @@ void ClientHandler::write_accesslog(Downstream *downstream) {
|
||||||
: downstream->get_request_path().c_str(),
|
: downstream->get_request_path().c_str(),
|
||||||
|
|
||||||
alpn_.c_str(),
|
alpn_.c_str(),
|
||||||
|
nghttp2::ssl::get_tls_session_info(&tls_info, conn_.tls.ssl),
|
||||||
|
|
||||||
std::chrono::system_clock::now(), // time_now
|
std::chrono::system_clock::now(), // time_now
|
||||||
downstream->get_request_start_time(), // request_start_time
|
downstream->get_request_start_time(), // request_start_time
|
||||||
|
@ -763,13 +766,16 @@ void ClientHandler::write_accesslog(int major, int minor, unsigned int status,
|
||||||
int64_t body_bytes_sent) {
|
int64_t body_bytes_sent) {
|
||||||
auto time_now = std::chrono::system_clock::now();
|
auto time_now = std::chrono::system_clock::now();
|
||||||
auto highres_now = std::chrono::high_resolution_clock::now();
|
auto highres_now = std::chrono::high_resolution_clock::now();
|
||||||
|
nghttp2::ssl::TLSSessionInfo tls_info;
|
||||||
|
|
||||||
upstream_accesslog(get_config()->accesslog_format,
|
upstream_accesslog(get_config()->accesslog_format,
|
||||||
LogSpec{
|
LogSpec{
|
||||||
nullptr, ipaddr_.c_str(),
|
nullptr, ipaddr_.c_str(),
|
||||||
"-", // method
|
"-", // method
|
||||||
"-", // path,
|
"-", // path,
|
||||||
alpn_.c_str(), time_now,
|
alpn_.c_str(), nghttp2::ssl::get_tls_session_info(
|
||||||
|
&tls_info, conn_.tls.ssl),
|
||||||
|
time_now,
|
||||||
highres_now, // request_start_time TODO is
|
highres_now, // request_start_time TODO is
|
||||||
// there a better value?
|
// there a better value?
|
||||||
highres_now, // request_end_time
|
highres_now, // request_end_time
|
||||||
|
|
|
@ -383,6 +383,12 @@ std::vector<LogFragment> parse_log_format(const char *optarg) {
|
||||||
type = SHRPX_LOGF_PID;
|
type = SHRPX_LOGF_PID;
|
||||||
} else if (util::strieq_l("$alpn", var_start, varlen)) {
|
} else if (util::strieq_l("$alpn", var_start, varlen)) {
|
||||||
type = SHRPX_LOGF_ALPN;
|
type = SHRPX_LOGF_ALPN;
|
||||||
|
} else if (util::strieq_l("$ssl_cipher", var_start, varlen)) {
|
||||||
|
type = SHRPX_LOGF_SSL_CIPHER;
|
||||||
|
} else if (util::strieq_l("$ssl_protocol", var_start, varlen)) {
|
||||||
|
type = SHRPX_LOGF_SSL_PROTOCOL;
|
||||||
|
} else if (util::strieq_l("$ssl_session_id", var_start, varlen)) {
|
||||||
|
type = SHRPX_LOGF_SSL_SESSION_ID;
|
||||||
} else {
|
} else {
|
||||||
LOG(WARN) << "Unrecognized log format variable: "
|
LOG(WARN) << "Unrecognized log format variable: "
|
||||||
<< std::string(var_start, varlen);
|
<< std::string(var_start, varlen);
|
||||||
|
|
|
@ -164,6 +164,24 @@ std::pair<OutputIterator, size_t> copy(const char *src, size_t avail,
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const char LOWER_XDIGITS[] = "0123456789abcdef";
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template <typename OutputIterator>
|
||||||
|
std::pair<OutputIterator, size_t> copy_hex_low(const uint8_t *src,
|
||||||
|
size_t srclen, size_t avail,
|
||||||
|
OutputIterator oitr) {
|
||||||
|
auto nwrite = std::min(srclen * 2, avail) / 2;
|
||||||
|
for (auto i = 0; i < nwrite; ++i) {
|
||||||
|
*oitr++ = LOWER_XDIGITS[src[i] >> 4];
|
||||||
|
*oitr++ = LOWER_XDIGITS[src[i] & 0xf];
|
||||||
|
}
|
||||||
|
return std::make_pair(oitr, avail - nwrite);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void upstream_accesslog(const std::vector<LogFragment> &lfv,
|
void upstream_accesslog(const std::vector<LogFragment> &lfv,
|
||||||
const LogSpec &lgsp) {
|
const LogSpec &lgsp) {
|
||||||
auto lgconf = log_config();
|
auto lgconf = log_config();
|
||||||
|
@ -253,6 +271,29 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
|
||||||
case SHRPX_LOGF_ALPN:
|
case SHRPX_LOGF_ALPN:
|
||||||
std::tie(p, avail) = copy(lgsp.alpn, avail, p);
|
std::tie(p, avail) = copy(lgsp.alpn, avail, p);
|
||||||
break;
|
break;
|
||||||
|
case SHRPX_LOGF_SSL_CIPHER:
|
||||||
|
if (!lgsp.tls_info) {
|
||||||
|
std::tie(p, avail) = copy("-", avail, p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::tie(p, avail) = copy(lgsp.tls_info->cipher, avail, p);
|
||||||
|
break;
|
||||||
|
case SHRPX_LOGF_SSL_PROTOCOL:
|
||||||
|
if (!lgsp.tls_info) {
|
||||||
|
std::tie(p, avail) = copy("-", avail, p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::tie(p, avail) = copy(lgsp.tls_info->protocol, avail, p);
|
||||||
|
break;
|
||||||
|
case SHRPX_LOGF_SSL_SESSION_ID:
|
||||||
|
if (!lgsp.tls_info || lgsp.tls_info->session_id_length == 0) {
|
||||||
|
std::tie(p, avail) = copy("-", avail, p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::tie(p, avail) =
|
||||||
|
copy_hex_low(lgsp.tls_info->session_id,
|
||||||
|
lgsp.tls_info->session_id_length, avail, p);
|
||||||
|
break;
|
||||||
case SHRPX_LOGF_NONE:
|
case SHRPX_LOGF_NONE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#include "shrpx_log_config.h"
|
#include "shrpx_log_config.h"
|
||||||
|
#include "ssl.h"
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
|
@ -115,6 +116,9 @@ enum LogFragmentType {
|
||||||
SHRPX_LOGF_REQUEST_TIME,
|
SHRPX_LOGF_REQUEST_TIME,
|
||||||
SHRPX_LOGF_PID,
|
SHRPX_LOGF_PID,
|
||||||
SHRPX_LOGF_ALPN,
|
SHRPX_LOGF_ALPN,
|
||||||
|
SHRPX_LOGF_SSL_CIPHER,
|
||||||
|
SHRPX_LOGF_SSL_PROTOCOL,
|
||||||
|
SHRPX_LOGF_SSL_SESSION_ID,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LogFragment {
|
struct LogFragment {
|
||||||
|
@ -128,6 +132,7 @@ struct LogSpec {
|
||||||
const char *method;
|
const char *method;
|
||||||
const char *path;
|
const char *path;
|
||||||
const char *alpn;
|
const char *alpn;
|
||||||
|
const nghttp2::ssl::TLSSessionInfo *tls_info;
|
||||||
std::chrono::system_clock::time_point time_now;
|
std::chrono::system_clock::time_point time_now;
|
||||||
std::chrono::high_resolution_clock::time_point request_start_time;
|
std::chrono::high_resolution_clock::time_point request_start_time;
|
||||||
std::chrono::high_resolution_clock::time_point request_end_time;
|
std::chrono::high_resolution_clock::time_point request_end_time;
|
||||||
|
|
40
src/ssl.cc
40
src/ssl.cc
|
@ -78,6 +78,46 @@ LibsslGlobalLock::LibsslGlobalLock() {
|
||||||
|
|
||||||
LibsslGlobalLock::~LibsslGlobalLock() { ssl_global_locks.clear(); }
|
LibsslGlobalLock::~LibsslGlobalLock() { ssl_global_locks.clear(); }
|
||||||
|
|
||||||
|
const char *get_tls_protocol(SSL *ssl) {
|
||||||
|
auto session = SSL_get_session(ssl);
|
||||||
|
if (!session) {
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (session->ssl_version) {
|
||||||
|
case SSL2_VERSION:
|
||||||
|
return "SSLv2";
|
||||||
|
case SSL3_VERSION:
|
||||||
|
return "SSLv3";
|
||||||
|
case TLS1_2_VERSION:
|
||||||
|
return "TLSv1.2";
|
||||||
|
case TLS1_1_VERSION:
|
||||||
|
return "TLSv1.1";
|
||||||
|
case TLS1_VERSION:
|
||||||
|
return "TLSv1";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TLSSessionInfo *get_tls_session_info(TLSSessionInfo *tls_info, SSL *ssl) {
|
||||||
|
if (!ssl) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto session = SSL_get_session(ssl);
|
||||||
|
if (!session) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls_info->cipher = SSL_get_cipher_name(ssl);
|
||||||
|
tls_info->protocol = get_tls_protocol(ssl);
|
||||||
|
tls_info->session_id = session->session_id;
|
||||||
|
tls_info->session_id_length = session->session_id_length;
|
||||||
|
|
||||||
|
return tls_info;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ssl
|
} // namespace ssl
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
20
src/ssl.h
20
src/ssl.h
|
@ -22,8 +22,15 @@
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
#ifndef SSL_H
|
||||||
|
#define SSL_H
|
||||||
|
|
||||||
#include "nghttp2_config.h"
|
#include "nghttp2_config.h"
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
namespace ssl {
|
namespace ssl {
|
||||||
|
@ -40,6 +47,19 @@ public:
|
||||||
|
|
||||||
extern const char *const DEFAULT_CIPHER_LIST;
|
extern const char *const DEFAULT_CIPHER_LIST;
|
||||||
|
|
||||||
|
const char *get_tls_protocol(SSL *ssl);
|
||||||
|
|
||||||
|
struct TLSSessionInfo {
|
||||||
|
const char *cipher;
|
||||||
|
const char *protocol;
|
||||||
|
const uint8_t *session_id;
|
||||||
|
size_t session_id_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
TLSSessionInfo *get_tls_session_info(TLSSessionInfo *tls_info, SSL *ssl);
|
||||||
|
|
||||||
} // namespace ssl
|
} // namespace ssl
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
||||||
|
#endif // SSL_H
|
||||||
|
|
Loading…
Reference in New Issue