I am using stunnel v5.32 compiled on a RHEL 6.7 with
openssl-1.0.1e-42.el6.x86_64.
The stunnel.conf cache settings are (for testing cache behaviour):
*sessionCacheSize = 3sessionCacheTimeout = 60*
What I expect is that after sessioncache size is reached, the memory (RSS)
allocated to stunnel process does not grow with new sessions which are not
in cache.
Instead of this the stunnel allocates about 28K for any new session which
does not have a stored session in cache and does not free this anymore.
For new connections, but with session stored in cache, the memory does not
grow. This lead me to a problem in memory deallocation for expired session
in internal session cache.( I know that openssl frees expired session cache
entries at every 255 sessions).
See example below:
--> stunnel start (see RSS)
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
stunnel 20655 0.0 0.0 117760 1440 ? Ss 15:49 0:00
/usr/local/bin/stunnel5
--> after 3 sessions with no cache hits
stunnel 20655 0.0 0.0 117828 2976 ? Ss 15:49 0:00
/usr/local/bin/stunnel5
- stunnel log
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: New session callback
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: 4 server accept(s)
requested
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: 4 server accept(s)
succeeded
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: 0 server
renegotiation(s) requested
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: 0 session reuse(s)
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: 3 internal session
cache item(s)
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: 0 internal session
cache fill-up(s)
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: 0 internal session
cache miss(es)
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: 0 external session
cache hit(s)
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: 0 expired session(s)
retrieved
2016.05.11 15:50:57 LOG6[kngHAM6DLUpVRXEqHcUMIt]: SSL accepted: new session
negotiated
2016.05.11 15:50:57 LOG7[kngHAM6DLUpVRXEqHcUMIt]: Remove session callback
-----------------------------------------------------
--> after another 1 request with cache hit: as you can see no RSS memory
was added
stunnel 20655 0.0 0.0 117828 2976 ? Ss 15:49 0:00
/usr/local/bin/stunnel5
- stunnel log
2016.05.11 15:51:57 LOG7[Slq6WdqS97Ox4G8eOKfGg0]: SSL state (accept): SSLv3
read finished A
2016.05.11 15:51:57 LOG7[Slq6WdqS97Ox4G8eOKfGg0]: 5 server accept(s)
requested
2016.05.11 15:51:57 LOG7[Slq6WdqS97Ox4G8eOKfGg0]: 5 server accept(s)
succeeded
2016.05.11 15:51:57 LOG7[Slq6WdqS97Ox4G8eOKfGg0]: 0 server
renegotiation(s) requested
2016.05.11 15:51:57 LOG7[Slq6WdqS97Ox4G8eOKfGg0]: 1 session reuse(s)
2016.05.11 15:51:57 LOG7[Slq6WdqS97Ox4G8eOKfGg0]: 3 internal session
cache item(s)
2016.05.11 15:51:57 LOG7[Slq6WdqS97Ox4G8eOKfGg0]: 1 internal session
cache fill-up(s)
2016.05.11 15:51:57 LOG7[Slq6WdqS97Ox4G8eOKfGg0]: 0 internal session
cache miss(es)
2016.05.11 15:51:57 LOG7[Slq6WdqS97Ox4G8eOKfGg0]: 0 external session
cache hit(s)
2016.05.11 15:51:57 LOG7[Slq6WdqS97Ox4G8eOKfGg0]: 0 expired session(s)
retrieved
2016.05.11 15:51:57 LOG6[Slq6WdqS97Ox4G8eOKfGg0]: SSL accepted: previous
session reused
----------------------------------------------------
--> after another 1 request with no cache hit (now we have the first cache
fill-up)
stunnel 20655 0.0 0.0 117828 3000 ? Ss 15:49 0:00
/usr/local/bin/stunnel5
- stunnel log
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: New session callback
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: 6 server accept(s)
requested
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: 6 server accept(s)
succeeded
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: 0 server
renegotiation(s) requested
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: 1 session reuse(s)
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: 3 internal session
cache item(s)
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: 1 internal session
cache fill-up(s)
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: 0 internal session
cache miss(es)
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: 0 external session
cache hit(s)
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: 0 expired session(s)
retrieved
2016.05.11 15:53:31 LOG6[P8n33mFxzHVAZEeRwnFccK]: SSL accepted: new session
negotiated
2016.05.11 15:53:31 LOG7[P8n33mFxzHVAZEeRwnFccK]: Remove session callback
----------------------------------------------------
--> after another 300 new session with no cache hits and after waiting 1
minute for entries in session cache to expire (as said in documentation
openssl must free expired entries every 255 sessions)
stunnel 20655 0.0 0.2 117828 11632 ? Ss 15:49 0:03
/usr/local/bin/stunnel5
- stunnel log
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: New session callback
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: 306 server accept(s)
requested
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: 306 server accept(s)
succeeded
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: 0 server
renegotiation(s) requested
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: 1 session reuse(s)
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: 3 internal session
cache item(s)
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: 301 internal session
cache fill-up(s)
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: 0 internal session
cache miss(es)
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: 0 external session
cache hit(s)
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: 0 expired session(s)
retrieved
2016.05.11 16:13:26 LOG6[vWvoFT1DXuJ9x0eEfFnQBf]: SSL accepted: new session
negotiated
2016.05.11 16:13:26 LOG7[vWvoFT1DXuJ9x0eEfFnQBf]: Remove session callback
----------------------------------------------------
What I can see is tat memory grows with ~28K for every new session after
session cache was filled and never deallocates this memory.
In my production env. this really creates problems because after 2 weeks
stunnel fils all 32GB of server RAM.
*Anyone has encountered a similar problem? *
Of course the stunnel service restart clears the memory but I loose all
cache entries and is not acceptable.
After some code analysis between different versions of stunnel I can see
that between v5.26 ans v5.27 the ctx callbacks functions was changed.
In my tests with versions prior to 5.27 I can see that this memory problems
does not appear. See logs below:
---- stunnel v5.26 --------
2016.05.12 13:08:14 LOG5[ui]: stunnel 5.26 on x86_64-unknown-linux-gnu
platform
2016.05.12 13:08:14 LOG5[ui]: Compiled/running with OpenSSL 1.0.1e-fips 11
Feb 2013
stunnel 27402 0.0 0.0 117604 1316 ? Ss 13:08 0:00
/usr/local/bin/stunnel5
stunnel 27402 0.0 0.0 117672 2756 ? Ss 13:08 0:00
/usr/local/bin/stunnel5
stunnel 27402 0.0 0.0 117672 2804 ? Ss 13:08 0:00
/usr/local/bin/stunnel5
stunnel 27402 0.0 0.0 117672 2828 ? Ss 13:08 0:00
/usr/local/bin/stunnel5
stunnel 27402 0.0 0.0 117672 2868 ? Ss 13:08 0:00
/usr/local/bin/stunnel5
cache fill-up
2016.05.12 13:11:01 LOG7[FdNYw7uGlV9xNElZSPBfyh]: 0 session reuse(s)
2016.05.12 13:11:01 LOG7[FdNYw7uGlV9xNElZSPBfyh]: 3 internal session
cache item(s)
2016.05.12 13:11:01 LOG7[FdNYw7uGlV9xNElZSPBfyh]: 1 internal session
cache fill-up(s)
stunnel 27402 0.0 0.0 117672 2868 ? Ss 13:08 0:00
/usr/local/bin/stunnel5
stunnel 27402 0.0 0.0 117672 2868 ? Ss 13:08 0:00
/usr/local/bin/stunnel5
after 100 fill-ups
2016.05.12 13:13:55 LOG7[TWO1OFFPYvsW4qdjyJ0IZK]: SSL state (accept): SSLv3
flush data
2016.05.12 13:13:55 LOG7[TWO1OFFPYvsW4qdjyJ0IZK]: 107 server accept(s)
requested
2016.05.12 13:13:55 LOG7[TWO1OFFPYvsW4qdjyJ0IZK]: 107 server accept(s)
succeeded
2016.05.12 13:13:55 LOG7[TWO1OFFPYvsW4qdjyJ0IZK]: 0 server
renegotiation(s) requested
2016.05.12 13:13:55 LOG7[TWO1OFFPYvsW4qdjyJ0IZK]: 1 session reuse(s)
2016.05.12 13:13:55 LOG7[TWO1OFFPYvsW4qdjyJ0IZK]: 3 internal session
cache item(s)
2016.05.12 13:13:55 LOG7[TWO1OFFPYvsW4qdjyJ0IZK]: 102 internal session
cache fill-up(s)
2016.05.12 13:13:55 LOG7[TWO1OFFPYvsW4qdjyJ0IZK]: 0 internal session
cache miss(es)
2016.05.12 13:13:55 LOG7[TWO1OFFPYvsW4qdjyJ0IZK]: 0 external session
cache hit(s)
2016.05.12 13:13:55 LOG7[TWO1OFFPYvsW4qdjyJ0IZK]: 0 expired session(s)
retrieved
2016.05.12 13:13:55 LOG6[TWO1OFFPYvsW4qdjyJ0IZK]: SSL accepted: new session
negotiated
stunnel 27402 0.1 0.0 117672 2872 ? Ss 13:08 0:00
/usr/local/bin/stunnel5
after another 100 fill-ups
2016.05.12 13:19:03 LOG7[InwkBBOxJrfptxYx6wXTxU]: SSL state (accept): SSLv3
flush data
2016.05.12 13:19:03 LOG7[InwkBBOxJrfptxYx6wXTxU]: 207 server accept(s)
requested
2016.05.12 13:19:03 LOG7[InwkBBOxJrfptxYx6wXTxU]: 207 server accept(s)
succeeded
2016.05.12 13:19:03 LOG7[InwkBBOxJrfptxYx6wXTxU]: 0 server
renegotiation(s) requested
2016.05.12 13:19:03 LOG7[InwkBBOxJrfptxYx6wXTxU]: 1 session reuse(s)
2016.05.12 13:19:03 LOG7[InwkBBOxJrfptxYx6wXTxU]: 3 internal session
cache item(s)
2016.05.12 13:19:03 LOG7[InwkBBOxJrfptxYx6wXTxU]: 202 internal session
cache fill-up(s)
2016.05.12 13:19:03 LOG7[InwkBBOxJrfptxYx6wXTxU]: 0 internal session
cache miss(es)
2016.05.12 13:19:03 LOG7[InwkBBOxJrfptxYx6wXTxU]: 0 external session
cache hit(s)
2016.05.12 13:19:03 LOG7[InwkBBOxJrfptxYx6wXTxU]: 0 expired session(s)
retrieved
2016.05.12 13:19:03 LOG6[InwkBBOxJrfptxYx6wXTxU]: SSL accepted: new session
negotiated
stunnel 27402 0.0 0.0 117672 2872 ? Ss 13:08 0:01
/usr/local/bin/stunnel5
Code:
--->>> callbacks in v5.26 L605
*NOEXPORT int sess_new_cb(SSL *ssl, SSL_SESSION *sess) { unsigned char
*val, *val_tmp; ssize_t val_len; const unsigned char *session_id;
unsigned int session_id_length; val_len=i2d_SSL_SESSION(sess, NULL);
val_tmp=val=str_alloc((size_t)val_len); i2d_SSL_SESSION(sess,
&val_tmp);#if OPENSSL_VERSION_NUMBER>=0x0090800fL
session_id=SSL_SESSION_get_id(sess, &session_id_length);#else
session_id=(const unsigned char *)sess->session_id;
session_id_length=sess->session_id_length;#endif
cache_transfer(SSL_get_SSL_CTX(ssl), CACHE_CMD_NEW,
SSL_SESSION_get_timeout(sess), session_id, session_id_length, val,
(size_t)val_len, NULL, NULL); str_free(val); return 1; /* leave the
session in local cache for reuse */}NOEXPORT SSL_SESSION *sess_get_cb(SSL
*ssl, unsigned char *key, int key_len, int *do_copy) { unsigned
char *val, *val_tmp=NULL; ssize_t val_len=0; SSL_SESSION *sess;
*do_copy = 0; /* allow the session to be freed autmatically */
cache_transfer(SSL_get_SSL_CTX(ssl), CACHE_CMD_GET, 0, key,
(size_t)key_len, NULL, 0, &val, (size_t *)&val_len); if(!val)
return NULL; val_tmp=val; sess=d2i_SSL_SESSION(NULL,#if
OPENSSL_VERSION_NUMBER>=0x0090800fL (const unsigned char **)#endif
/* OpenSSL version >= 0.8.0 */ &val_tmp, val_len); str_free(val);*
--->>> callbacks in v5.32
/**************************************** session callbacks */
*NOEXPORT int sess_new_cb(SSL *ssl, SSL_SESSION *sess) { CLI *c;
s_log(LOG_DEBUG, "New session callback"); c=SSL_get_ex_data(ssl,
index_cli); if(c->opt->option.sessiond) cache_new(ssl, sess);
return 1; /* leave the session in local cache for reuse */}NOEXPORT
SSL_SESSION *sess_get_cb(SSL *ssl,#if
OPENSSL_VERSION_NUMBER>=0x10100000L const#endif unsigned char
*key, int key_len, int *do_copy) { CLI *c; s_log(LOG_DEBUG, "Get
session callback"); *do_copy=0; /* allow the session to be freed
automatically */ c=SSL_get_ex_data(ssl, index_cli);
if(c->opt->option.sessiond) return cache_get(ssl, key, key_len);
return NULL; /* no session to resume */}NOEXPORT void
sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess) { SERVICE_OPTIONS
*opt; s_log(LOG_DEBUG, "Remove session callback");
opt=SSL_CTX_get_ex_data(ctx, index_opt); if(opt->option.sessiond)
cache_remove(ctx, sess);}*
In production env. I have downgraded today at stunnel v5.26 and memory
seems to be OK (untill now).
Regards,
Adrian Irimescu