Merge pull request #892 from nghttp2/nghttpx-sni-fwd
nghttpx: SNI based backend server selection
This commit is contained in:
commit
17614312e0
23
src/shrpx.cc
23
src/shrpx.cc
|
@ -1665,14 +1665,16 @@ Connections:
|
|||
which only lacks trailing '/' (e.g., path "/foo/"
|
||||
matches request path "/foo"). If it does not end with
|
||||
"/", it performs exact match against the request path.
|
||||
If host is given, it performs exact match against the
|
||||
request host. If host alone is given, "/" is appended
|
||||
to it, so that it matches all request paths under the
|
||||
host (e.g., specifying "nghttp2.org" equals to
|
||||
"nghttp2.org/"). CONNECT method is treated specially.
|
||||
It does not have path, and we don't allow empty path.
|
||||
To workaround this, we assume that CONNECT method has
|
||||
"/" as path.
|
||||
If host is given, it performs a match against the
|
||||
request host. For a request received on the frontend
|
||||
lister with "sni-fwd" parameter enabled, SNI host is
|
||||
used instead of a request host. If host alone is given,
|
||||
"/" is appended to it, so that it matches all request
|
||||
paths under the host (e.g., specifying "nghttp2.org"
|
||||
equals to "nghttp2.org/"). CONNECT method is treated
|
||||
specially. It does not have path, and we don't allow
|
||||
empty path. To workaround this, we assume that CONNECT
|
||||
method has "/" as path.
|
||||
|
||||
Patterns with host take precedence over patterns with
|
||||
just path. Then, longer patterns take precedence over
|
||||
|
@ -1811,6 +1813,11 @@ Connections:
|
|||
Optionally, TLS can be disabled by specifying "no-tls"
|
||||
parameter. TLS is enabled by default.
|
||||
|
||||
If "sni-fwd" parameter is used, when performing a match
|
||||
to select a backend server, SNI host name received from
|
||||
the client is used instead of the request host. See
|
||||
--backend option about the pattern match.
|
||||
|
||||
To make this frontend as API endpoint, specify "api"
|
||||
parameter. This is disabled by default. It is
|
||||
important to limit the access to the API frontend.
|
||||
|
|
|
@ -979,29 +979,30 @@ ClientHandler::get_downstream_connection(int &err, Downstream *downstream) {
|
|||
auto &balloc = downstream->get_block_allocator();
|
||||
|
||||
// Fast path. If we have one group, it must be catch-all group.
|
||||
// proxy mode falls in this case.
|
||||
if (groups.size() == 1) {
|
||||
group_idx = 0;
|
||||
} else if (req.method == HTTP_CONNECT) {
|
||||
// CONNECT method does not have path. But we requires path in
|
||||
// host-path mapping. As workaround, we assume that path is "/".
|
||||
group_idx = match_downstream_addr_group(routerconf, req.authority,
|
||||
StringRef::from_lit("/"), groups,
|
||||
catch_all, balloc);
|
||||
} else {
|
||||
if (!req.authority.empty()) {
|
||||
group_idx = match_downstream_addr_group(
|
||||
routerconf, req.authority, req.path, groups, catch_all, balloc);
|
||||
StringRef authority;
|
||||
if (faddr_->sni_fwd) {
|
||||
authority = sni_;
|
||||
} else if (!req.authority.empty()) {
|
||||
authority = req.authority;
|
||||
} else {
|
||||
auto h = req.fs.header(http2::HD_HOST);
|
||||
if (h) {
|
||||
group_idx = match_downstream_addr_group(routerconf, h->value, req.path,
|
||||
groups, catch_all, balloc);
|
||||
} else {
|
||||
group_idx = match_downstream_addr_group(
|
||||
routerconf, StringRef{}, req.path, groups, catch_all, balloc);
|
||||
authority = h->value;
|
||||
}
|
||||
}
|
||||
|
||||
StringRef path;
|
||||
// CONNECT method does not have path. But we requires path in
|
||||
// host-path mapping. As workaround, we assume that path is "/".
|
||||
if (req.method != HTTP_CONNECT) {
|
||||
path = req.path;
|
||||
}
|
||||
|
||||
group_idx = match_downstream_addr_group(routerconf, authority, path, groups,
|
||||
catch_all, balloc);
|
||||
}
|
||||
|
||||
if (LOG_ENABLED(INFO)) {
|
||||
|
|
|
@ -710,6 +710,7 @@ int parse_memcached_connection_params(MemcachedConnectionParams &out,
|
|||
struct UpstreamParams {
|
||||
int alt_mode;
|
||||
bool tls;
|
||||
bool sni_fwd;
|
||||
bool proxyproto;
|
||||
};
|
||||
|
||||
|
@ -725,6 +726,8 @@ int parse_upstream_params(UpstreamParams &out, const StringRef &src_params) {
|
|||
|
||||
if (util::strieq_l("tls", param)) {
|
||||
out.tls = true;
|
||||
} else if (util::strieq_l("sni-fwd", param)) {
|
||||
out.sni_fwd = true;
|
||||
} else if (util::strieq_l("no-tls", param)) {
|
||||
out.tls = false;
|
||||
} else if (util::strieq_l("api", param)) {
|
||||
|
@ -2313,9 +2316,15 @@ int parse_config(Config *config, int optid, const StringRef &opt,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (params.sni_fwd && !params.tls) {
|
||||
LOG(ERROR) << "frontend: sni_fwd requires tls";
|
||||
return -1;
|
||||
}
|
||||
|
||||
UpstreamAddr addr{};
|
||||
addr.fd = -1;
|
||||
addr.tls = params.tls;
|
||||
addr.sni_fwd = params.sni_fwd;
|
||||
addr.alt_mode = params.alt_mode;
|
||||
addr.accept_proxy_protocol = params.proxyproto;
|
||||
|
||||
|
|
|
@ -404,6 +404,9 @@ struct UpstreamAddr {
|
|||
bool host_unix;
|
||||
// true if TLS is enabled.
|
||||
bool tls;
|
||||
// true if SNI host should be used as a host when selecting backend
|
||||
// server.
|
||||
bool sni_fwd;
|
||||
// true if client is supposed to send PROXY protocol v1 header.
|
||||
bool accept_proxy_protocol;
|
||||
int fd;
|
||||
|
|
Loading…
Reference in New Issue