diff --git a/src/shrpx.cc b/src/shrpx.cc index b636cba4..951f1119 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -1602,12 +1602,12 @@ Connections: The parameters are delimited by ";". The available parameters are: "proto=", "tls", "sni=", "fall=", "rise=", - "affinity=", and "dns". The parameter consists - of keyword, and optionally followed by "=" and value. - For example, the parameter "proto=h2" consists of the - keyword "proto" and value "h2". The parameter "tls" - consists of the keyword "tls" without value. Each - parameter is described as follows. + "affinity=", "dns", and "frontend-tls". The + parameter consists of keyword, and optionally followed + by "=" and value. For example, the parameter "proto=h2" + consists of the keyword "proto" and value "h2". The + parameter "tls" consists of the keyword "tls" without + value. Each parameter is described as follows. The backend application protocol can be specified using optional "proto" parameter, and in the form of @@ -1664,6 +1664,17 @@ Connections: backend host name at start up, or reloading 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 . It + is advised to set "frontend-tls" parameter to all + backends explicitly if this feature is desired. + Since ";" and ":" are used as delimiter, must not contain these characters. Since ";" has special meaning in shell, the option value must be quoted. diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index d60057fe..d29e783f 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -1008,6 +1008,13 @@ ClientHandler::get_downstream_connection(Downstream *downstream) { 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 &shared_addr = group->shared_addr; diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 6a241efa..60ac5f6d 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -732,6 +732,7 @@ struct DownstreamParams { shrpx_session_affinity affinity; bool tls; bool dns; + bool frontend_tls; }; namespace { @@ -807,6 +808,8 @@ int parse_downstream_params(DownstreamParams &out, } } else if (util::strieq_l("dns", param)) { out.dns = true; + } else if (util::strieq_l("frontend-tls", param)) { + out.frontend_tls = true; } else if (!param.empty()) { LOG(ERROR) << "backend: " << param << ": unknown keyword"; return -1; @@ -899,6 +902,11 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr, if (params.affinity != AFFINITY_NONE) { 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); done = true; break; @@ -913,6 +921,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr, auto &g = addr_groups.back(); g.addrs.push_back(addr); g.affinity = params.affinity; + g.require_upstream_tls = params.frontend_tls; if (pattern[0] == '*') { // wildcard pattern @@ -3625,6 +3634,12 @@ int configure_downstream_group(Config *config, bool http2_proxy, 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; if (LOG_ENABLED(INFO)) { diff --git a/src/shrpx_config.h b/src/shrpx_config.h index 7f3135a4..6d494131 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -430,7 +430,9 @@ struct AffinityHash { struct DownstreamAddrGroupConfig { DownstreamAddrGroupConfig(const StringRef &pattern) - : pattern(pattern), affinity(AFFINITY_NONE) {} + : pattern(pattern), + affinity(AFFINITY_NONE), + require_upstream_tls(false) {} StringRef pattern; std::vector addrs; @@ -439,6 +441,8 @@ struct DownstreamAddrGroupConfig { std::vector affinity_hash; // Session affinity shrpx_session_affinity affinity; + // true if this group requires that client connection must be TLS. + bool require_upstream_tls; }; struct TicketKey { diff --git a/src/shrpx_worker.cc b/src/shrpx_worker.cc index 30db93a7..84b604ab 100644 --- a/src/shrpx_worker.cc +++ b/src/shrpx_worker.cc @@ -76,7 +76,8 @@ bool match_shared_downstream_addr( return false; } - if (lhs->affinity != rhs->affinity) { + if (lhs->affinity != rhs->affinity || + lhs->require_upstream_tls != rhs->require_upstream_tls) { return false; } @@ -191,6 +192,7 @@ void Worker::replace_downstream_config( shared_addr->addrs.resize(src.addrs.size()); shared_addr->affinity = src.affinity; shared_addr->affinity_hash = src.affinity_hash; + shared_addr->require_upstream_tls = src.require_upstream_tls; size_t num_http1 = 0; size_t num_http2 = 0; diff --git a/src/shrpx_worker.h b/src/shrpx_worker.h index 649534e5..e014139b 100644 --- a/src/shrpx_worker.h +++ b/src/shrpx_worker.h @@ -136,7 +136,8 @@ struct SharedDownstreamAddr { next{0}, http1_pri{}, http2_pri{}, - affinity{AFFINITY_NONE} {} + affinity{AFFINITY_NONE}, + require_upstream_tls{false} {} SharedDownstreamAddr(const SharedDownstreamAddr &) = delete; SharedDownstreamAddr(SharedDownstreamAddr &&) = delete; @@ -171,6 +172,8 @@ struct SharedDownstreamAddr { WeightedPri http2_pri; // Session affinity shrpx_session_affinity affinity; + // true if this group requires that client connection must be TLS. + bool require_upstream_tls; }; struct DownstreamAddrGroup {