Skip to content

Commit

Permalink
Merge pull request nghttp2#892 from nghttp2/nghttpx-sni-fwd
Browse files Browse the repository at this point in the history
nghttpx: SNI based backend server selection
  • Loading branch information
tatsuhiro-t authored Apr 19, 2017
2 parents 977779a + c8a5f1e commit 1761431
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 23 deletions.
23 changes: 15 additions & 8 deletions src/shrpx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1665,14 +1665,16 @@ void print_help(std::ostream &out) {
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
Expand Down Expand Up @@ -1811,6 +1813,11 @@ void print_help(std::ostream &out) {
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.
Expand Down
31 changes: 16 additions & 15 deletions src/shrpx_client_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
9 changes: 9 additions & 0 deletions src/shrpx_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,7 @@ int parse_memcached_connection_params(MemcachedConnectionParams &out,
struct UpstreamParams {
int alt_mode;
bool tls;
bool sni_fwd;
bool proxyproto;
};

Expand All @@ -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)) {
Expand Down Expand Up @@ -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;

Expand Down
3 changes: 3 additions & 0 deletions src/shrpx_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 1761431

Please sign in to comment.