You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2019/11/20 07:18:57 UTC
[trafficserver] branch 9.0.x updated: set host name in TLS
extension for SNI Host check in service side with sni policy
verify_with_name_source.
This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new acc888b set host name in TLS extension for SNI Host check in service side with sni policy verify_with_name_source.
acc888b is described below
commit acc888b73abaf6c7bfa05ebeecd2c4812a67b52e
Author: xinli1 <xi...@linkedin.com>
AuthorDate: Tue Oct 22 10:04:52 2019 -0700
set host name in TLS extension for SNI Host check in service side with sni policy verify_with_name_source.
fix build error in autest
update document
fix wrong comment
(cherry picked from commit 48771056f71f85a3ac6b01f1fa10a7172c4bdc04)
---
doc/admin-guide/files/records.config.en.rst | 16 +++++++++++++++-
iocore/net/I_NetVConnection.h | 23 +++++++++++++++++++++++
iocore/net/P_UnixNetVConnection.h | 1 +
iocore/net/SSLNetVConnection.cc | 9 +++++----
iocore/net/quic/QUICTLS_openssl.cc | 3 ++-
proxy/http/HttpSM.cc | 11 +++++++++++
6 files changed, 57 insertions(+), 6 deletions(-)
diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst
index d9999df..56a5645 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -3473,7 +3473,21 @@ Client-Related Configuration
Indicate how the SNI value for the TLS connection to the origin is selected. By default it is
`host` which means the host header field value is used for the SNI. If `remap` is specified, the
- remapped origin name is used for the SNI value.
+ remapped origin name is used for the SNI value. If `verify_with_name_source` is specified, the
+ SNI will be the host header value and the name to check in the server certificate will be the
+ remap header value.
+ We have two names that could be used in the transaction host header and the SNI value to the
+ origin. These could be the host header from the client or the remap host name. Unless you have
+ pristine host header enabled, these are likely the same values.
+ If sni_policy = host, both the sni and the host header to origin will be the same.
+ If sni_policy = remap, the sni value with be the remap host name and the host header will be the
+ host header from the client.
+ In addition, We may want to set the SNI and host headers the same (makes some common web servers
+ happy), but the certificate served by the origin may have a name that corresponds to the remap
+ name. So instead of using the SNI name for the name check, we may want to use the remap name.
+ So if sni_policy = verify_with_name_source, the sni will be the host header value and the name to
+ check in the server certificate will be the remap header value.
+
.. ts:cv:: CONFIG proxy.config.ssl.client.TLSv1 INT 0
diff --git a/iocore/net/I_NetVConnection.h b/iocore/net/I_NetVConnection.h
index df0667f..bfe1137 100644
--- a/iocore/net/I_NetVConnection.h
+++ b/iocore/net/I_NetVConnection.h
@@ -192,6 +192,10 @@ struct NetVCOptions {
*/
ats_scoped_str ssl_servername;
+ /** Server host name from client's request to use for SNI data on an outbound connection.
+ */
+ ats_scoped_str sni_hostname;
+
/**
* Client certificate to use in response to OS's certificate request
*/
@@ -259,6 +263,20 @@ struct NetVCOptions {
}
self &
+ set_sni_hostname(const char *name, size_t len)
+ {
+ IpEndpoint ip;
+
+ // Literal IPv4 and IPv6 addresses are not permitted in "HostName".(rfc6066#section-3)
+ if (name && len && ats_ip_pton(std::string_view(name, len), &ip) != 0) {
+ sni_hostname = ats_strndup(name, len);
+ } else {
+ sni_hostname = nullptr;
+ }
+ return *this;
+ }
+
+ self &
operator=(self const &that)
{
if (&that != this) {
@@ -274,6 +292,7 @@ struct NetVCOptions {
*/
sni_servername = nullptr; // release any current name.
ssl_servername = nullptr;
+ sni_hostname = nullptr;
memcpy(static_cast<void *>(this), &that, sizeof(self));
if (that.sni_servername) {
sni_servername.release(); // otherwise we'll free the source string.
@@ -283,6 +302,10 @@ struct NetVCOptions {
ssl_servername.release(); // otherwise we'll free the source string.
this->ssl_servername = ats_strdup(that.ssl_servername);
}
+ if (that.sni_hostname) {
+ sni_hostname.release(); // otherwise we'll free the source string.
+ this->sni_hostname = ats_strdup(that.sni_hostname);
+ }
}
return *this;
}
diff --git a/iocore/net/P_UnixNetVConnection.h b/iocore/net/P_UnixNetVConnection.h
index 128f572..26d573d 100644
--- a/iocore/net/P_UnixNetVConnection.h
+++ b/iocore/net/P_UnixNetVConnection.h
@@ -68,6 +68,7 @@ NetVCOptions::reset()
sni_servername = nullptr;
ssl_servername = nullptr;
+ sni_hostname = nullptr;
ssl_client_cert_name = nullptr;
ssl_client_private_key_name = nullptr;
ssl_client_ca_cert_name = nullptr;
diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
index d5771f5..051c97a 100644
--- a/iocore/net/SSLNetVConnection.cc
+++ b/iocore/net/SSLNetVConnection.cc
@@ -1078,11 +1078,12 @@ SSLNetVConnection::sslStartHandShake(int event, int &err)
SSL_set_verify(this->ssl, SSL_VERIFY_PEER, verify_callback);
- if (this->options.sni_servername) {
- if (SSL_set_tlsext_host_name(this->ssl, this->options.sni_servername)) {
- Debug("ssl", "using SNI name '%s' for client handshake", this->options.sni_servername.get());
+ ats_scoped_str &tlsext_host_name = this->options.sni_hostname ? this->options.sni_hostname : this->options.sni_servername;
+ if (tlsext_host_name) {
+ if (SSL_set_tlsext_host_name(this->ssl, tlsext_host_name)) {
+ Debug("ssl", "using SNI name '%s' for client handshake", tlsext_host_name.get());
} else {
- Debug("ssl.error", "failed to set SNI name '%s' for client handshake", this->options.sni_servername.get());
+ Debug("ssl.error", "failed to set SNI name '%s' for client handshake", tlsext_host_name.get());
SSL_INCREMENT_DYN_STAT(ssl_sni_name_set_failure);
}
}
diff --git a/iocore/net/quic/QUICTLS_openssl.cc b/iocore/net/quic/QUICTLS_openssl.cc
index 0eabec1..75e9842 100644
--- a/iocore/net/quic/QUICTLS_openssl.cc
+++ b/iocore/net/quic/QUICTLS_openssl.cc
@@ -405,7 +405,8 @@ QUICTLS::QUICTLS(QUICPacketProtectionKeyInfo &pp_key_info, SSL_CTX *ssl_ctx, Net
SSL_set_alpn_protos(this->_ssl, reinterpret_cast<const unsigned char *>(netvc_options.alpn_protos.data()),
netvc_options.alpn_protos.size());
- SSL_set_tlsext_host_name(this->_ssl, netvc_options.sni_servername.get());
+ const ats_scoped_str &tlsext_host_name = netvc_options.sni_hostname ? netvc_options.sni_hostname : netvc_options.sni_servername;
+ SSL_set_tlsext_host_name(this->_ssl, tlsext_host_name.get());
} else {
SSL_set_accept_state(this->_ssl);
}
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 45d3e5b..2450d2b 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -5007,6 +5007,17 @@ HttpSM::do_http_server_open(bool raw)
if (t_state.txn_conf->ssl_client_sni_policy != nullptr && !strcmp(t_state.txn_conf->ssl_client_sni_policy, "remap")) {
len = strlen(t_state.server_info.name);
opt.set_sni_servername(t_state.server_info.name, len);
+ } else if (t_state.txn_conf->ssl_client_sni_policy != nullptr &&
+ !strcmp(t_state.txn_conf->ssl_client_sni_policy, "verify_with_name_source")) {
+ // the same with "remap" policy to set sni_servername
+ len = strlen(t_state.server_info.name);
+ opt.set_sni_servername(t_state.server_info.name, len);
+
+ // also set sni_hostname with host header from server request in this policy
+ const char *host = t_state.hdr_info.server_request.host_get(&len);
+ if (host && len > 0) {
+ opt.set_sni_hostname(host, len);
+ }
} else { // Do the default of host header for SNI
const char *host = t_state.hdr_info.server_request.host_get(&len);
if (host && len > 0) {