nghttpx: Add sni keyword to --backend option
The --backend-tls-sni-field is deprecated in favor of sni keyword. --backend-tls-sni-field still works, and it overrides all sni keyword in --backend option. But it will be removed in the future release.
This commit is contained in:
parent
99f7e7e2a5
commit
fd801864e3
32
src/shrpx.cc
32
src/shrpx.cc
|
@ -1263,13 +1263,13 @@ Connections:
|
||||||
|
|
||||||
Several parameters <PARAM> are accepted after <PATTERN>.
|
Several parameters <PARAM> are accepted after <PATTERN>.
|
||||||
The parameters are delimited by ";". The available
|
The parameters are delimited by ";". The available
|
||||||
parameters are: "proto=<PROTO>", "tls", "fall=<N>", and
|
parameters are: "proto=<PROTO>", "tls",
|
||||||
"rise=<N>". The parameter consists of keyword, and
|
"sni=<SNI_HOST>", "fall=<N>", and "rise=<N>". The
|
||||||
optionally followed by "=" and value. For example, the
|
parameter consists of keyword, and optionally followed
|
||||||
parameter "proto=h2" consists of the keyword "proto" and
|
by "=" and value. For example, the parameter "proto=h2"
|
||||||
value "h2". The parameter "tls" consists of the keyword
|
consists of the keyword "proto" and value "h2". The
|
||||||
"tls" without value. Each parameter is described as
|
parameter "tls" consists of the keyword "tls" without
|
||||||
follows.
|
value. Each parameter is described as follows.
|
||||||
|
|
||||||
The backend application protocol can be specified using
|
The backend application protocol can be specified using
|
||||||
optional "proto" keyword, and in the form of
|
optional "proto" keyword, and in the form of
|
||||||
|
@ -1284,6 +1284,10 @@ Connections:
|
||||||
TLS can be enabled by specifying optional "tls" keyword.
|
TLS can be enabled by specifying optional "tls" keyword.
|
||||||
TLS is not enabled by default.
|
TLS is not enabled by default.
|
||||||
|
|
||||||
|
With "sni=<SNI_HOST>" parameter, it can override the TLS
|
||||||
|
SNI field value with given <SNI_HOST>. This will
|
||||||
|
default to the backend <HOST> name
|
||||||
|
|
||||||
The feature to detect whether backend is online or
|
The feature to detect whether backend is online or
|
||||||
offline can be enabled using optional "fall" and "rise"
|
offline can be enabled using optional "fall" and "rise"
|
||||||
parameters. Using "fall=<N>" parameter, if nghttpx
|
parameters. Using "fall=<N>" parameter, if nghttpx
|
||||||
|
@ -1503,9 +1507,6 @@ SSL/TLS:
|
||||||
indicated by client using TLS SNI extension. This
|
indicated by client using TLS SNI extension. This
|
||||||
option can be used multiple times. To make OCSP
|
option can be used multiple times. To make OCSP
|
||||||
stapling work, <CERTPATH> must be absolute path.
|
stapling work, <CERTPATH> must be absolute path.
|
||||||
--backend-tls-sni-field=<HOST>
|
|
||||||
Explicitly set the content of the TLS SNI extension.
|
|
||||||
This will default to the backend HOST name.
|
|
||||||
--dh-param-file=<PATH>
|
--dh-param-file=<PATH>
|
||||||
Path to file that contains DH parameters in PEM format.
|
Path to file that contains DH parameters in PEM format.
|
||||||
Without this option, DHE cipher suites are not
|
Without this option, DHE cipher suites are not
|
||||||
|
@ -2168,6 +2169,17 @@ void process_options(int argc, char **argv,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// backward compatibility: override all SNI fields with the option
|
||||||
|
// value --backend-tls-sni-field
|
||||||
|
if (!tlsconf.backend_sni_name.empty()) {
|
||||||
|
auto &sni = tlsconf.backend_sni_name;
|
||||||
|
for (auto &addr_group : addr_groups) {
|
||||||
|
for (auto &addr : addr_group.addrs) {
|
||||||
|
addr.sni = sni;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
LOG(INFO) << "Resolving backend address";
|
LOG(INFO) << "Resolving backend address";
|
||||||
}
|
}
|
||||||
|
|
|
@ -644,6 +644,7 @@ int parse_upstream_params(UpstreamParams &out, const StringRef &src_params) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
struct DownstreamParams {
|
struct DownstreamParams {
|
||||||
|
StringRef sni;
|
||||||
size_t fall;
|
size_t fall;
|
||||||
size_t rise;
|
size_t rise;
|
||||||
shrpx_proto proto;
|
shrpx_proto proto;
|
||||||
|
@ -709,6 +710,8 @@ int parse_downstream_params(DownstreamParams &out,
|
||||||
out.tls = true;
|
out.tls = true;
|
||||||
} else if (util::strieq_l("no-tls", param)) {
|
} else if (util::strieq_l("no-tls", param)) {
|
||||||
out.tls = false;
|
out.tls = false;
|
||||||
|
} else if (util::istarts_with_l(param, "sni=")) {
|
||||||
|
out.sni = StringRef{first + str_size("sni="), end};
|
||||||
} else if (!param.empty()) {
|
} else if (!param.empty()) {
|
||||||
LOG(ERROR) << "backend: " << param << ": unknown keyword";
|
LOG(ERROR) << "backend: " << param << ": unknown keyword";
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -750,6 +753,7 @@ int parse_mapping(DownstreamAddrConfig addr, const StringRef &src_pattern,
|
||||||
|
|
||||||
addr.fall = params.fall;
|
addr.fall = params.fall;
|
||||||
addr.rise = params.rise;
|
addr.rise = params.rise;
|
||||||
|
addr.sni = ImmutableString{std::begin(params.sni), std::end(params.sni)};
|
||||||
|
|
||||||
for (const auto &raw_pattern : mapping) {
|
for (const auto &raw_pattern : mapping) {
|
||||||
auto done = false;
|
auto done = false;
|
||||||
|
@ -2050,6 +2054,9 @@ int parse_config(const StringRef &opt, const StringRef &optarg,
|
||||||
"default. See also " << SHRPX_OPT_BACKEND_TLS;
|
"default. See also " << SHRPX_OPT_BACKEND_TLS;
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD:
|
case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD:
|
||||||
|
LOG(WARN) << opt << ": deprecated. Use sni keyword in --backend option. "
|
||||||
|
"For now, all sni values of all backends are "
|
||||||
|
"overridden by the given value " << optarg;
|
||||||
mod_config()->tls.backend_sni_name = optarg.str();
|
mod_config()->tls.backend_sni_name = optarg.str();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -327,6 +327,8 @@ struct DownstreamAddrConfig {
|
||||||
// <HOST>:<PORT>. This does not treat 80 and 443 specially. If
|
// <HOST>:<PORT>. This does not treat 80 and 443 specially. If
|
||||||
// |host_unix| is true, this is "localhost".
|
// |host_unix| is true, this is "localhost".
|
||||||
ImmutableString hostport;
|
ImmutableString hostport;
|
||||||
|
// hostname sent as SNI field
|
||||||
|
ImmutableString sni;
|
||||||
size_t fall;
|
size_t fall;
|
||||||
size_t rise;
|
size_t rise;
|
||||||
// backend port. 0 if |host_unix| is true.
|
// backend port. 0 if |host_unix| is true.
|
||||||
|
|
|
@ -360,9 +360,8 @@ int Http2Session::initiate_connection() {
|
||||||
|
|
||||||
conn_.set_ssl(ssl);
|
conn_.set_ssl(ssl);
|
||||||
|
|
||||||
auto sni_name = !get_config()->tls.backend_sni_name.empty()
|
auto sni_name =
|
||||||
? StringRef(get_config()->tls.backend_sni_name)
|
addr_->sni.empty() ? StringRef{addr_->host} : StringRef{addr_->sni};
|
||||||
: StringRef(addr_->host);
|
|
||||||
|
|
||||||
if (!util::numeric_host(sni_name.c_str())) {
|
if (!util::numeric_host(sni_name.c_str())) {
|
||||||
// TLS extensions: SNI. There is no documentation about the return
|
// TLS extensions: SNI. There is no documentation about the return
|
||||||
|
|
|
@ -239,9 +239,8 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
|
||||||
addr_ = &addr;
|
addr_ = &addr;
|
||||||
|
|
||||||
if (ssl_ctx_) {
|
if (ssl_ctx_) {
|
||||||
auto sni_name = !get_config()->tls.backend_sni_name.empty()
|
auto sni_name =
|
||||||
? StringRef(get_config()->tls.backend_sni_name)
|
addr_->sni.empty() ? StringRef{addr_->host} : StringRef{addr_->sni};
|
||||||
: StringRef(addr_->host);
|
|
||||||
if (!util::numeric_host(sni_name.c_str())) {
|
if (!util::numeric_host(sni_name.c_str())) {
|
||||||
SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.c_str());
|
SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,9 +192,8 @@ int LiveCheck::initiate_connection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssl_ctx_) {
|
if (ssl_ctx_) {
|
||||||
auto sni_name = !get_config()->tls.backend_sni_name.empty()
|
auto sni_name =
|
||||||
? StringRef(get_config()->tls.backend_sni_name)
|
addr_->sni.empty() ? StringRef{addr_->host} : StringRef{addr_->sni};
|
||||||
: StringRef(addr_->host);
|
|
||||||
if (!util::numeric_host(sni_name.c_str())) {
|
if (!util::numeric_host(sni_name.c_str())) {
|
||||||
SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.c_str());
|
SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1064,10 +1064,8 @@ int check_cert(SSL *ssl, const Address *addr, const StringRef &host) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_cert(SSL *ssl, const DownstreamAddr *addr) {
|
int check_cert(SSL *ssl, const DownstreamAddr *addr) {
|
||||||
auto &backend_sni_name = get_config()->tls.backend_sni_name;
|
auto hostname =
|
||||||
|
addr->sni.empty() ? StringRef{addr->host} : StringRef{addr->sni};
|
||||||
auto hostname = !backend_sni_name.empty() ? StringRef(backend_sni_name)
|
|
||||||
: StringRef(addr->host);
|
|
||||||
return check_cert(ssl, &addr->addr, hostname);
|
return check_cert(ssl, &addr->addr, hostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ bool match_shared_downstream_addr(
|
||||||
|
|
||||||
auto &b = rhs->addrs[i];
|
auto &b = rhs->addrs[i];
|
||||||
if (a.host == b.host && a.port == b.port && a.host_unix == b.host_unix &&
|
if (a.host == b.host && a.port == b.port && a.host_unix == b.host_unix &&
|
||||||
a.fall == b.fall && a.rise == b.rise) {
|
a.sni == b.sni && a.fall == b.fall && a.rise == b.rise) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,7 @@ Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
|
||||||
dst_addr.hostport = src_addr.hostport;
|
dst_addr.hostport = src_addr.hostport;
|
||||||
dst_addr.port = src_addr.port;
|
dst_addr.port = src_addr.port;
|
||||||
dst_addr.host_unix = src_addr.host_unix;
|
dst_addr.host_unix = src_addr.host_unix;
|
||||||
|
dst_addr.sni = src_addr.sni;
|
||||||
dst_addr.fall = src_addr.fall;
|
dst_addr.fall = src_addr.fall;
|
||||||
dst_addr.rise = src_addr.rise;
|
dst_addr.rise = src_addr.rise;
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,9 @@ struct DownstreamAddr {
|
||||||
// true if |host| contains UNIX domain socket path.
|
// true if |host| contains UNIX domain socket path.
|
||||||
bool host_unix;
|
bool host_unix;
|
||||||
|
|
||||||
|
// sni field to send remote server if TLS is enabled.
|
||||||
|
ImmutableString sni;
|
||||||
|
|
||||||
std::unique_ptr<ConnectBlocker> connect_blocker;
|
std::unique_ptr<ConnectBlocker> connect_blocker;
|
||||||
std::unique_ptr<LiveCheck> live_check;
|
std::unique_ptr<LiveCheck> live_check;
|
||||||
size_t fall;
|
size_t fall;
|
||||||
|
|
|
@ -254,15 +254,15 @@ public:
|
||||||
|
|
||||||
ImmutableString() : len(0), base("") {}
|
ImmutableString() : len(0), base("") {}
|
||||||
ImmutableString(const char *s, size_t slen)
|
ImmutableString(const char *s, size_t slen)
|
||||||
: len(slen), base(copystr(s, len)) {}
|
: len(slen), base(copystr(s, s + len)) {}
|
||||||
ImmutableString(const char *s) : len(strlen(s)), base(copystr(s, len)) {}
|
ImmutableString(const char *s) : len(strlen(s)), base(copystr(s, s + len)) {}
|
||||||
ImmutableString(const std::string &s)
|
ImmutableString(const std::string &s)
|
||||||
: len(s.size()), base(copystr(s.c_str(), s.size())) {}
|
: len(s.size()), base(copystr(std::begin(s), std::end(s))) {}
|
||||||
template <typename InputIt>
|
template <typename InputIt>
|
||||||
ImmutableString(InputIt first, InputIt last)
|
ImmutableString(InputIt first, InputIt last)
|
||||||
: len(std::distance(first, last)), base(copystr(first, len)) {}
|
: len(std::distance(first, last)), base(copystr(first, last)) {}
|
||||||
ImmutableString(const ImmutableString &other)
|
ImmutableString(const ImmutableString &other)
|
||||||
: len(other.len), base(copystr(other.base, other.len)) {}
|
: len(other.len), base(copystr(std::begin(other), std::end(other))) {}
|
||||||
ImmutableString(ImmutableString &&other) noexcept : len(other.len),
|
ImmutableString(ImmutableString &&other) noexcept : len(other.len),
|
||||||
base(other.base) {
|
base(other.base) {
|
||||||
other.len = 0;
|
other.len = 0;
|
||||||
|
@ -282,7 +282,7 @@ public:
|
||||||
delete[] base;
|
delete[] base;
|
||||||
}
|
}
|
||||||
len = other.len;
|
len = other.len;
|
||||||
base = copystr(other.base, other.len);
|
base = copystr(std::begin(other), std::end(other));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
ImmutableString &operator=(ImmutableString &&other) noexcept {
|
ImmutableString &operator=(ImmutableString &&other) noexcept {
|
||||||
|
@ -325,12 +325,12 @@ public:
|
||||||
const_reference operator[](size_type pos) const { return *(base + pos); }
|
const_reference operator[](size_type pos) const { return *(base + pos); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *copystr(const char *s, size_t slen) {
|
template <typename InputIt> const char *copystr(InputIt first, InputIt last) {
|
||||||
if (slen == 0) {
|
if (first == last) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
auto res = new char[slen + 1];
|
auto res = new char[std::distance(first, last) + 1];
|
||||||
*std::copy_n(s, slen, res) = '\0';
|
*std::copy(first, last, res) = '\0';
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue