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