Skip to content

Commit 801e5be

Browse files
traeakBrian Olsen
andauthored
add host_override to parent.config and other sni name fixes (#12868)
* add host_override to parent.config and other sni name fixes * add documentation for host_override in parent.config, update strategies.yaml docs * add test using pristine_host_hdr setting --------- Co-authored-by: Brian Olsen <bolsen149@comcast.com>
1 parent 627f507 commit 801e5be

16 files changed

Lines changed: 402 additions & 30 deletions

doc/admin-guide/files/parent.config.en.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,14 @@ The following list shows the possible actions and their allowed values.
324324

325325
- ``false`` - The default. Do not ignore the host status.
326326

327+
.. _parent-config-format-host_override:
328+
329+
``host_override``
330+
One of the following values:
331+
332+
- ``true`` - Sets the host header of the request using the selected parent, including the SNI name to be used for any upstream TLS connection. Useful when a parent is another CDN that requires a correct SNI name.
333+
- ``false`` - The default. Does not change the host header.
334+
327335
.. _parent-config-format-hash-algorithm:
328336

329337
``hash_algorithm``

doc/admin-guide/files/strategies.yaml.en.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ Each **strategy** in the list may using the following parameters:
286286
(**self** should only be necessary when the local hostname can only be translated to an IP address
287287
with a DNS lookup.)
288288

289-
- **host_override**: A boolean value that will set the host header to the selected parent rather than the original host. **true** sets host header to selected parent. **false** (default) leaves the host header untouched.
289+
- **host_override**: A boolean value that will set the host header to the selected parent rather than the original host, including the SNI name for any attempted upstream TLS connection. **true** sets host header to selected parent. **false** (default) leaves the host header untouched.
290290

291291
Example:
292292
::

include/proxy/ParentSelection.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ class ParentRecord : public ControlBase
167167
int max_unavailable_server_retries = 1;
168168
int secondary_mode = 1;
169169
bool ignore_self_detect = false;
170+
bool host_override = false;
170171
ParentHashAlgorithm consistent_hash_algorithm = ParentHashAlgorithm::SIPHASH24;
171172
uint64_t consistent_hash_seed0 = 0;
172173
uint64_t consistent_hash_seed1 = 0;
@@ -242,6 +243,20 @@ struct ParentResult {
242243
return is_api_result() ? ParentRetry_t::NONE : rec->parent_retry;
243244
}
244245

246+
bool
247+
host_override() const
248+
{
249+
if (is_api_result()) {
250+
return false;
251+
}
252+
253+
if (!is_some()) {
254+
return false;
255+
}
256+
257+
return rec->host_override;
258+
}
259+
245260
unsigned
246261
max_retries(ParentRetry_t method) const
247262
{

include/proxy/http/remap/NextHopSelectionStrategy.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include <utility>
2828

2929
#include "ts/apidefs.h"
30-
#include "proxy/ParentSelection.h"
3130
#include "proxy/http/HttpTransact.h"
3231

3332
#ifndef _NH_UNIT_TESTS_
@@ -199,8 +198,6 @@ class NextHopSelectionStrategy
199198
const time_t now = 0);
200199
bool nextHopExists(TSHttpTxn txnp, void *ih = nullptr);
201200

202-
void setHostHeader(TSHttpTxn txnp, const char *hostname);
203-
204201
virtual ParentRetry_t responseIsRetryable(int64_t sm_id, HttpTransact::CurrentInfo &current_info, HTTPStatus response_code);
205202

206203
void retryComplete(TSHttpTxn txn, const char *hostname, const int port);

src/proxy/ParentSelection.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,13 @@ ParentRecord::Init(matcher_line *line_info)
797797
ignore_self_detect = false;
798798
}
799799
used = true;
800+
} else if (strcasecmp(label, "host_override") == 0) {
801+
if (strcasecmp(val, "true") == 0) {
802+
host_override = true;
803+
} else {
804+
host_override = false;
805+
}
806+
used = true;
800807
} else if (strcasecmp(label, "hash_algorithm") == 0) {
801808
consistent_hash_algorithm = parseHashAlgorithm(val);
802809
used = true;

src/proxy/http/HttpSM.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5337,11 +5337,11 @@ HttpSM::get_outbound_sni() const
53375337
// By default the host header field value is used for the SNI.
53385338
zret = t_state.hdr_info.server_request.host_get();
53395339
} else if (_ua.get_txn() && policy == "server_name"_tv) {
5340-
const char *server_name = snis->get_sni_server_name();
5341-
if (server_name[0] == '\0') {
5340+
const char *const server_name = snis->get_sni_server_name();
5341+
if (nullptr == server_name || server_name[0] == '\0') {
53425342
zret.assign(nullptr, swoc::TextView::npos);
53435343
} else {
5344-
zret.assign(snis->get_sni_server_name(), swoc::TextView::npos);
5344+
zret.assign(server_name, swoc::TextView::npos);
53455345
}
53465346
} else if (policy.front() == '@') { // guaranteed non-empty from previous clause
53475347
zret = policy.remove_prefix(1);

src/proxy/http/HttpTransact.cc

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,19 +139,51 @@ bypass_ok(HttpTransact::State *s)
139139
return false;
140140
}
141141
142+
// wrapper to choose between a remap next hop strategy or use parent.config
143+
// remap next hop strategy is preferred
144+
inline static bool
145+
host_override(HttpTransact::State *s)
146+
{
147+
if (s->response_action.handled) { // should be handled by the plugin
148+
return false;
149+
} else if (nullptr != s->next_hop_strategy) {
150+
// remap strategies do not support the TSHttpTxnParentProxySet API.
151+
return s->next_hop_strategy->host_override;
152+
} else if (nullptr != s->parent_params) {
153+
return s->parent_result.host_override();
154+
}
155+
return false;
156+
}
157+
158+
// wrapper to choose between a remap next hop strategy or use parent.config
159+
// remap next hop strategy is preferred
160+
inline static bool
161+
is_some(HttpTransact::State *s)
162+
{
163+
if (s->response_action.handled) {
164+
return true;
165+
} else if (nullptr != s->next_hop_strategy) {
166+
// remap strategies do not support the TSHttpTxnParentProxySet API.
167+
return s->parent_result.result == ParentResultType::SPECIFIED;
168+
} else if (nullptr != s->parent_params) {
169+
return s->parent_result.is_some();
170+
}
171+
return false;
172+
}
173+
142174
// wrapper to choose between a remap next hop strategy or use parent.config
143175
// remap next hop strategy is preferred
144176
inline static bool
145177
is_api_result(HttpTransact::State *s)
146178
{
147-
bool r = false;
179+
bool res = false;
148180
if (nullptr != s->next_hop_strategy) {
149181
// remap strategies do not support the TSHttpTxnParentProxySet API.
150-
r = false;
182+
res = false;
151183
} else if (nullptr != s->parent_params) {
152-
r = s->parent_result.is_api_result();
184+
res = s->parent_result.is_api_result();
153185
}
154-
return r;
186+
return res;
155187
}
156188
157189
// wrapper to get the max_retries.
@@ -207,6 +239,8 @@ retry_type(HttpTransact::State *s)
207239
inline static void
208240
findParent(HttpTransact::State *s)
209241
{
242+
TxnDbg(dbg_ctl_http_trans, "findParent");
243+
210244
Metrics::Counter::increment(http_rsb.parent_count);
211245
if (s->response_action.handled) {
212246
s->parent_result.hostname = s->response_action.action.hostname;
@@ -295,6 +329,8 @@ parentExists(HttpTransact::State *s)
295329
inline static void
296330
nextParent(HttpTransact::State *s)
297331
{
332+
TxnDbg(dbg_ctl_http_trans, "nextParent");
333+
298334
TxnDbg(dbg_ctl_parent_down, "connection to parent %s failed, conn_state: %s, request to origin: %s", s->parent_result.hostname,
299335
HttpDebugNames::get_server_state_name(s->current.state), s->request_data.get_host());
300336
Metrics::Counter::increment(http_rsb.parent_count);
@@ -599,10 +635,11 @@ find_server_and_update_current_info(HttpTransact::State *s)
599635
} else {
600636
findParent(s);
601637
}
602-
if (!s->parent_result.is_some() || is_api_result(s) || parent_is_proxy(s)) {
638+
if (!is_some(s) || is_api_result(s) || parent_is_proxy(s)) {
603639
TxnDbg(dbg_ctl_http_trans, "request not cacheable, so bypass parent");
604640
s->parent_result.result = ParentResultType::DIRECT;
605641
}
642+
606643
} else if (s->txn_conf->uncacheable_requests_bypass_parent && s->txn_conf->no_dns_forward_to_parent == 0 &&
607644
!HttpTransact::is_request_cache_lookupable(s)) {
608645
// request not lookupable and cacheable, so bypass parent if the parent is not an origin server.
@@ -616,10 +653,12 @@ find_server_and_update_current_info(HttpTransact::State *s)
616653
} else {
617654
findParent(s);
618655
}
619-
if (!s->parent_result.is_some() || is_api_result(s) || parent_is_proxy(s)) {
656+
657+
if (!is_some(s) || is_api_result(s) || parent_is_proxy(s)) {
620658
TxnDbg(dbg_ctl_http_trans, "request not cacheable, so bypass parent");
621659
s->parent_result.result = ParentResultType::DIRECT;
622660
}
661+
623662
} else {
624663
switch (s->parent_result.result) {
625664
case ParentResultType::UNDEFINED:
@@ -660,14 +699,32 @@ find_server_and_update_current_info(HttpTransact::State *s)
660699
}
661700
662701
switch (s->parent_result.result) {
663-
case ParentResultType::SPECIFIED:
664-
s->parent_info.name = s->arena.str_store(s->parent_result.hostname, strlen(s->parent_result.hostname));
702+
case ParentResultType::SPECIFIED: {
703+
char const *const hostname = s->parent_result.hostname;
704+
705+
if (nullptr != hostname) {
706+
s->parent_info.name = s->arena.str_store(hostname, strlen(hostname));
707+
708+
// if host header override option enabled
709+
if (host_override(s)) {
710+
TxnDbg(dbg_ctl_http_trans, "overriding host header with parent %s", hostname);
711+
if (!s->hdr_info.server_request.valid()) {
712+
s->hdr_info.client_request.value_set(static_cast<std::string_view>(MIME_FIELD_HOST), hostname);
713+
s->hdr_info.client_request.mark_target_dirty();
714+
} else {
715+
s->hdr_info.server_request.value_set(static_cast<std::string_view>(MIME_FIELD_HOST), hostname);
716+
s->hdr_info.server_request.mark_target_dirty();
717+
}
718+
}
719+
}
720+
665721
update_current_info(&s->current, &s->parent_info, ResolveInfo::PARENT_PROXY, false);
666722
update_dns_info(&s->dns_info, &s->current);
667723
ink_assert(s->dns_info.looking_up == ResolveInfo::PARENT_PROXY);
668724
s->next_hop_scheme = URL_WKSIDX_HTTP;
669725
670726
return ResolveInfo::PARENT_PROXY;
727+
}
671728
case ParentResultType::FAIL:
672729
// No more parents - need to return an error message
673730
s->current.request_to = ResolveInfo::HOST_NONE;

src/proxy/http/remap/NextHopConsistentHash.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,4 @@ NextHopConsistentHash::findNextHop(TSHttpTxn txnp, void * /* ih ATS_UNUSED */, t
547547
NH_Dbg(NH_DBG_CTL, "[%" PRIu64 "] result.result: %s set hostname null port 0 retry false", sm_id,
548548
ParentResultStr[static_cast<int>(result.result)]);
549549
}
550-
551-
setHostHeader(txnp, result.hostname);
552-
553-
return;
554550
}

src/proxy/http/remap/NextHopRoundRobin.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ NextHopRoundRobin::findNextHop(TSHttpTxn txnp, void * /* ih ATS_UNUSED */, time_
170170
result->last_parent = cur_hst_index;
171171
result->last_group = cur_grp_index;
172172
result->retry = parentRetry;
173-
setHostHeader(txnp, result->hostname);
174173
ink_assert(result->hostname != nullptr);
175174
ink_assert(result->port != 0);
176175
NH_Dbg(NH_DBG_CTL, "[%" PRIu64 "] Chosen parent = %s.%d", sm_id, result->hostname, result->port);

src/proxy/http/remap/NextHopSelectionStrategy.cc

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -265,16 +265,6 @@ NextHopSelectionStrategy::markNextHop(TSHttpTxn txnp, const char *hostname, cons
265265
return passive_health.markNextHop(txnp, hostname, port, status, ih, now);
266266
}
267267

268-
void
269-
NextHopSelectionStrategy::setHostHeader(TSHttpTxn txnp, const char *hostname)
270-
{
271-
if (host_override && nullptr != hostname) {
272-
HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
273-
sm->t_state.hdr_info.client_request.value_set(static_cast<std::string_view>(MIME_FIELD_HOST), hostname);
274-
NH_Dbg(NH_DBG_CTL, "[%" PRIu64 "] overriding host header with parent %s", sm->sm_id, hostname);
275-
}
276-
}
277-
278268
bool
279269
NextHopSelectionStrategy::nextHopExists(TSHttpTxn txnp, void * /* ih ATS_UNUSED */)
280270
{

0 commit comments

Comments
 (0)