spdycat, shrpx: TLS SNI enhancements

shrpx:
* Added an option to set the TLS SNI extension between shrpx and the
  origin on the command line

spdycat:
* If the user set an explicit host header ( using --headers ) use that
  name for the TLS SNI extension.
* Added the handshake completion time to the verbose output
* The gettimeofday call in get_time was using the incorrect structure
  ( I believe )
* In update_html_parser it was submitting the request regardless of
  the return value of add_request.

Patch from Stephen Ludin
This commit is contained in:
Tatsuhiro Tsujikawa 2013-03-29 22:06:33 +09:00
parent e543441ccc
commit a9f475fb88
6 changed files with 50 additions and 8 deletions

View File

@ -520,7 +520,10 @@ void print_help(std::ostream& out)
<< " key file. Shrpx will choose certificates\n" << " key file. Shrpx will choose certificates\n"
<< " based on the hostname indicated by client\n" << " based on the hostname indicated by client\n"
<< " using TLS SNI extension. This option can be\n" << " using TLS SNI extension. This option can be\n"
<< " used multiple times.\n" << " --backend-tls-sni-field=<HOST>\n"
<< " Explicitly set the content of the TLS SNI\n"
<< " extension. This will default to the backend\n"
<< " HOST name.\n"
<< "\n" << "\n"
<< " SPDY:\n" << " SPDY:\n"
<< " -c, --spdy-max-concurrent-streams=<NUM>\n" << " -c, --spdy-max-concurrent-streams=<NUM>\n"
@ -659,6 +662,7 @@ int main(int argc, char **argv)
{"backend-spdy-proto", required_argument, &flag, 28}, {"backend-spdy-proto", required_argument, &flag, 28},
{"frontend-spdy-no-tls", no_argument, &flag, 29}, {"frontend-spdy-no-tls", no_argument, &flag, 29},
{"frontend-spdy-proto", required_argument, &flag, 30}, {"frontend-spdy-proto", required_argument, &flag, 30},
{"backend-tls-sni-field", required_argument, &flag, 31},
{0, 0, 0, 0 } {0, 0, 0, 0 }
}; };
int option_index = 0; int option_index = 0;
@ -838,6 +842,12 @@ int main(int argc, char **argv)
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_FRONTEND_SPDY_PROTO, cmdcfgs.push_back(std::make_pair(SHRPX_OPT_FRONTEND_SPDY_PROTO,
optarg)); optarg));
break; break;
case 31:
// --backend-tls-sni-field
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_BACKEND_TLS_SNI_FIELD,
optarg));
break;
default: default:
break; break;
} }

View File

