Commit 025ec851 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa Committed by GitHub

Merge pull request #790 from nghttp2/nghttpx-backend-frontend-tls-parameter

nghttpx: Add frontend-tls parameter to backend to require client TLS
parents bd97886d 0b1ddad6
...@@ -1602,12 +1602,12 @@ Connections: ...@@ -1602,12 +1602,12 @@ Connections:
The parameters are delimited by ";". The available The parameters are delimited by ";". The available
parameters are: "proto=<PROTO>", "tls", parameters are: "proto=<PROTO>", "tls",
"sni=<SNI_HOST>", "fall=<N>", "rise=<N>", "sni=<SNI_HOST>", "fall=<N>", "rise=<N>",
"affinity=<METHOD>", and "dns". The parameter consists "affinity=<METHOD>", "dns", and "frontend-tls". The
of keyword, and optionally followed by "=" and value. parameter consists of keyword, and optionally followed
For example, the parameter "proto=h2" consists of the by "=" and value. For example, the parameter "proto=h2"
keyword "proto" and value "h2". The parameter "tls" consists of the keyword "proto" and value "h2". The
consists of the keyword "tls" without value. Each parameter "tls" consists of the keyword "tls" without
parameter is described as 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" parameter, and in the form of optional "proto" parameter, and in the form of
...@@ -1664,6 +1664,17 @@ Connections: ...@@ -1664,6 +1664,17 @@ Connections:
backend host name at start up, or reloading backend host name at start up, or reloading
configuration is skipped. configuration is skipped.
If "frontend-tls" parameter is used, the matched backend
requires frontend TLS connection. In other words, even
if pattern is matched, frontend connection is not TLS
protected, the request is forwarded to one of catch-all
backends. For this reason, catch-all backend cannot
have "frontend-tls" parameter. If at least one backend
has "frontend-tls" parameter, this feature is enabled
for all backend servers sharing the same <PATTERN>. It
is advised to set "frontend-tls" parameter to all
backends explicitly if this feature is desired.
Since ";" and ":" are used as delimiter, <PATTERN> must Since ";" and ":" are used as delimiter, <PATTERN> must
not contain these characters. Since ";" has special not contain these characters. Since ";" has special
meaning in shell, the option value must be quoted. meaning in shell, the option value must be quoted.
......
...@@ -1008,6 +1008,13 @@ ClientHandler::get_downstream_connection(Downstream *downstream) { ...@@ -1008,6 +1008,13 @@ ClientHandler::get_downstream_connection(Downstream *downstream) {
CLOG(INFO, this) << "Downstream address group_idx: " << group_idx; CLOG(INFO, this) << "Downstream address group_idx: " << group_idx;
} }
if (groups[group_idx]->shared_addr->require_upstream_tls && !conn_.tls.ssl) {
CLOG(INFO, this) << "Downstream address group " << group_idx
<< " requires frontend TLS connection. Send request to "
"catch-all group.";
group_idx = catch_all;
}
auto &group = groups[group_idx]; auto &group = groups[group_idx];
auto &shared_addr = group->shared_addr; auto &shared_addr = group->shared_addr;
......
...@@ -732,6 +732,7 @@ struct DownstreamParams { ...@@ -732,6 +732,7 @@ struct DownstreamParams {
shrpx_session_affinity affinity; shrpx_session_affinity affinity;
bool tls; bool tls;
bool dns; bool dns;
bool frontend_tls;
}; };
namespace { namespace {
...@@ -807,6 +808,8 @@ int parse_downstream_params(DownstreamParams &out, ...@@ -807,6 +808,8 @@ int parse_downstream_params(DownstreamParams &out,
} }
} else if (util::strieq_l("dns", param)) { } else if (util::strieq_l("dns", param)) {
out.dns = true; out.dns = true;
} else if (util::strieq_l("frontend-tls", param)) {
out.frontend_tls = true;
} else if (!param.empty()) { } else if (!param.empty()) {
LOG(ERROR) << "backend: " << param << ": unknown keyword"; LOG(ERROR) << "backend: " << param << ": unknown keyword";
return -1; return -1;
...@@ -899,6 +902,11 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr, ...@@ -899,6 +902,11 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
if (params.affinity != AFFINITY_NONE) { if (params.affinity != AFFINITY_NONE) {
g.affinity = params.affinity; g.affinity = params.affinity;
} }
// If at least one backend requires frontend TLS connection,
// enable it for all backends sharing the same pattern.
if (params.frontend_tls) {
g.require_upstream_tls = true;
}
g.addrs.push_back(addr); g.addrs.push_back(addr);
done = true; done = true;
break; break;
...@@ -913,6 +921,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr, ...@@ -913,6 +921,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
auto &g = addr_groups.back(); auto &g = addr_groups.back();
g.addrs.push_back(addr); g.addrs.push_back(addr);
g.affinity = params.affinity; g.affinity = params.affinity;
g.require_upstream_tls = params.frontend_tls;
if (pattern[0] == '*') { if (pattern[0] == '*') {
// wildcard pattern // wildcard pattern
...@@ -3625,6 +3634,12 @@ int configure_downstream_group(Config *config, bool http2_proxy, ...@@ -3625,6 +3634,12 @@ int configure_downstream_group(Config *config, bool http2_proxy,
return -1; return -1;
} }
if (addr_groups[catch_all_group].require_upstream_tls) {
LOG(FATAL)
<< "backend: Catch-all backend cannot have frontend-tls parameter";
return -1;
}
downstreamconf.addr_group_catch_all = catch_all_group; downstreamconf.addr_group_catch_all = catch_all_group;
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
......
...@@ -430,7 +430,9 @@ struct AffinityHash { ...@@ -430,7 +430,9 @@ struct AffinityHash {
struct DownstreamAddrGroupConfig { struct DownstreamAddrGroupConfig {
DownstreamAddrGroupConfig(const StringRef &pattern) DownstreamAddrGroupConfig(const StringRef &pattern)
: pattern(pattern), affinity(AFFINITY_NONE) {} : pattern(pattern),
affinity(AFFINITY_NONE),
require_upstream_tls(false) {}
StringRef pattern; StringRef pattern;
std::vector<DownstreamAddrConfig> addrs; std::vector<DownstreamAddrConfig> addrs;
...@@ -439,6 +441,8 @@ struct DownstreamAddrGroupConfig { ...@@ -439,6 +441,8 @@ struct DownstreamAddrGroupConfig {
std::vector<AffinityHash> affinity_hash; std::vector<AffinityHash> affinity_hash;
// Session affinity // Session affinity
shrpx_session_affinity affinity; shrpx_session_affinity affinity;
// true if this group requires that client connection must be TLS.
bool require_upstream_tls;
}; };
struct TicketKey { struct TicketKey {
......
...@@ -76,7 +76,8 @@ bool match_shared_downstream_addr( ...@@ -76,7 +76,8 @@ bool match_shared_downstream_addr(
return false; return false;
} }
if (lhs->affinity != rhs->affinity) { if (lhs->affinity != rhs->affinity ||
lhs->require_upstream_tls != rhs->require_upstream_tls) {
return false; return false;
} }
...@@ -191,6 +192,7 @@ void Worker::replace_downstream_config( ...@@ -191,6 +192,7 @@ void Worker::replace_downstream_config(
shared_addr->addrs.resize(src.addrs.size()); shared_addr->addrs.resize(src.addrs.size());
shared_addr->affinity = src.affinity; shared_addr->affinity = src.affinity;
shared_addr->affinity_hash = src.affinity_hash; shared_addr->affinity_hash = src.affinity_hash;
shared_addr->require_upstream_tls = src.require_upstream_tls;
size_t num_http1 = 0; size_t num_http1 = 0;
size_t num_http2 = 0; size_t num_http2 = 0;
......
...@@ -136,7 +136,8 @@ struct SharedDownstreamAddr { ...@@ -136,7 +136,8 @@ struct SharedDownstreamAddr {
next{0}, next{0},
http1_pri{}, http1_pri{},
http2_pri{}, http2_pri{},
affinity{AFFINITY_NONE} {} affinity{AFFINITY_NONE},
require_upstream_tls{false} {}
SharedDownstreamAddr(const SharedDownstreamAddr &) = delete; SharedDownstreamAddr(const SharedDownstreamAddr &) = delete;
SharedDownstreamAddr(SharedDownstreamAddr &&) = delete; SharedDownstreamAddr(SharedDownstreamAddr &&) = delete;
...@@ -171,6 +172,8 @@ struct SharedDownstreamAddr { ...@@ -171,6 +172,8 @@ struct SharedDownstreamAddr {
WeightedPri http2_pri; WeightedPri http2_pri;
// Session affinity // Session affinity
shrpx_session_affinity affinity; shrpx_session_affinity affinity;
// true if this group requires that client connection must be TLS.
bool require_upstream_tls;
}; };
struct DownstreamAddrGroup { struct DownstreamAddrGroup {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment