Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TLS session reuse support #458

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,51 @@

#include "ssl.h"

SSL_CTX *ssl_init() {
int ssl_data_index;

static int ssl_new_client_session(SSL *ssl, SSL_SESSION *session) {
connection *c = SSL_get_ex_data(ssl, ssl_data_index);

if (c->cache) {
if (c->cache->cached_session) {
SSL_SESSION_free(c->cache->cached_session);
c->cache->cached_session = NULL;
}
c->cache->cached_session = session;
}

return 1;
}

SSL_CTX *ssl_init(bool tls_session_reuse) {
SSL_CTX *ctx = NULL;

SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
ssl_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);

if ((ctx = SSL_CTX_new(SSLv23_client_method()))) {
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
SSL_CTX_set_verify_depth(ctx, 0);
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT);

if (tls_session_reuse) {
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL);
SSL_CTX_sess_set_new_cb(ctx, ssl_new_client_session);
}
}

return ctx;
}

status ssl_connect(connection *c, char *host) {
int r;

if (SSL_get_fd(c->ssl) != c->fd && c->cache && c->cache->cached_session) {
SSL_set_session(c->ssl, c->cache->cached_session);
}

SSL_set_fd(c->ssl, c->fd);
SSL_set_tlsext_host_name(c->ssl, host);
if ((r = SSL_connect(c->ssl)) != 1) {
Expand All @@ -42,6 +68,8 @@ status ssl_connect(connection *c, char *host) {
status ssl_close(connection *c) {
SSL_shutdown(c->ssl);
SSL_clear(c->ssl);
SSL_free(c->ssl);
c->ssl = NULL;
return OK;
}

Expand Down
4 changes: 3 additions & 1 deletion src/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@

#include "net.h"

SSL_CTX *ssl_init();
SSL_CTX *ssl_init(bool);

status ssl_connect(connection *, char *);
status ssl_close(connection *);
status ssl_read(connection *, size_t *);
status ssl_write(connection *, char *, size_t, size_t *);
size_t ssl_readable(connection *);

extern int ssl_data_index;

#endif /* SSL_H */
37 changes: 34 additions & 3 deletions src/wrk.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ static struct config {
bool delay;
bool dynamic;
bool latency;
bool tls_session_reuse;
char *host;
char *script;
SSL_CTX *ctx;
Expand Down Expand Up @@ -52,6 +53,7 @@ static void usage() {
" -H, --header <H> Add header to request \n"
" --latency Print latency statistics \n"
" --timeout <T> Socket/request timeout \n"
" -r, --reuse Enable TLS session reuse \n"
" -v, --version Print version details \n"
" \n"
" Numeric arguments may include a SI unit (1k, 1M, 1G)\n"
Expand All @@ -73,7 +75,7 @@ int main(int argc, char **argv) {
char *service = port ? port : schema;

if (!strncmp("https", schema, 5)) {
if ((cfg.ctx = ssl_init()) == NULL) {
if ((cfg.ctx = ssl_init(cfg.tls_session_reuse)) == NULL) {
fprintf(stderr, "unable to initialize SSL\n");
ERR_print_errors_fp(stderr);
exit(1);
Expand Down Expand Up @@ -136,7 +138,13 @@ int main(int argc, char **argv) {

char *time = format_time_s(cfg.duration);
printf("Running %s test @ %s\n", time, url);
printf(" %"PRIu64" threads and %"PRIu64" connections\n", cfg.threads, cfg.connections);
printf(" %"PRIu64" threads and %"PRIu64" connections", cfg.threads, cfg.connections);

if (cfg.ctx) {
printf(" (TLS session reuse %s)", cfg.tls_session_reuse ? "enabled" : "disabled");
}

printf("\n");

uint64_t start = time_us();
uint64_t complete = 0;
Expand Down Expand Up @@ -190,6 +198,19 @@ int main(int argc, char **argv) {
printf("Requests/sec: %9.2Lf\n", req_per_s);
printf("Transfer/sec: %10sB\n", format_binary(bytes_per_s));

if (cfg.ctx) {
printf("TLS new conn %lu reused %lu miss %lu finished conn %lu sess_cb_hit %lu renegotiation %lu timeout %lu full remove %lu\n",
SSL_CTX_sess_connect(cfg.ctx),
SSL_CTX_sess_hits(cfg.ctx),
SSL_CTX_sess_misses(cfg.ctx),
SSL_CTX_sess_connect_good(cfg.ctx),
SSL_CTX_sess_cb_hits(cfg.ctx),
SSL_CTX_sess_connect_renegotiate(cfg.ctx),
SSL_CTX_sess_timeouts(cfg.ctx),
SSL_CTX_sess_cache_full(cfg.ctx)
);
}

if (script_has_done(L)) {
script_summary(L, runtime_us, complete, bytes);
script_errors(L, &errors);
Expand All @@ -214,7 +235,6 @@ void *thread_main(void *arg) {

for (uint64_t i = 0; i < thread->connections; i++, c++) {
c->thread = thread;
c->ssl = cfg.ctx ? SSL_new(cfg.ctx) : NULL;
c->request = request;
c->length = length;
c->delayed = cfg.delay;
Expand All @@ -227,6 +247,7 @@ void *thread_main(void *arg) {
thread->start = time_us();
aeMain(loop);

SSL_SESSION_free(thread->cache.cached_session);
aeDeleteEventLoop(loop);
zfree(thread->cs);

Expand All @@ -250,6 +271,12 @@ static int connect_socket(thread *thread, connection *c) {
flags = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags));

if (cfg.ctx) {
c->ssl = cfg.ctx ? SSL_new(cfg.ctx) : NULL;
SSL_set_ex_data(c->ssl, ssl_data_index, c);
c->cache = cfg.tls_session_reuse ? &thread->cache : NULL;
}

flags = AE_READABLE | AE_WRITABLE;
if (aeCreateFileEvent(loop, fd, flags, socket_connected, c) == AE_OK) {
c->parser.data = c;
Expand Down Expand Up @@ -475,6 +502,7 @@ static struct option longopts[] = {
{ "latency", no_argument, NULL, 'L' },
{ "timeout", required_argument, NULL, 'T' },
{ "help", no_argument, NULL, 'h' },
{ "reuse", no_argument, NULL, 'r' },
{ "version", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
};
Expand Down Expand Up @@ -517,6 +545,9 @@ static int parse_args(struct config *cfg, char **url, struct http_parser_url *pa
printf("wrk %s [%s] ", VERSION, aeGetApiName());
printf("Copyright (C) 2012 Will Glozer\n");
break;
case 'r':
cfg->tls_session_reuse = true;
break;
case 'h':
case '?':
case ':':
Expand Down
6 changes: 6 additions & 0 deletions src/wrk.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

extern const char *VERSION;

typedef struct {
SSL_SESSION *cached_session;
} tls_session_cache;

typedef struct {
pthread_t thread;
aeEventLoop *loop;
Expand All @@ -35,6 +39,7 @@ typedef struct {
uint64_t start;
lua_State *L;
errors errors;
tls_session_cache cache;
struct connection *cs;
} thread;

Expand All @@ -52,6 +57,7 @@ typedef struct connection {
} state;
int fd;
SSL *ssl;
tls_session_cache *cache;
bool delayed;
uint64_t start;
char *request;
Expand Down