diff --git a/doc/reference/commands/traffic_line.en.rst b/doc/reference/commands/traffic_line.en.rst index aed88307d3f..14aaaafcdea 100644 --- a/doc/reference/commands/traffic_line.en.rst +++ b/doc/reference/commands/traffic_line.en.rst @@ -792,6 +792,222 @@ The :option:`traffic_line -r` option accepts the following variable names:: proxy.process.cache.volume_0.hdr_marshal_bytes proxy.process.cache.volume_0.gc_bytes_evacuated proxy.process.cache.volume_0.gc_frags_evacuated + proxy.process.https.incoming_requests + proxy.process.https.outgoing_requests + proxy.process.https.current_client_connections + proxy.process.https.total_client_connections + proxy.process.https.current_server_connections + proxy.process.https.total_server_connections + proxy.node.https.user_agent_total_request_bytes + proxy.process.https.user_agent_request_document_total_size + proxy.process.https.user_agent_request_header_total_size + proxy.node.https.user_agent_total_response_bytes + proxy.process.https.user_agent_response_document_total_size + proxy.process.https.user_agent_response_header_total_size + proxy.node.https.origin_server_total_request_bytes + proxy.process.https.origin_server_request_document_total_size + proxy.process.https.origin_server_request_header_total_size + proxy.node.https.origin_server_total_response_bytes + proxy.process.https.origin_server_response_document_total_size + proxy.process.https.origin_server_response_header_total_size + proxy.node.https.user_agent_total_bytes + proxy.node.https.user_agent_total_request_bytes + proxy.node.https.user_agent_total_response_bytes + proxy.node.https.origin_server_total_bytes + proxy.node.https.origin_server_total_request_bytes + proxy.node.https.origin_server_total_response_bytes + proxy.process.ssl.user_agent_other_errors + proxy.process.ssl.user_agent_expired_cert + proxy.process.ssl.user_agent_revoked_cert + proxy.process.ssl.user_agent_unknown_cert + proxy.process.ssl.user_agent_cert_verify_failed + proxy.process.ssl.user_agent_bad_cert + proxy.process.ssl.user_agent_decryption_failed + proxy.process.ssl.user_agent_wrong_version + proxy.process.ssl.user_agent_unknown_ca + proxy.process.ssl.origin_server_other_errors + proxy.process.ssl.origin_server_expired_cert + proxy.process.ssl.origin_server_revoked_cert + proxy.process.ssl.origin_server_unknown_cert + proxy.process.ssl.origin_server_cert_verify_failed + proxy.process.ssl.origin_server_bad_cert + proxy.process.ssl.origin_server_decryption_failed + proxy.process.ssl.origin_server_wrong_version + proxy.process.ssl.origin_server_unknown_ca + proxy.process.ssl.user_agent_sessions + proxy.process.ssl.user_agent_session_hit + proxy.process.ssl.user_agent_session_miss + proxy.process.ssl.user_agent_session_timeout + proxy.process.ssl.cipher.user_agent.{cipherName} + +Statistics Descriptions +======================= + +proxy.process.https.incoming_requests + Total number of inbound https requests. + +proxy.process.https.outgoing_requests + Total number of outbound https requests. + +proxy.process.https.current_client_connections + Current number of https connected clients. + +proxy.process.https.total_client_connections + Total number of inbound https connections. + +proxy.process.https.current_server_connections + Current number of https connected origins. + +proxy.process.https.total_server_connections + Total number of outbound https connections. + +proxy.node.https.user_agent_total_request_bytes + Total number of bytes received from https connected clients. + +proxy.process.https.user_agent_request_document_total_size + Total size of body data received from https connected clients. + +proxy.process.https.user_agent_request_header_total_size + Total size of request headers received from https connected clients. + +proxy.node.https.user_agent_total_response_bytes + Total number of bytes sent to https connected clients. + +proxy.process.https.user_agent_response_document_total_size + Total size of response body data sent to https connected clients. + +proxy.process.https.user_agent_response_header_total_size + Total size of response headers sent to https connected clients. + +proxy.node.https.origin_server_total_request_bytes + Total number of bytes sent to https connected origins. + +proxy.process.https.origin_server_request_document_total_size + Total size of request body data sent to https connected origins. + +proxy.process.https.origin_server_request_header_total_size + Total size of request headers sent to https connected origins. + +proxy.node.https.origin_server_total_response_bytes + Total number of bytes received from https connected origins. + +proxy.process.https.origin_server_response_document_total_size + Total size of response body data from https connected origins. + +proxy.process.https.origin_server_response_header_total_size + Total size of header data from https connected origins. + +proxy.node.https.user_agent_total_bytes + Total bytes transferred to/from https connected clients. + +proxy.node.https.origin_server_total_bytes + Total bytes transferred to/from https connected origins. + +proxy.process.ssl.user_agent_other_errors + Total number of *other* ssl client connection errors (counts ssl + errors that are not captured in other user agent stats below) + +proxy.process.ssl.user_agent_expired_cert + Total number of ssl client connection failures where the cert was + expired. + +proxy.process.ssl.user_agent_revoked_cert + Total number of ssl client connection failures where the cert was + revoked. + +proxy.process.ssl.user_agent_unknown_cert + Total number of ssl client connection failures related to the cert, + but specific error was unknown. + +proxy.process.ssl.user_agent_cert_verify_failed + Total number of ssl client connection failures where cert verification + failed. + +proxy.process.ssl.user_agent_bad_cert + Total number of ssl client connection failures where the cert is bad. + +proxy.process.ssl.user_agent_decryption_failed + Total number of ssl client connection decryption failures (during + negotiation). + +proxy.process.ssl.user_agent_wrong_version + Total number of ssl client connections that provided an invalid protocol + version. + +proxy.process.ssl.user_agent_unknown_ca + Total number of ssl client connection that failed due to unknown ca. + +proxy.process.ssl.origin_server_other_errors + Total number of *other* ssl origin server connection errors (counts ssl + errors that are not captured in other origin server stats below). + +proxy.process.ssl.origin_server_expired_cert + Total number of ssl origin server connection failures where the cert + was expired. + +proxy.process.ssl.origin_server_revoked_cert + Total number of ssl origin server connection failures where the cert + was revoked. + +proxy.process.ssl.origin_server_unknown_cert + Total number of ssl origin server connection failures related to the + cert where specific error was unknown. + +proxy.process.ssl.origin_server_cert_verify_failed + Total number of ssl origin server connection failures where cert + verification failed. + +proxy.process.ssl.origin_server_bad_cert + Total number of ssl origin server connection failures where the cert + is bad. + +proxy.process.ssl.origin_server_decryption_failed + Total number of ssl origin server connection decryption failures + (during negotiation). + +proxy.process.ssl.origin_server_wrong_version + Total number of ssl origin server connections that provided an invalid + protocol version. + +proxy.process.ssl.origin_server_unknown_ca + Total number of ssl origin server connection that failed due to + unknown ca. + +proxy.process.ssl.user_agent_sessions + Total number of ssl/tls sessions created. + +proxy.process.ssl.user_agent_session_hit + Total number of session hits. A previous session was reused which + resulted in an abbreviated ssl client negotiation. + +proxy.process.ssl.user_agent_session_miss + Total number of session misses. The ssl client provided a session id + that was not found in cache and, therefore, could not be used. + +proxy.process.ssl.user_agent_session_timeout + Total number of session timeouts. The ssl client provided a session, but + it could not be used because it was past the session timeout. + +proxy.process.ssl.cipher.user_agent.{cipherName} + Total number of ssl client connections that used cipherName. The list of + cipher stats is dynamic and depends upon the installed ciphers for the + system. Some common cipher stats are: + proxy.process.ssl.cipher.user_agent.ECDHE-RSA-RC4-SHA + proxy.process.ssl.cipher.user_agent.ECDHE-RSA-AES128-SHA256 + proxy.process.ssl.cipher.user_agent.ECDHE-RSA-AES128-GCM-SHA256 + proxy.process.ssl.cipher.user_agent.ECDHE-RSA-AES128-SHA + proxy.process.ssl.cipher.user_agent.RC4-SHA + proxy.process.ssl.cipher.user_agent.RC4-MD5 + proxy.process.ssl.cipher.user_agent.AES128-GCM-SHA256 + proxy.process.ssl.cipher.user_agent.AES128-SHA + There are two ways to get the list of cipher stats: + 1. Run ATS with debug logging and show ssl diags: + CONFIG proxy.config.diags.debug.enabled INT 1 + CONFIG proxy.config.diags.debug.tags STRING ssl.* + View output of traffic.out looking for lines like: + (ssl) Registering ssl cipher stat 'proxy.process.ssl.cipher.user_agent.ECDHE-RSA-AES256-GCM-SHA384' + 2. Run this script (just asks openssl to tell us): + openssl ciphers | awk '{n=split($0,a,":"); for (i = 0; ++i <= n;) print "proxy.process.ssl.cipher.user_agent." a[i];}' Examples ======== diff --git a/iocore/net/P_SSLCertLookup.h b/iocore/net/P_SSLCertLookup.h index dced9092759..763dbff1fd3 100644 --- a/iocore/net/P_SSLCertLookup.h +++ b/iocore/net/P_SSLCertLookup.h @@ -43,6 +43,9 @@ struct SSLCertLookup : public ConfigInfo // Return the last-resort default TLS context if there is no name or address match. SSL_CTX * defaultContext() const { return ssl_default; } + size_t getCtxCount(); + SSL_CTX * getCtx(size_t i); + SSLCertLookup(); virtual ~SSLCertLookup(); }; diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h index fcb0e8c0f69..02d8683d9bf 100644 --- a/iocore/net/P_SSLNetVConnection.h +++ b/iocore/net/P_SSLNetVConnection.h @@ -36,6 +36,7 @@ #include "P_EventSystem.h" #include "P_UnixNetVConnection.h" #include "P_UnixNet.h" +#include "I_RecHttp.h" #include #include @@ -85,6 +86,8 @@ class SSLNetVConnection:public UnixNetVConnection virtual void setSSLClientConnection(bool state) { sslClientConnection = state; + // set attributes to indicate SSL transport + attributes = (state ? HttpProxyPort::TRANSPORT_SSL : HttpProxyPort::TRANSPORT_DEFAULT); }; int sslServerHandShakeEvent(int &err); int sslClientHandShakeEvent(int &err); diff --git a/iocore/net/P_SSLUtils.h b/iocore/net/P_SSLUtils.h index 5ed2d826ec7..d60eb3b4d00 100644 --- a/iocore/net/P_SSLUtils.h +++ b/iocore/net/P_SSLUtils.h @@ -44,6 +44,51 @@ struct SSLConfigParams; struct SSLCertLookup; +class SSLNetVConnection; +struct RecRawStatBlock; + +enum SSL_Stats +{ + ssl_origin_server_expired_cert_stat, + ssl_user_agent_expired_cert_stat, + ssl_origin_server_revoked_cert_stat, + ssl_user_agent_revoked_cert_stat, + ssl_origin_server_unknown_cert_stat, + ssl_user_agent_unknown_cert_stat, + ssl_origin_server_cert_verify_failed_stat, + ssl_user_agent_cert_verify_failed_stat, + ssl_origin_server_bad_cert_stat, + ssl_user_agent_bad_cert_stat, + ssl_origin_server_decryption_failed_stat, + ssl_user_agent_decryption_failed_stat, + ssl_origin_server_wrong_version_stat, + ssl_user_agent_wrong_version_stat, + ssl_origin_server_other_errors_stat, + ssl_user_agent_other_errors_stat, + ssl_origin_server_unknown_ca_stat, + ssl_user_agent_unknown_ca_stat, + ssl_user_agent_sessions_stat, + ssl_user_agent_session_hit_stat, + ssl_user_agent_session_miss_stat, + ssl_user_agent_session_timeout_stat, + + ssl_cipher_stats_start = 100, + ssl_cipher_stats_end = 300, + + Ssl_Stat_Count +}; + +extern RecRawStatBlock *ssl_rsb; + +/* Stats should only be accessed using these macros */ +#define SSL_INCREMENT_DYN_STAT(x) RecIncrRawStat(ssl_rsb, NULL, (int) x, 1) +#define SSL_DECREMENT_DYN_STAT(x) RecIncrRawStat(ssl_rsb, NULL, (int) x, -1) +#define SSL_SET_COUNT_DYN_STAT(x,count) RecSetRawStatCount(ssl_rsb, x, count) +#define SSL_CLEAR_DYN_STAT(x) \ + do { \ + RecSetRawStatSum(ssl_rsb, (x), 0); \ + RecSetRawStatCount(ssl_rsb, (x), 0); \ + } while (0); // Create a default SSL server context. SSL_CTX * SSLDefaultServerContext(); @@ -66,11 +111,11 @@ void SSLInitializeLibrary(); void SSLReleaseContext(SSL_CTX* ctx); // Log an SSL error. -#define SSLError(fmt, ...) SSLDiagnostic(DiagsMakeLocation(), false, fmt, ##__VA_ARGS__) +#define SSLError(vc,fmt, ...) SSLDiagnostic(DiagsMakeLocation(), false, vc, fmt, ##__VA_ARGS__) // Log a SSL diagnostic using the "ssl" diagnostic tag. -#define SSLDebug(fmt, ...) SSLDiagnostic(DiagsMakeLocation(), true, fmt, ##__VA_ARGS__) +#define SSLDebug(vc,fmt, ...) SSLDiagnostic(DiagsMakeLocation(), true, vc, fmt, ##__VA_ARGS__) -void SSLDiagnostic(const SrcLoc& loc, bool debug, const char * fmt, ...) TS_PRINTFLIKE(3, 4); +void SSLDiagnostic(const SrcLoc& loc, bool debug, SSLNetVConnection * vc, const char * fmt, ...) TS_PRINTFLIKE(4, 5); // Return a static string name for a SSL_ERROR constant. const char * SSLErrorName(int ssl_error); diff --git a/iocore/net/SSLCertLookup.cc b/iocore/net/SSLCertLookup.cc index df774181a11..74c437e33b3 100644 --- a/iocore/net/SSLCertLookup.cc +++ b/iocore/net/SSLCertLookup.cc @@ -75,6 +75,8 @@ struct SSLContextStorage bool insert(SSL_CTX * ctx, const char * name); SSL_CTX * lookup(const char * name) const; + size_t getCtxCount() { return this->references.count(); } + SSL_CTX * getCtx(size_t i) { return this->references[i]; } private: struct SSLEntry @@ -141,6 +143,18 @@ SSLCertLookup::insert(SSL_CTX * ctx, const IpEndpoint& address) return this->ssl_storage->insert(ctx, key.get()); } +size_t +SSLCertLookup::getCtxCount() +{ + return ssl_storage->getCtxCount(); +} + +SSL_CTX * +SSLCertLookup::getCtx(size_t i) +{ + return ssl_storage->getCtx(i); +} + struct ats_wildcard_matcher { ats_wildcard_matcher() { diff --git a/iocore/net/SSLNetProcessor.cc b/iocore/net/SSLNetProcessor.cc index 25b4204540c..713705c919d 100644 --- a/iocore/net/SSLNetProcessor.cc +++ b/iocore/net/SSLNetProcessor.cc @@ -62,7 +62,7 @@ SSLNetProcessor::start(int number_of_ssl_threads, size_t stacksize) // initialization hasn't failed already. client_ctx = SSLInitClientContext(params); if (!client_ctx) { - SSLError("Can't initialize the SSL client, HTTPS in remap rules will not function"); + SSLError(NULL,"Can't initialize the SSL client, HTTPS in remap rules will not function"); } if (number_of_ssl_threads < 1) { diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index 9ddc8e9fffe..f6e9e91f601 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -132,7 +132,7 @@ ssl_read_from_net(UnixNetVConnection * vc, EThread * lthread, int64_t &ret) // not EOF event = SSL_READ_ERROR; ret = errno; - SSLError("[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_SYSCALL, underlying IO error: %s", strerror(errno)); + SSLError(static_cast(vc),"[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_SYSCALL, underlying IO error: %s", strerror(errno)); } else { // then EOF observed, treat it as EOS event = SSL_READ_EOS; @@ -147,7 +147,7 @@ ssl_read_from_net(UnixNetVConnection * vc, EThread * lthread, int64_t &ret) default: event = SSL_READ_ERROR; ret = errno; - SSLError("[SSL_NetVConnection::ssl_read_from_net]"); + SSLError(static_cast(vc),"[SSL_NetVConnection::ssl_read_from_net]"); break; } // switch break; @@ -430,7 +430,7 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted, i default: r = -errno; Debug("ssl", "SSL_write-SSL_ERROR_SSL"); - SSLError("SSL_write"); + SSLError(this,"SSL_write"); break; } return (r); @@ -495,7 +495,7 @@ SSLNetVConnection::sslStartHandShake(int event, int &err) this->ssl = make_ssl_connection(lookup->defaultContext(), this); if (this->ssl == NULL) { Debug("ssl", "SSLNetVConnection::sslServerHandShakeEvent, ssl create failed"); - SSLError("SSL_StartHandShake"); + SSLError(this,"SSL_StartHandShake"); return EVENT_ERROR; } } @@ -523,7 +523,7 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err) ssl_error = SSL_get_error(ssl, ret); if (ssl_error != SSL_ERROR_NONE) { err = errno; - SSLDebug("SSL handshake error: %s (%d), errno=%d", SSLErrorName(ssl_error), ssl_error, err); + SSLDebug(this,"SSL handshake error: %s (%d), errno=%d", SSLErrorName(ssl_error), ssl_error, err); } switch (ssl_error) { @@ -660,7 +660,7 @@ SSLNetVConnection::sslClientHandShakeEvent(int &err) case SSL_ERROR_SSL: default: err = errno; - SSLError("sslClientHandShakeEvent"); + SSLError(this, "sslClientHandShakeEvent"); return EVENT_ERROR; break; diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc index 474f4563e9b..2cbde71a21f 100644 --- a/iocore/net/SSLUtils.cc +++ b/iocore/net/SSLUtils.cc @@ -25,6 +25,7 @@ #include "P_Net.h" #include "ink_cap.h" +#include #include #include #include @@ -87,6 +88,9 @@ static int ssl_session_ticket_index = 0; static pthread_mutex_t *mutex_buf = NULL; static bool open_ssl_initialized = false; +RecRawStatBlock *ssl_rsb = NULL; +InkHashTable *ssl_cipher_name_table = NULL; + struct ats_file_bio { ats_file_bio(const char * path, const char * mode) @@ -303,6 +307,147 @@ ssl_context_enable_tickets(SSL_CTX * ctx, const char * ticket_key_path) #endif /* HAVE_OPENSSL_SESSION_TICKETS */ } +static int +SSLRecRawStatSyncCount(const char *name, RecDataT data_type, RecData *data, RecRawStatBlock *rsb, int id) +{ + // we will grab all the stats we want from openssl and set the stats + // this function only needs to be called by one of the involved stats, all others + // must call RecRawStatSyncSum + SSLCertLookup * certLookup = SSLCertificateConfig::acquire(); + int64_t sessions = 0; + int64_t hits = 0; + int64_t misses = 0; + int64_t timeouts = 0; + if(certLookup) { + size_t ctxCount = certLookup->getCtxCount(); + for(size_t i = 0; i < ctxCount; i++) { + SSL_CTX * ctx = certLookup->getCtx(i); + sessions += SSL_CTX_sess_accept_good(ctx); + hits += SSL_CTX_sess_hits(ctx); + misses += SSL_CTX_sess_misses(ctx); + timeouts += SSL_CTX_sess_timeouts(ctx); + } + } + SSL_SET_COUNT_DYN_STAT(ssl_user_agent_sessions_stat, sessions); + SSL_SET_COUNT_DYN_STAT(ssl_user_agent_session_hit_stat, hits); + SSL_SET_COUNT_DYN_STAT(ssl_user_agent_session_miss_stat, misses); + SSL_SET_COUNT_DYN_STAT(ssl_user_agent_session_timeout_stat, timeouts); + return RecRawStatSyncCount(name, data_type, data, rsb, id); +} + +static void +register_ssl_stats() +{ + // ssl client + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_other_errors", + RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_other_errors_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_expired_cert", + RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_expired_cert_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_revoked_cert", + RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_revoked_cert_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_unknown_cert", + RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_unknown_cert_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_cert_verify_failed", + RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_cert_verify_failed_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_bad_cert", + RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_bad_cert_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_decryption_failed", + RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_decryption_failed_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_wrong_version", + RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_wrong_version_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_unknown_ca", + RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_unknown_ca_stat, + RecRawStatSyncSum); + // polled stats + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_sessions", + RECD_INT, RECP_NON_PERSISTENT, (int) ssl_user_agent_sessions_stat, + SSLRecRawStatSyncCount); //<- only use this fn once + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_session_hit", + RECD_INT, RECP_NON_PERSISTENT, (int) ssl_user_agent_session_hit_stat, + RecRawStatSyncCount); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_session_miss", + RECD_INT, RECP_NON_PERSISTENT, (int) ssl_user_agent_session_miss_stat, + RecRawStatSyncCount); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_session_timeout", + RECD_INT, RECP_NON_PERSISTENT, (int) ssl_user_agent_session_timeout_stat, + RecRawStatSyncCount); + + // ssl server + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_other_errors", + RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_other_errors_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_expired_cert", + RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_expired_cert_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_revoked_cert", + RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_revoked_cert_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_unknown_cert", + RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_unknown_cert_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_cert_verify_failed", + RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_cert_verify_failed_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_bad_cert", + RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_bad_cert_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_decryption_failed", + RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_decryption_failed_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_wrong_version", + RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_wrong_version_stat, + RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_unknown_ca", + RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_unknown_ca_stat, + RecRawStatSyncSum); + // get and register ssl cipher stats + // initialize stat name->index hash table + ssl_cipher_name_table = ink_hash_table_create(InkHashTableKeyType_Word); + + const SSL_METHOD * meth = SSLv23_server_method(); + if (meth) { + SSL_CTX * ctx = SSL_CTX_new(meth); + if (ctx) { + SSL * ssl = SSL_new(ctx); + if (ssl) { + for (int index = 0;; index++) { + const char *cipherName = SSL_get_cipher_list(ssl, index); + if (cipherName == NULL) break; + + std::string statName = "proxy.process.ssl.cipher.user_agent." + std::string(cipherName); + // if room in allocated space + if (ssl_cipher_stats_start + index <= ssl_cipher_stats_end) { + // if not already registered + if (!ink_hash_table_isbound(ssl_cipher_name_table, cipherName) ) { + ink_hash_table_insert(ssl_cipher_name_table, cipherName, (void *)(ssl_cipher_stats_start + index) ); + // registering as non-persistent since the order/index is dependent upon configuration + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, statName.c_str(), + RECD_INT, RECP_NON_PERSISTENT, (int) ssl_cipher_stats_start + index, + RecRawStatSyncSum); + SSL_CLEAR_DYN_STAT((int) ssl_cipher_stats_start + index); + Debug("ssl","Registering ssl cipher stat '%s'", statName.c_str()); + } + } else { // too many ciphers, increase ssl_cipher_stats_end + SSLError(NULL, "Too many ciphers to register stat '%s', increase SSL_Stats::ssl_cipher_stats_end", + statName.c_str()); + } + } + } + if (ssl != NULL) SSL_free(ssl); + } + if (ctx != NULL) SSL_CTX_free(ctx); + } + +} + void SSLInitializeLibrary() { @@ -320,19 +465,109 @@ SSLInitializeLibrary() CRYPTO_set_locking_callback(SSL_locking_callback); CRYPTO_set_id_callback(SSL_pthreads_thread_id); + + // alloc stat block + ssl_rsb = RecAllocateRawStatBlock((int) Ssl_Stat_Count); + // register ssl stats + register_ssl_stats(); } int iRet = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (iRet == -1) { - SSLError("failed to create session ticket index"); + SSLError(NULL, "failed to create session ticket index"); } ssl_session_ticket_index = (iRet == -1 ? 0 : iRet); open_ssl_initialized = true; } +bool +SSLUpdateStats(unsigned long err, bool bIsSSLClientConn) +{ + bool bHadAStat = true; + // stat determined by LIB and REASON (we ignore FUNCTION with the prejudice that + // we don't care what function the error came from, hope that's ok?) + switch (ERR_PACK(ERR_GET_LIB(err),0,ERR_GET_REASON(err)) ) { + // expired cert + case ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED): + if (bIsSSLClientConn) { // where ats is client + SSL_INCREMENT_DYN_STAT(ssl_origin_server_expired_cert_stat); + } else { // ats is server + SSL_INCREMENT_DYN_STAT(ssl_user_agent_expired_cert_stat); + } + break; + // revoked cert + case ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED): + if (bIsSSLClientConn) { // where ats is client + SSL_INCREMENT_DYN_STAT(ssl_origin_server_revoked_cert_stat); + } else { // ats is server + SSL_INCREMENT_DYN_STAT(ssl_user_agent_revoked_cert_stat); + } + break; + // unknown cert + case ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN): + if (bIsSSLClientConn) { // where ats is client + SSL_INCREMENT_DYN_STAT(ssl_origin_server_unknown_cert_stat); + } else { // ats is server + SSL_INCREMENT_DYN_STAT(ssl_user_agent_unknown_cert_stat); + } + break; + // cert verify failed + case ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CERTIFICATE_VERIFY_FAILED): + if (bIsSSLClientConn) { // where ats is client + // will get proxy.config.http.connect_attempts_max_retries_dead_server of these + // for each OS connection attempts (we just count those too) + SSL_INCREMENT_DYN_STAT(ssl_origin_server_cert_verify_failed_stat); + } else { // ats is server + SSL_INCREMENT_DYN_STAT(ssl_user_agent_cert_verify_failed_stat); + } + break; + // bad cert + case ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_BAD_CERTIFICATE): + if (bIsSSLClientConn) { // where ats is client + SSL_INCREMENT_DYN_STAT(ssl_origin_server_bad_cert_stat); + } else { // ats is server + SSL_INCREMENT_DYN_STAT(ssl_user_agent_bad_cert_stat); + } + break; + // decryption failed + case ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECRYPTION_FAILED): + if (bIsSSLClientConn) { // where ats is client + SSL_INCREMENT_DYN_STAT(ssl_origin_server_decryption_failed_stat); + } else { // ats is server + SSL_INCREMENT_DYN_STAT(ssl_user_agent_decryption_failed_stat); + } + break; + // wrong version + case ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_VERSION_NUMBER): + if (bIsSSLClientConn) { // where ats is client + SSL_INCREMENT_DYN_STAT(ssl_origin_server_wrong_version_stat); + } else { // ats is server + SSL_INCREMENT_DYN_STAT(ssl_user_agent_wrong_version_stat); + } + break; + // unknown CA + case ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_UNKNOWN_CA): + if (bIsSSLClientConn) { // where ats is client + SSL_INCREMENT_DYN_STAT(ssl_origin_server_unknown_ca_stat); + } else { // ats is server + SSL_INCREMENT_DYN_STAT(ssl_user_agent_unknown_ca_stat); + } + break; + default: + if (bIsSSLClientConn) { // where ats is client + SSL_INCREMENT_DYN_STAT(ssl_origin_server_other_errors_stat); + } else { /// ats is server + SSL_INCREMENT_DYN_STAT(ssl_user_agent_other_errors_stat); + } + bHadAStat = false; + break; + } + return bHadAStat; +} + void -SSLDiagnostic(const SrcLoc& loc, bool debug, const char * fmt, ...) +SSLDiagnostic(const SrcLoc& loc, bool debug, SSLNetVConnection * vc, const char * fmt, ...) { unsigned long l; char buf[256]; @@ -355,6 +590,11 @@ SSLDiagnostic(const SrcLoc& loc, bool debug, const char * fmt, ...) "SSL::%lu:%s:%s:%d%s%s", es, ERR_error_string(l, buf), file, line, (flags & ERR_TXT_STRING) ? ":" : "", (flags & ERR_TXT_STRING) ? data : ""); } + // tally desired stats (only client/server connection stats, not init + // issues where vc is NULL) + if(vc) { + SSLUpdateStats(l,vc->getSSLClientConnection()); + } } va_start(ap, fmt); @@ -450,7 +690,7 @@ SSLInitServerContext( // be in the same file. SSL_CTX_use_certificate_chain_file() was added in OpenSSL 0.9.3. completeServerCertPath = Layout::relative_to(params->serverCertPathOnly, serverCertPtr); if (!SSL_CTX_use_certificate_file(ctx, completeServerCertPath, SSL_FILETYPE_PEM)) { - SSLError("failed to load certificate from %s", (const char *)completeServerCertPath); + SSLError(NULL, "failed to load certificate from %s", (const char *) completeServerCertPath); goto fail; } @@ -458,7 +698,7 @@ SSLInitServerContext( if (params->serverCertChainFilename) { xptr completeServerCertChainPath(Layout::relative_to(params->serverCertPathOnly, params->serverCertChainFilename)); if (!SSL_CTX_add_extra_chain_cert_file(ctx, completeServerCertChainPath)) { - SSLError("failed to load global certificate chain from %s", (const char *)completeServerCertChainPath); + SSLError(NULL, "failed to load global certificate chain from %s", (const char *) completeServerCertChainPath); goto fail; } } @@ -467,29 +707,30 @@ SSLInitServerContext( if (serverCaCertPtr) { xptr completeServerCertChainPath(Layout::relative_to(params->serverCertPathOnly, serverCaCertPtr)); if (!SSL_CTX_add_extra_chain_cert_file(ctx, completeServerCertChainPath)) { - SSLError("failed to load certificate chain from %s", (const char *)completeServerCertChainPath); + SSLError(NULL, "failed to load certificate chain from %s", (const char *) completeServerCertChainPath); goto fail; } } + if (serverKeyPtr == NULL) { // assume private key is contained in cert obtained from multicert file. if (!SSL_CTX_use_PrivateKey_file(ctx, completeServerCertPath, SSL_FILETYPE_PEM)) { - SSLError("failed to load server private key from %s", (const char *)completeServerCertPath); + SSLError(NULL, "failed to load server private key from %s", (const char *) completeServerCertPath); goto fail; } } else if (params->serverKeyPathOnly != NULL) { xptr completeServerKeyPath(Layout::get()->relative_to(params->serverKeyPathOnly, serverKeyPtr)); if (!SSL_CTX_use_PrivateKey_file(ctx, completeServerKeyPath, SSL_FILETYPE_PEM)) { - SSLError("failed to load server private key from %s", (const char *)completeServerKeyPath); + SSLError(NULL, "failed to load server private key from %s", (const char *) completeServerKeyPath); goto fail; } } else { - SSLError("empty SSL private key path in records.config"); + SSLError(NULL, "empty SSL private key path in records.config"); } if (!SSL_CTX_check_private_key(ctx)) { - SSLError("server private key does not match the certificate public key"); + SSLError(NULL, "server private key does not match the certificate public key"); goto fail; } @@ -498,7 +739,7 @@ SSLInitServerContext( if (params->serverCACertFilename != NULL && params->serverCACertPath != NULL) { if ((!SSL_CTX_load_verify_locations(ctx, params->serverCACertFilename, params->serverCACertPath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { - SSLError("CA Certificate file or CA Certificate path invalid"); + SSLError(NULL, "CA Certificate file or CA Certificate path invalid"); goto fail; } } @@ -526,7 +767,7 @@ SSLInitServerContext( if (params->cipherSuite != NULL) { if (!SSL_CTX_set_cipher_list(ctx, params->cipherSuite)) { - SSLError("invalid cipher suite in records.config"); + SSLError(NULL, "invalid cipher suite in records.config"); goto fail; } } @@ -555,7 +796,7 @@ SSLInitClientContext(const SSLConfigParams * params) // disable selected protocols SSL_CTX_set_options(client_ctx, params->ssl_ctx_options); if (!client_ctx) { - SSLError("cannot create new client context"); + SSLError(NULL, "cannot create new client context"); return NULL; } @@ -568,17 +809,17 @@ SSLInitClientContext(const SSLConfigParams * params) if (params->clientCertPath != 0) { if (!SSL_CTX_use_certificate_file(client_ctx, params->clientCertPath, SSL_FILETYPE_PEM)) { - SSLError("failed to load client certificate from %s", params->clientCertPath); + SSLError(NULL, "failed to load client certificate from %s", params->clientCertPath); goto fail; } if (!SSL_CTX_use_PrivateKey_file(client_ctx, clientKeyPtr, SSL_FILETYPE_PEM)) { - SSLError("failed to load client private key file from %s", clientKeyPtr); + SSLError(NULL, "failed to load client private key file from %s", clientKeyPtr); goto fail; } if (!SSL_CTX_check_private_key(client_ctx)) { - SSLError("client private key (%s) does not match the certificate public key (%s)", + SSLError(NULL, "client private key (%s) does not match the certificate public key (%s)", clientKeyPtr, params->clientCertPath); goto fail; } @@ -594,7 +835,7 @@ SSLInitClientContext(const SSLConfigParams * params) if (params->clientCACertFilename != NULL && params->clientCACertPath != NULL) { if ((!SSL_CTX_load_verify_locations(client_ctx, params->clientCACertFilename, params->clientCACertPath)) || (!SSL_CTX_set_default_verify_paths(client_ctx))) { - SSLError("invalid client CA Certificate file (%s) or CA Certificate path (%s)", + SSLError(NULL, "invalid client CA Certificate file (%s) or CA Certificate path (%s)", params->clientCACertFilename, params->clientCACertPath); goto fail; } @@ -674,7 +915,7 @@ ssl_index_certificate(SSLCertLookup * lookup, SSL_CTX * ctx, const char * certfi // This callback function is executed while OpenSSL processes the SSL // handshake and does SSL record layer stuff. It's used to trap -// client-initiated renegotiations +// client-initiated renegotiations and update cipher stats static void ssl_callback_info(const SSL *ssl, int where, int ret) { @@ -690,6 +931,18 @@ ssl_callback_info(const SSL *ssl, int where, int ret) Debug("ssl", "ssl_callback_info trying to renegotiate from the client"); } } + if (where & SSL_CB_HANDSHAKE_DONE) { + // handshake is complete + const SSL_CIPHER * cipher = SSL_get_current_cipher(ssl); + if (cipher) { + const char * cipherName = SSL_CIPHER_get_name(cipher); + // lookup index of stat by name and incr count + InkHashTableValue data; + if (ink_hash_table_lookup(ssl_cipher_name_table, cipherName, &data)) { + SSL_INCREMENT_DYN_STAT((intptr_t)data); + } + } + } } static bool diff --git a/iocore/net/UnixNetVConnection.cc b/iocore/net/UnixNetVConnection.cc index bf1dc0a8e92..c9db90dab29 100644 --- a/iocore/net/UnixNetVConnection.cc +++ b/iocore/net/UnixNetVConnection.cc @@ -806,6 +806,7 @@ UnixNetVConnection::UnixNetVConnection() memset(&local_addr, 0, sizeof local_addr); memset(&server_addr, 0, sizeof server_addr); SET_HANDLER((NetVConnHandler) & UnixNetVConnection::startEvent); + attributes = HttpProxyPort::TRANSPORT_DEFAULT; } // Private methods diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index 41b876c7e0b..581cad1ac8c 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -1629,6 +1629,20 @@ RecordElement RecordsConfig[] = { , {RECT_NODE, "proxy.node.http.current_parent_proxy_connections", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} , + // ssl + {RECT_NODE, "proxy.node.https.user_agent_total_request_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_NODE, "proxy.node.https.user_agent_total_response_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_NODE, "proxy.node.https.origin_server_total_request_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_NODE, "proxy.node.https.origin_server_total_response_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_NODE, "proxy.node.https.user_agent_total_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_NODE, "proxy.node.https.origin_server_total_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + //# Cache {RECT_NODE, "proxy.node.cache.contents.num_docs", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} , @@ -1787,6 +1801,17 @@ RecordElement RecordsConfig[] = { , {RECT_CLUSTER, "proxy.cluster.http.parent_proxy_total_response_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} , + // ssl + {RECT_CLUSTER, "proxy.cluster.https.throughput", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_CLUSTER, "proxy.cluster.https.user_agent_total_request_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_CLUSTER, "proxy.cluster.https.user_agent_total_response_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_CLUSTER, "proxy.cluster.https.origin_server_total_request_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_CLUSTER, "proxy.cluster.https.origin_server_total_response_bytes", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , //# Cache {RECT_CLUSTER, "proxy.cluster.cache.contents.num_docs", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} , @@ -1851,6 +1876,13 @@ RecordElement RecordsConfig[] = { , {RECT_CLUSTER, "proxy.cluster.current_server_connections", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} , + // ssl + {RECT_CLUSTER, "proxy.cluster.https.user_agent_xacts_per_second", RECD_FLOAT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_CLUSTER, "proxy.cluster.https.client_throughput_out", RECD_FLOAT, "0.0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , + {RECT_CLUSTER, "proxy.cluster.https.client_throughput_out_kbit", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , // //# diff --git a/proxy/config/stats.config.xml.default b/proxy/config/stats.config.xml.default index 6d97a7a8e9d..7cb91b1c65f 100644 --- a/proxy/config/stats.config.xml.default +++ b/proxy/config/stats.config.xml.default @@ -34,7 +34,6 @@ - proxy.node.http.cache_current_connections_count @@ -139,7 +138,7 @@ - + + + + proxy.node.https.user_agent_total_request_bytes + proxy.cluster.https.user_agent_total_request_bytes + + proxy.process.https.user_agent_request_document_total_size + + proxy.process.https.user_agent_request_header_total_size + + + + + proxy.node.https.user_agent_total_response_bytes + proxy.cluster.https.user_agent_total_response_bytes + + proxy.process.https.user_agent_response_document_total_size + + proxy.process.https.user_agent_response_header_total_size + + + + + proxy.node.https.origin_server_total_request_bytes + proxy.cluster.https.origin_server_total_request_bytes + + proxy.process.https.origin_server_request_document_total_size + + proxy.process.https.origin_server_request_header_total_size + + + + + proxy.node.https.origin_server_total_response_bytes + proxy.cluster.https.origin_server_total_response_bytes + + proxy.process.https.origin_server_response_document_total_size + + proxy.process.https.origin_server_response_header_total_size + + + + @@ -269,6 +309,14 @@ + + proxy.node.https.user_agent_total_bytes + + proxy.node.https.user_agent_total_request_bytes + + proxy.node.https.user_agent_total_response_bytes + + + + proxy.node.https.origin_server_total_bytes + + proxy.node.https.origin_server_total_request_bytes + + proxy.node.https.origin_server_total_response_bytes + + httpClientSessionAllocator("httpClientSessionA HttpClientSession::HttpClientSession() : VConnection(NULL), con_id(0), client_vc(NULL), magic(HTTP_CS_MAGIC_DEAD), tcp_init_cwnd_set(false), - transact_count(0), half_close(false), conn_decrease(false), bound_ss(NULL), + transact_count(0), half_close(false), conn_decrease(false), + client_vc_attributes(HttpProxyPort::TRANSPORT_DEFAULT), bound_ss(NULL), read_buffer(NULL), current_reader(NULL), read_state(HCS_INIT), ka_vio(NULL), slave_ka_vio(NULL), cur_hook_id(TS_HTTP_LAST_HOOK), cur_hook(NULL), @@ -99,6 +100,9 @@ HttpClientSession::cleanup() if (conn_decrease) { HTTP_DECREMENT_DYN_STAT(http_current_client_connections_stat); + if(client_vc_attributes == HttpProxyPort::TRANSPORT_SSL) { + HTTP_DECREMENT_DYN_STAT(https_current_client_connections_stat); + } conn_decrease = false; } } @@ -186,11 +190,16 @@ HttpClientSession::new_connection(NetVConnection * new_vc, bool backdoor) MUTEX_TRY_LOCK(lock, mutex, this_ethread()); ink_assert(!!lock); this->backdoor_connect = backdoor; + client_vc_attributes = client_vc->attributes; // Unique client session identifier. con_id = ink_atomic_increment((int64_t *) (&next_cs_id), 1); HTTP_INCREMENT_DYN_STAT(http_current_client_connections_stat); + if(client_vc_attributes == HttpProxyPort::TRANSPORT_SSL) { + HTTP_INCREMENT_DYN_STAT(https_current_client_connections_stat); + HTTP_INCREMENT_DYN_STAT(https_total_client_connections_stat); + } conn_decrease = true; HTTP_INCREMENT_DYN_STAT(http_total_client_connections_stat); /* inbound requests stat should be incremented here, not after the @@ -329,6 +338,9 @@ HttpClientSession::do_io_close(int alerrno) client_vc = NULL; HTTP_SUM_DYN_STAT(http_transactions_per_client_con, transact_count); HTTP_DECREMENT_DYN_STAT(http_current_client_connections_stat); + if(client_vc_attributes == HttpProxyPort::TRANSPORT_SSL) { + HTTP_DECREMENT_DYN_STAT(https_current_client_connections_stat); + } conn_decrease = false; do_api_callout(TS_HTTP_SSN_CLOSE_HOOK); } diff --git a/proxy/http/HttpClientSession.h b/proxy/http/HttpClientSession.h index e80743b5a00..19ef54b5385 100644 --- a/proxy/http/HttpClientSession.h +++ b/proxy/http/HttpClientSession.h @@ -117,6 +117,8 @@ class HttpClientSession: public VConnection bool half_close; bool conn_decrease; void *user_args[HTTP_SSN_TXN_MAX_USER_ARG]; + // The saved off client_vc->atrributes (is a HttpProxyPort::TransportType) + int client_vc_attributes; HttpServerSession *bound_ss; diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc index 419de41652a..27eac5f8411 100644 --- a/proxy/http/HttpConfig.cc +++ b/proxy/http/HttpConfig.cc @@ -1108,6 +1108,67 @@ register_stat_callbacks() RECD_COUNTER, RECP_PERSISTENT, (int) http_total_x_redirect_stat, RecRawStatSyncCount); + // SSL stats + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.incoming_requests", + RECD_COUNTER, RECP_PERSISTENT, (int) https_incoming_requests_stat, RecRawStatSyncCount); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.outgoing_requests", + RECD_COUNTER, RECP_PERSISTENT, (int) https_outgoing_requests_stat, RecRawStatSyncCount); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.current_client_connections", + RECD_INT, RECP_NON_PERSISTENT, (int) https_current_client_connections_stat, RecRawStatSyncSum); + HTTP_CLEAR_DYN_STAT(https_current_client_connections_stat); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.total_client_connections", + RECD_COUNTER, RECP_PERSISTENT, (int) https_total_client_connections_stat, RecRawStatSyncCount); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.current_server_connections", + RECD_INT, RECP_NON_PERSISTENT, (int) https_current_server_connections_stat, RecRawStatSyncSum); + HTTP_CLEAR_DYN_STAT(https_current_server_connections_stat); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.total_server_connections", + RECD_COUNTER, RECP_PERSISTENT, (int) https_total_server_connections_stat, RecRawStatSyncCount); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.user_agent_request_document_total_size", + RECD_INT, RECP_PERSISTENT, (int) https_user_agent_request_document_total_size_stat, RecRawStatSyncSum); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.user_agent_request_header_total_size", + RECD_INT, RECP_PERSISTENT, (int) https_user_agent_request_header_total_size_stat, RecRawStatSyncSum); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.user_agent_response_document_total_size", + RECD_INT, RECP_PERSISTENT, (int) https_user_agent_response_document_total_size_stat, RecRawStatSyncSum); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.user_agent_response_header_total_size", + RECD_INT, RECP_PERSISTENT, (int) https_user_agent_response_header_total_size_stat, RecRawStatSyncSum); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.origin_server_request_document_total_size", + RECD_INT, RECP_PERSISTENT, (int) https_origin_server_request_document_total_size_stat, RecRawStatSyncSum); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.origin_server_request_header_total_size", + RECD_INT, RECP_PERSISTENT, (int) https_origin_server_request_header_total_size_stat, RecRawStatSyncSum); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.origin_server_response_document_total_size", + RECD_INT, RECP_PERSISTENT, + (int) https_origin_server_response_document_total_size_stat, RecRawStatSyncSum); + + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.https.origin_server_response_header_total_size", + RECD_INT, RECP_PERSISTENT, (int) https_origin_server_response_header_total_size_stat, RecRawStatSyncSum); + } diff --git a/proxy/http/HttpConfig.h b/proxy/http/HttpConfig.h index 54cf2733247..d9441e09006 100644 --- a/proxy/http/HttpConfig.h +++ b/proxy/http/HttpConfig.h @@ -345,6 +345,22 @@ enum http_response_status_505_count_stat, http_response_status_5xx_count_stat, + // SSL related stats + https_incoming_requests_stat, + https_outgoing_requests_stat, + https_current_client_connections_stat, + https_total_client_connections_stat, + https_current_server_connections_stat, + https_total_server_connections_stat, + https_user_agent_request_document_total_size_stat, + https_user_agent_request_header_total_size_stat, + https_user_agent_response_document_total_size_stat, + https_user_agent_response_header_total_size_stat, + https_origin_server_request_document_total_size_stat, + https_origin_server_request_header_total_size_stat, + https_origin_server_response_document_total_size_stat, + https_origin_server_response_header_total_size_stat, + http_stat_count }; diff --git a/proxy/http/HttpServerSession.cc b/proxy/http/HttpServerSession.cc index dd3de6131d4..ac88f4a64ee 100644 --- a/proxy/http/HttpServerSession.cc +++ b/proxy/http/HttpServerSession.cc @@ -72,6 +72,10 @@ HttpServerSession::new_connection(NetVConnection *new_vc) magic = HTTP_SS_MAGIC_ALIVE; HTTP_SUM_GLOBAL_DYN_STAT(http_current_server_connections_stat, 1); // Update the true global stat HTTP_INCREMENT_DYN_STAT(http_total_server_connections_stat); + if(server_vc->attributes == HttpProxyPort::TRANSPORT_SSL) { + HTTP_SUM_GLOBAL_DYN_STAT(https_current_server_connections_stat, 1); + HTTP_INCREMENT_DYN_STAT(https_total_server_connections_stat); + } // Check to see if we are limiting the number of connections // per host if (enable_origin_connection_limiting == true) { @@ -119,6 +123,11 @@ HttpServerSession::do_io_close(int alerrno) this->server_trans_stat--; } + // update ssl stat before disposal of server_vc + if(server_vc->attributes == HttpProxyPort::TRANSPORT_SSL) { + HTTP_SUM_GLOBAL_DYN_STAT(https_current_server_connections_stat, -1); + } + server_vc->do_io_close(alerrno); Debug("http_ss", "[%" PRId64 "] session closed", con_id); server_vc = NULL; diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index 9692d998a2d..ce773cd2692 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -1287,6 +1287,9 @@ HttpTransact::HandleRequest(State* s) ink_assert(!s->hdr_info.server_request.valid()); HTTP_INCREMENT_TRANS_STAT(http_incoming_requests_stat); + if(s->client_info.port_attribute == HttpProxyPort::TRANSPORT_SSL) { + HTTP_INCREMENT_TRANS_STAT(https_incoming_requests_stat); + } if (s->api_release_server_session == true) { s->api_release_server_session = false; @@ -7842,6 +7845,9 @@ HttpTransact::build_request(State* s, HTTPHdr* base_request, HTTPHdr* outgoing_r DUMP_HEADER("http_hdrs", outgoing_request, s->state_machine_id, "Proxy's Request"); HTTP_INCREMENT_TRANS_STAT(http_outgoing_requests_stat); + if(s->next_hop_scheme == URL_WKSIDX_HTTPS) { + HTTP_INCREMENT_TRANS_STAT(https_outgoing_requests_stat); + } } // build a (status_code) response based upon the given info @@ -8764,6 +8770,15 @@ HttpTransact::update_size_and_time_stats(State* s, ink_hrtime total_time, ink_hr HTTP_SUM_TRANS_STAT(http_user_agent_request_document_total_size_stat, user_agent_request_body_size); HTTP_SUM_TRANS_STAT(http_user_agent_response_document_total_size_stat, user_agent_response_body_size); + // ssl stats + // ssl user agent/client stats + if(s->client_info.port_attribute == HttpProxyPort::TRANSPORT_SSL) { + HTTP_SUM_TRANS_STAT(https_user_agent_request_header_total_size_stat, user_agent_request_header_size); + HTTP_SUM_TRANS_STAT(https_user_agent_request_document_total_size_stat, user_agent_request_body_size); + HTTP_SUM_TRANS_STAT(https_user_agent_response_header_total_size_stat, user_agent_response_header_size); + HTTP_SUM_TRANS_STAT(https_user_agent_response_document_total_size_stat, user_agent_response_body_size); + } + // proxy stats if (s->current.request_to == HttpTransact::PARENT_PROXY) { HTTP_SUM_TRANS_STAT(http_parent_proxy_request_total_bytes_stat, @@ -8779,6 +8794,13 @@ HttpTransact::update_size_and_time_stats(State* s, ink_hrtime total_time, ink_hr HTTP_SUM_TRANS_STAT(http_origin_server_response_header_total_size_stat, origin_server_response_header_size); HTTP_SUM_TRANS_STAT(http_origin_server_request_document_total_size_stat, origin_server_request_body_size); HTTP_SUM_TRANS_STAT(http_origin_server_response_document_total_size_stat, origin_server_response_body_size); + // ssl origin + if(s->next_hop_scheme == URL_WKSIDX_HTTPS) { + HTTP_SUM_TRANS_STAT(https_origin_server_request_header_total_size_stat, origin_server_request_header_size); + HTTP_SUM_TRANS_STAT(https_origin_server_response_header_total_size_stat, origin_server_response_header_size); + HTTP_SUM_TRANS_STAT(https_origin_server_request_document_total_size_stat, origin_server_request_body_size); + HTTP_SUM_TRANS_STAT(https_origin_server_response_document_total_size_stat, origin_server_response_body_size); + } } if (s->method == HTTP_WKSIDX_PUSH) {