@ -79,6 +79,7 @@ const char SHRPX_OPT_FRONTEND_SPDY_NO_TLS[] = "frontend-spdy-no-tls";
const char SHRPX_OPT_FRONTEND_SPDY_PROTO[] = "frontend-spdy-proto"; const char SHRPX_OPT_FRONTEND_SPDY_PROTO[] = "frontend-spdy-proto";
const char SHRPX_OPT_BACKEND_SPDY_NO_TLS[] = "backend-spdy-no-tls"; const char SHRPX_OPT_BACKEND_SPDY_NO_TLS[] = "backend-spdy-no-tls";
const char SHRPX_OPT_BACKEND_SPDY_PROTO[] = "backend-spdy-proto"; const char SHRPX_OPT_BACKEND_SPDY_PROTO[] = "backend-spdy-proto";
const char SHRPX_OPT_BACKEND_TLS_SNI_FIELD[] = "backend-tls-sni-field";
const char SHRPX_OPT_PID_FILE[] = "pid-file"; const char SHRPX_OPT_PID_FILE[] = "pid-file";
const char SHRPX_OPT_USER[] = "user"; const char SHRPX_OPT_USER[] = "user";
const char SHRPX_OPT_SYSLOG[] = "syslog"; const char SHRPX_OPT_SYSLOG[] = "syslog";
@ -300,6 +301,8 @@ int parse_config(const char *opt, const char *optarg)
} else { } else {
mod_config()->spdy_downstream_version = version; mod_config()->spdy_downstream_version = version;
} }
} else if(util::strieq(opt, SHRPX_OPT_BACKEND_TLS_SNI_FIELD)) {
set_config_str(&mod_config()->backend_tls_sni_name, optarg);
} else if(util::strieq(opt, SHRPX_OPT_PID_FILE)) { } else if(util::strieq(opt, SHRPX_OPT_PID_FILE)) {
set_config_str(&mod_config()->pid_file, optarg); set_config_str(&mod_config()->pid_file, optarg);
} else if(util::strieq(opt, SHRPX_OPT_USER)) { } else if(util::strieq(opt, SHRPX_OPT_USER)) {

View File

@ -84,6 +84,7 @@ extern const char SHRPX_OPT_CACERT[];
extern const char SHRPX_OPT_BACKEND_IPV4[]; extern const char SHRPX_OPT_BACKEND_IPV4[];
extern const char SHRPX_OPT_BACKEND_IPV6[]; extern const char SHRPX_OPT_BACKEND_IPV6[];
extern const char SHRPX_OPT_BACKEND_HTTP_PROXY_URI[]; extern const char SHRPX_OPT_BACKEND_HTTP_PROXY_URI[];
extern const char SHRPX_OPT_BACKEND_TLS_SNI_FIELD[];
union sockaddr_union { union sockaddr_union {
sockaddr sa; sockaddr sa;
@ -134,6 +135,7 @@ struct Config {
uint16_t spdy_upstream_version; uint16_t spdy_upstream_version;
bool spdy_downstream_no_tls; bool spdy_downstream_no_tls;
uint16_t spdy_downstream_version; uint16_t spdy_downstream_version;
char *backend_tls_sni_name;
char *pid_file; char *pid_file;
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;

View File

@ -402,11 +402,19 @@ int SpdySession::initiate_connection()
return -1; return -1;
} }
if(!ssl::numeric_host(get_config()->downstream_host)) { const char *sni_name = 0;
if ( get_config()->backend_tls_sni_name ) {
sni_name = get_config()->backend_tls_sni_name;
}
else {
sni_name = get_config()->downstream_host;
}
if(!ssl::numeric_host(sni_name)) {
// TLS extensions: SNI. There is no documentation about the return // TLS extensions: SNI. There is no documentation about the return
// code for this function (actually this is macro wrapping SSL_ctrl // code for this function (actually this is macro wrapping SSL_ctrl
// at the time of this writing). // at the time of this writing).
SSL_set_tlsext_host_name(ssl_, get_config()->downstream_host); SSL_set_tlsext_host_name(ssl_, sni_name);
} }
// If state_ == PROXY_CONNECTED, we has connected to the proxy // If state_ == PROXY_CONNECTED, we has connected to the proxy
// using fd_ and tunnel has been established. // using fd_ and tunnel has been established.

View File

@ -396,9 +396,10 @@ void update_html_parser(SpdySession *spdySession, Request *req,
fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_HOST) && fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_HOST) &&
porteq(uri.c_str(), u, req->uri.c_str(), req->u)) { porteq(uri.c_str(), u, req->uri.c_str(), req->u)) {
// No POST data for assets // No POST data for assets
spdySession->add_request(uri, u, 0, 0, req->level+1); if ( spdySession->add_request(uri, u, 0, 0, req->level+1) ) {
submit_request(*spdySession->sc, spdySession->hostport, config.headers, submit_request(*spdySession->sc, spdySession->hostport, config.headers,
spdySession->reqvec.back()); spdySession->reqvec.back());
}
} }
} }
req->html_parser->clear_links(); req->html_parser->clear_links();
@ -721,7 +722,20 @@ int communicate(const std::string& host, uint16_t port,
result = -1; result = -1;
goto fin; goto fin;
} }
if (!SSL_set_tlsext_host_name(ssl, host.c_str())) {
// If the user overrode the host header, use that value for the
// SNI extension
const char *host_string = 0;
std::map<std::string,std::string>::const_iterator i =
config.headers.find( "Host" );
if ( i != config.headers.end() ) {
host_string = (*i).second.c_str();
}
else {
host_string = host.c_str();
}
if (!SSL_set_tlsext_host_name(ssl, host_string)) {
std::cerr << ERR_error_string(ERR_get_error(), 0) << std::endl; std::cerr << ERR_error_string(ERR_get_error(), 0) << std::endl;
result = -1; result = -1;
goto fin; goto fin;
@ -739,6 +753,11 @@ int communicate(const std::string& host, uint16_t port,
} }
} }
if ( config.verbose ) {
print_timer();
std::cout << " Handshake complete" << std::endl;
}
spdySession.record_handshake_time(); spdySession.record_handshake_time();
spdy_version = spdylay_npn_get_version( spdy_version = spdylay_npn_get_version(
reinterpret_cast<const unsigned char*>(next_proto.c_str()), reinterpret_cast<const unsigned char*>(next_proto.c_str()),

View File

@ -916,7 +916,7 @@ int get_time(timeval *tv)
tv->tv_sec = ts.tv_sec; tv->tv_sec = ts.tv_sec;
tv->tv_usec = ts.tv_nsec/1000; tv->tv_usec = ts.tv_nsec/1000;
#else // !HAVE_CLOCK_GETTIME #else // !HAVE_CLOCK_GETTIME
rv = gettimeofday(&base_tv, 0); rv = gettimeofday(tv, 0);
#endif // !HAVE_CLOCK_GETTIME #endif // !HAVE_CLOCK_GETTIME
return rv; return rv;
} }