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