[stunnel-users] SNI and some troubles solving
Alexey Drozdov
anyquist at yandex.ru
Sat Sep 10 15:53:04 CEST 2011
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
More information about the stunnel-users
mailing list