nghttpx: Enable/disable TLS per frontend address
This change allows user to disable TLS per frontend address using no-tls keyword in --frontend option. We removed --frontend-no-tls in favor of this new feature.
This commit is contained in:
parent
58b06f32a2
commit
eec0b04a33
22
src/shrpx.cc
22
src/shrpx.cc
|
@ -432,7 +432,8 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr,
|
|||
});
|
||||
|
||||
if (found != std::end(iaddrs)) {
|
||||
LOG(NOTICE) << "Listening on UNIX domain socket " << faddr.host;
|
||||
LOG(NOTICE) << "Listening on UNIX domain socket " << faddr.host
|
||||
<< (faddr.tls ? ", tls" : "");
|
||||
(*found).used = true;
|
||||
faddr.fd = (*found).fd;
|
||||
faddr.hostport = "localhost";
|
||||
|
@ -496,7 +497,8 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr,
|
|||
return -1;
|
||||
}
|
||||
|
||||
LOG(NOTICE) << "Listening on UNIX domain socket " << faddr.host;
|
||||
LOG(NOTICE) << "Listening on UNIX domain socket " << faddr.host
|
||||
<< (faddr.tls ? ", tls" : "");
|
||||
|
||||
faddr.fd = fd;
|
||||
faddr.hostport = "localhost";
|
||||
|
@ -652,7 +654,8 @@ int create_tcp_server_socket(UpstreamAddr &faddr,
|
|||
faddr.fd = fd;
|
||||
faddr.hostport = util::make_http_hostport(StringRef{host.data()}, faddr.port);
|
||||
|
||||
LOG(NOTICE) << "Listening on " << faddr.hostport;
|
||||
LOG(NOTICE) << "Listening on " << faddr.hostport
|
||||
<< (faddr.tls ? ", tls" : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1274,13 +1277,17 @@ Connections:
|
|||
|
||||
Default: )" << DEFAULT_DOWNSTREAM_HOST << ","
|
||||
<< DEFAULT_DOWNSTREAM_PORT << R"(
|
||||
-f, --frontend=(<HOST>,<PORT>|unix:<PATH>)
|
||||
-f, --frontend=(<HOST>,<PORT>|unix:<PATH>)[;no-tls]
|
||||
Set frontend host and port. If <HOST> is '*', it
|
||||
assumes all addresses including both IPv4 and IPv6.
|
||||
UNIX domain socket can be specified by prefixing path
|
||||
name with "unix:" (e.g., unix:/var/run/nghttpx.sock).
|
||||
This option can be used multiple times to listen to
|
||||
multiple addresses.
|
||||
|
||||
Optionally, TLS can be disabled by specifying "no-tls"
|
||||
keyword. TLS is enabled by default.
|
||||
|
||||
Default: *,3000
|
||||
--backlog=<N>
|
||||
Set listen backlog size.
|
||||
|
@ -1652,8 +1659,6 @@ HTTP/2 and SPDY:
|
|||
2**<N>-1. For SPDY, the size is 2**<N>.
|
||||
Default: )" << get_config()->http2.upstream.connection_window_bits
|
||||
<< R"(
|
||||
--frontend-no-tls
|
||||
Disable SSL/TLS on frontend connections.
|
||||
--backend-http2-window-bits=<N>
|
||||
Sets the initial window size of HTTP/2 backend
|
||||
connection to 2**<N>-1.
|
||||
|
@ -2040,6 +2045,7 @@ void process_options(
|
|||
UpstreamAddr addr{};
|
||||
addr.host = "*";
|
||||
addr.port = 3000;
|
||||
addr.tls = true;
|
||||
addr.family = AF_INET;
|
||||
listenerconf.addrs.push_back(addr);
|
||||
addr.family = AF_INET6;
|
||||
|
@ -2050,14 +2056,14 @@ void process_options(
|
|||
upstreamconf.worker_connections = std::numeric_limits<size_t>::max();
|
||||
}
|
||||
|
||||
if (!upstreamconf.no_tls &&
|
||||
if (ssl::upstream_tls_enabled() &&
|
||||
(tlsconf.private_key_file.empty() || tlsconf.cert_file.empty())) {
|
||||
print_usage(std::cerr);
|
||||
LOG(FATAL) << "Too few arguments";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!upstreamconf.no_tls && !tlsconf.ocsp.disabled) {
|
||||
if (ssl::upstream_tls_enabled() && !tlsconf.ocsp.disabled) {
|
||||
struct stat buf;
|
||||
if (stat(tlsconf.ocsp.fetch_ocsp_response_file.c_str(), &buf) != 0) {
|
||||
tlsconf.ocsp.disabled = true;
|
||||
|
|
|
@ -568,6 +568,40 @@ int parse_duration(ev_tstamp *dest, const char *opt, const char *optarg) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
struct UpstreamParams {
|
||||
bool tls;
|
||||
};
|
||||
|
||||
namespace {
|
||||
// Parses upstream configuration parameter |src_params|, and stores
|
||||
// parsed results into |out|. This function returns 0 if it succeeds,
|
||||
// or -1.
|
||||
int parse_upstream_params(UpstreamParams &out, const StringRef &src_params) {
|
||||
auto last = std::end(src_params);
|
||||
for (auto first = std::begin(src_params); first != last;) {
|
||||
auto end = std::find(first, last, ';');
|
||||
auto param = StringRef{first, end};
|
||||
|
||||
if (util::strieq_l("tls", param)) {
|
||||
out.tls = true;
|
||||
} else if (util::strieq_l("no-tls", param)) {
|
||||
out.tls = false;
|
||||
} else if (!param.empty()) {
|
||||
LOG(ERROR) << "frontend: " << param << ": unknown keyword";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (end == last) {
|
||||
break;
|
||||
}
|
||||
|
||||
first = end + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
struct DownstreamParams {
|
||||
shrpx_proto proto;
|
||||
bool tls;
|
||||
|
@ -1683,7 +1717,7 @@ int parse_config(const char *opt, const char *optarg,
|
|||
addr.host = ImmutableString(path, addr_end);
|
||||
addr.host_unix = true;
|
||||
} else {
|
||||
if (split_host_port(host, sizeof(host), &port, &src[0],
|
||||
if (split_host_port(host, sizeof(host), &port, src.c_str(),
|
||||
addr_end - std::begin(src)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1707,12 +1741,24 @@ int parse_config(const char *opt, const char *optarg,
|
|||
case SHRPX_OPTID_FRONTEND: {
|
||||
auto &listenerconf = mod_config()->conn.listener;
|
||||
|
||||
auto src = StringRef{optarg};
|
||||
auto addr_end = std::find(std::begin(src), std::end(src), ';');
|
||||
auto src_params = StringRef{addr_end, std::end(src)};
|
||||
|
||||
UpstreamParams params{};
|
||||
params.tls = true;
|
||||
|
||||
if (parse_upstream_params(params, src_params) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
UpstreamAddr addr{};
|
||||
addr.fd = -1;
|
||||
addr.tls = params.tls;
|
||||
|
||||
if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
|
||||
auto path = optarg + str_size(SHRPX_UNIX_PATH_PREFIX);
|
||||
addr.host = ImmutableString(path);
|
||||
if (util::istarts_with_l(src, SHRPX_UNIX_PATH_PREFIX)) {
|
||||
auto path = std::begin(src) + str_size(SHRPX_UNIX_PATH_PREFIX);
|
||||
addr.host = ImmutableString{path, addr_end};
|
||||
addr.host_unix = true;
|
||||
|
||||
listenerconf.addrs.push_back(std::move(addr));
|
||||
|
@ -1720,8 +1766,8 @@ int parse_config(const char *opt, const char *optarg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (split_host_port(host, sizeof(host), &port, optarg, strlen(optarg)) ==
|
||||
-1) {
|
||||
if (split_host_port(host, sizeof(host), &port, src.c_str(),
|
||||
addr_end - std::begin(src)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1920,8 +1966,8 @@ int parse_config(const char *opt, const char *optarg,
|
|||
return 0;
|
||||
}
|
||||
case SHRPX_OPTID_FRONTEND_NO_TLS:
|
||||
mod_config()->conn.upstream.no_tls = util::strieq(optarg, "yes");
|
||||
|
||||
LOG(WARN) << opt << ": deprecated. Use no-tls keyword in "
|
||||
<< SHRPX_OPT_FRONTEND;
|
||||
return 0;
|
||||
case SHRPX_OPTID_BACKEND_NO_TLS:
|
||||
LOG(WARN) << opt << ": deprecated. backend connection is not encrypted by "
|
||||
|
|
|
@ -277,6 +277,8 @@ struct UpstreamAddr {
|
|||
int family;
|
||||
// true if |host| contains UNIX domain socket path.
|
||||
bool host_unix;
|
||||
// true if TLS is enabled.
|
||||
bool tls;
|
||||
int fd;
|
||||
};
|
||||
|
||||
|
@ -558,7 +560,6 @@ struct ConnectionConfig {
|
|||
RateLimitConfig write;
|
||||
} ratelimit;
|
||||
size_t worker_connections;
|
||||
bool no_tls;
|
||||
bool accept_proxy_protocol;
|
||||
} upstream;
|
||||
|
||||
|
|
|
@ -800,8 +800,11 @@ ClientHandler *accept_connection(Worker *worker, int fd, sockaddr *addr,
|
|||
}
|
||||
}
|
||||
SSL *ssl = nullptr;
|
||||
auto ssl_ctx = worker->get_sv_ssl_ctx();
|
||||
if (ssl_ctx) {
|
||||
if (faddr->tls) {
|
||||
auto ssl_ctx = worker->get_sv_ssl_ctx();
|
||||
|
||||
assert(ssl_ctx);
|
||||
|
||||
ssl = create_ssl(ssl_ctx);
|
||||
if (!ssl) {
|
||||
return nullptr;
|
||||
|
@ -1245,6 +1248,12 @@ bool in_proto_list(const std::vector<std::string> &protos,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool upstream_tls_enabled() {
|
||||
const auto &faddrs = get_config()->conn.listener.addrs;
|
||||
return std::any_of(std::begin(faddrs), std::end(faddrs),
|
||||
[](const UpstreamAddr &faddr) { return faddr.tls; });
|
||||
}
|
||||
|
||||
SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||
CertLookupTree *cert_tree
|
||||
#ifdef HAVE_NEVERBLEED
|
||||
|
@ -1252,7 +1261,7 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
|||
neverbleed_t *nb
|
||||
#endif // HAVE_NEVERBLEED
|
||||
) {
|
||||
if (get_config()->conn.upstream.no_tls) {
|
||||
if (!upstream_tls_enabled()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1346,8 +1355,7 @@ void setup_downstream_http1_alpn(SSL *ssl) {
|
|||
}
|
||||
|
||||
CertLookupTree *create_cert_lookup_tree() {
|
||||
if (get_config()->conn.upstream.no_tls ||
|
||||
get_config()->tls.subcerts.empty()) {
|
||||
if (!upstream_tls_enabled() || get_config()->tls.subcerts.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return new ssl::CertLookupTree();
|
||||
|
|
|
@ -213,6 +213,9 @@ CertLookupTree *create_cert_lookup_tree();
|
|||
|
||||
SSL *create_ssl(SSL_CTX *ssl_ctx);
|
||||
|
||||
// Returns true if SSL/TLS is enabled on upstream
|
||||
bool upstream_tls_enabled();
|
||||
|
||||
// Returns true if SSL/TLS is enabled on downstream
|
||||
bool downstream_tls_enabled();
|
||||
|
||||
|
|
|
@ -393,10 +393,8 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
|||
conn_handler.add_acceptor(make_unique<AcceptHandler>(&addr, &conn_handler));
|
||||
}
|
||||
|
||||
auto &upstreamconf = get_config()->conn.upstream;
|
||||
|
||||
#ifdef HAVE_NEVERBLEED
|
||||
if (!upstreamconf.no_tls || ssl::downstream_tls_enabled()) {
|
||||
if (ssl::upstream_tls_enabled() || ssl::downstream_tls_enabled()) {
|
||||
std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf;
|
||||
auto nb = make_unique<neverbleed_t>();
|
||||
if (neverbleed_init(nb.get(), errbuf.data()) != 0) {
|
||||
|
@ -423,7 +421,7 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
|||
MemchunkPool mcpool;
|
||||
|
||||
ev_timer renew_ticket_key_timer;
|
||||
if (!upstreamconf.no_tls) {
|
||||
if (ssl::upstream_tls_enabled()) {
|
||||
auto &ticketconf = get_config()->tls.ticket;
|
||||
auto &memcachedconf = ticketconf.memcached;
|
||||
|
||||
|
@ -522,7 +520,7 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
|||
ipcev.data = &conn_handler;
|
||||
ev_io_start(loop, &ipcev);
|
||||
|
||||
if (!upstreamconf.no_tls && !get_config()->tls.ocsp.disabled) {
|
||||
if (ssl::upstream_tls_enabled() && !get_config()->tls.ocsp.disabled) {
|
||||
conn_handler.proceed_next_cert_ocsp();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue