Hi All,
At first I would like to thank Marzena Trojnara for the useful program!
Occurrence of support SNI has especially interest. I have decided to use the given possibility, but have detect pair of bugs which has independently successfully solved.
To begin with I dump part of my config:
[virtual_server] accept = 443 connect = localhost:1081
cert = /usr/local/etc/stunnel/alexCA.crt key = /usr/local/etc/stunnel/alexCA.key
; need peer verification for default access verify = 2 CAfile = /usr/local/etc/stunnel/alexCA.crt
; use restricted access form some target services [socks5] sni = virtual_server:localhost sni = virtual_server:89.250.5.185 sni = virtual_server:127.0.0.1 sni = virtual_server:server
cert = /usr/local/etc/stunnel/alexCA.crt key = /usr/local/etc/stunnel/alexCA.key
verify = 2 CAfile = /usr/local/etc/stunnel/alexCA.crt connect = localhost:1081
; public service [dreamhub_ru] sni = virtual_server:dreamhub.ru sni = virtual_server:pad.dreamhub.ru
cert = /usr/local/etc/stunnel/dreamhub.cer key = /usr/local/etc/stunnel/dreamhub.pem connect = localhost:80
I want to use stunnel on 443rd port for ssl-socks5 service with peer certificates verification and use public https web-service (https://dreamhub.ru).
And so it has appeared that value for "verify" are always used from global section (in my case [virtual_server]), and values of "verify" parameters from virtual services sections aren't used.
Problem it has appeared that in the SNI check callback
static int servername_cb(SSL *ssl, int *ad, void *arg) ... for(list=section->servername_list_head; list; list=list->next) if(!strcasecmp(servername, list->servername)) { c=SSL_get_ex_data(ssl, cli_index); c->opt=list->opt; SSL_set_SSL_CTX(ssl, c->opt->ctx); s_log(LOG_NOTICE, "SNI: switched to section %s", c->opt->servname);
SSL_set_SSL_CTX(ssl, c->opt->ctx); does not copy ctx->verify_mode
(SSL*)s->verify_mode=ctx->verify_mode;
It has been solved by explicit calling SSL_set_verify
*** ctx.c 2011-09-07 14:43:50.000000000 +0400 --- ctx.c_patched 2011-09-10 01:12:48.000000000 +0400 *************** *** 156,161 **** --- 156,162 ---- c=SSL_get_ex_data(ssl, cli_index); c->opt=list->opt; SSL_set_SSL_CTX(ssl, c->opt->ctx); + SSL_set_verify(ssl, SSL_CTX_get_verify_mode(c->opt->ctx), +NULL); s_log(LOG_NOTICE, "SNI: switched to section %s", c->opt->servname); #ifdef USE_LIBWRAP
The second moment concerns uses stunnel as client through HTTPS a proxy (protocol=connect). All works perfectly, only it has appeared that value for SNI used from "connect" parameter instead of value of "protocolHost". On a code all is quite obvious:
if(c->opt->host_name) { s_log(LOG_DEBUG, "SNI: host name: %s", c->opt->host_name); if(!SSL_set_tlsext_host_name(c->ssl, c->opt->host_name)) { sslerror("SSL_set_tlsext_host_name"); longjmp(c->err, 1); } }
I solved it such:
*** options.c 2011-09-07 20:38:56.000000000 +0400 --- options.c_patch 2011-09-10 16:34:56.882619049 +0400 *************** *** 695,700 **** --- 695,705 ---- s_log(LOG_INFO, "Cannot resolve '%s' - delaying DNS lookup", arg); section->option.delayed_lookup=1; } + + /* check - is host_name already filled */ + if (section->host_name != NULL) + return NULL; /* OK */ + tmpstr=strrchr(arg, ':'); if(tmpstr) { *tmpstr='\0'; *************** *** 1077,1082 **** --- 1082,1095 ---- if(strcasecmp(opt, "protocolHost")) break; section->protocol_host=str_dup_err(arg); + + /* Overwrite section->host_nam because of + protocolHost should be used for client SNI */ + tmpstr=strrchr(arg, ':'); + if(tmpstr) { + *tmpstr='\0'; + section->host_name=str_dup_err(arg); + } return NULL; /* OK */ case CMD_DEFAULT: break;
I think that the given changes can be useful for other :)
/ Alexey Drozdov