nghttpx: Generate and set QUIC secrets
This commit is contained in:
parent
8563ec5a7a
commit
137da6adf6
|
@ -1554,14 +1554,6 @@ void fill_default_config(Config *config) {
|
||||||
{
|
{
|
||||||
quicconf.timeout.idle = 30_s;
|
quicconf.timeout.idle = 30_s;
|
||||||
|
|
||||||
auto &stateless_resetconf = quicconf.stateless_reset;
|
|
||||||
// TODO Find better place to do this and error handling.
|
|
||||||
if (RAND_bytes(stateless_resetconf.secret.data(),
|
|
||||||
stateless_resetconf.secret.size()) != 1) {
|
|
||||||
LOG(FATAL) << "Unable to generate stateless reset secret";
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &bpfconf = quicconf.bpf;
|
auto &bpfconf = quicconf.bpf;
|
||||||
bpfconf.prog_file = StringRef::from_lit(PKGLIBDIR "/reuseport_kern.o");
|
bpfconf.prog_file = StringRef::from_lit(PKGLIBDIR "/reuseport_kern.o");
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,9 @@
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#include "shrpx_router.h"
|
#include "shrpx_router.h"
|
||||||
|
#if ENABLE_HTTP3
|
||||||
|
# include "shrpx_quic.h"
|
||||||
|
#endif // ENABLE_HTTP3
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
@ -572,6 +575,14 @@ struct TLSCertificate {
|
||||||
std::vector<uint8_t> sct_data;
|
std::vector<uint8_t> sct_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef ENABLE_HTTP3
|
||||||
|
struct QUICSecret {
|
||||||
|
std::array<uint8_t, SHRPX_QUIC_STATELESS_RESET_SECRETLEN>
|
||||||
|
stateless_reset_secret;
|
||||||
|
std::array<uint8_t, SHRPX_QUIC_TOKEN_SECRETLEN> token_secret;
|
||||||
|
};
|
||||||
|
#endif // ENABLE_HTTP3
|
||||||
|
|
||||||
struct HttpProxy {
|
struct HttpProxy {
|
||||||
Address addr;
|
Address addr;
|
||||||
// host in http proxy URI
|
// host in http proxy URI
|
||||||
|
@ -711,9 +722,6 @@ struct TLSConfig {
|
||||||
|
|
||||||
#ifdef ENABLE_HTTP3
|
#ifdef ENABLE_HTTP3
|
||||||
struct QUICConfig {
|
struct QUICConfig {
|
||||||
struct {
|
|
||||||
std::array<uint8_t, 32> secret;
|
|
||||||
} stateless_reset;
|
|
||||||
struct {
|
struct {
|
||||||
ev_tstamp idle;
|
ev_tstamp idle;
|
||||||
} timeout;
|
} timeout;
|
||||||
|
|
|
@ -291,6 +291,8 @@ int ConnectionHandler::create_single_worker() {
|
||||||
#endif // HAVE_MRUBY
|
#endif // HAVE_MRUBY
|
||||||
|
|
||||||
#ifdef ENABLE_HTTP3
|
#ifdef ENABLE_HTTP3
|
||||||
|
single_worker_->set_quic_secret(quic_secret_);
|
||||||
|
|
||||||
if (single_worker_->setup_quic_server_socket() != 0) {
|
if (single_worker_->setup_quic_server_socket() != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -394,6 +396,8 @@ int ConnectionHandler::create_worker_thread(size_t num) {
|
||||||
# endif // HAVE_MRUBY
|
# endif // HAVE_MRUBY
|
||||||
|
|
||||||
# ifdef ENABLE_HTTP3
|
# ifdef ENABLE_HTTP3
|
||||||
|
worker->set_quic_secret(quic_secret_);
|
||||||
|
|
||||||
if ((!apiconf.enabled || i != 0) &&
|
if ((!apiconf.enabled || i != 0) &&
|
||||||
worker->setup_quic_server_socket() != 0) {
|
worker->setup_quic_server_socket() != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1035,6 +1039,27 @@ int ConnectionHandler::forward_quic_packet(const UpstreamAddr *faddr,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ConnectionHandler::create_quic_secret() {
|
||||||
|
auto quic_secret = std::make_shared<QUICSecret>();
|
||||||
|
|
||||||
|
if (generate_quic_stateless_reset_secret(
|
||||||
|
quic_secret->stateless_reset_secret.data()) != 0) {
|
||||||
|
LOG(ERROR) << "Failed to generate QUIC Stateless Reset secret";
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generate_quic_token_secret(quic_secret->token_secret.data()) != 0) {
|
||||||
|
LOG(ERROR) << "Failed to generate QUIC token secret";
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
quic_secret_ = std::move(quic_secret);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
# ifdef HAVE_LIBBPF
|
# ifdef HAVE_LIBBPF
|
||||||
std::vector<BPFRef> &ConnectionHandler::get_quic_bpf_refs() {
|
std::vector<BPFRef> &ConnectionHandler::get_quic_bpf_refs() {
|
||||||
return quic_bpf_refs_;
|
return quic_bpf_refs_;
|
||||||
|
|
|
@ -177,6 +177,8 @@ public:
|
||||||
const Address &local_addr, const uint8_t *cid_prefix,
|
const Address &local_addr, const uint8_t *cid_prefix,
|
||||||
const uint8_t *data, size_t datalen);
|
const uint8_t *data, size_t datalen);
|
||||||
|
|
||||||
|
int create_quic_secret();
|
||||||
|
|
||||||
# ifdef HAVE_LIBBPF
|
# ifdef HAVE_LIBBPF
|
||||||
std::vector<BPFRef> &get_quic_bpf_refs();
|
std::vector<BPFRef> &get_quic_bpf_refs();
|
||||||
# endif // HAVE_LIBBPF
|
# endif // HAVE_LIBBPF
|
||||||
|
@ -213,6 +215,7 @@ private:
|
||||||
# ifdef HAVE_LIBBPF
|
# ifdef HAVE_LIBBPF
|
||||||
std::vector<BPFRef> quic_bpf_refs_;
|
std::vector<BPFRef> quic_bpf_refs_;
|
||||||
# endif // HAVE_LIBBPF
|
# endif // HAVE_LIBBPF
|
||||||
|
std::shared_ptr<QUICSecret> quic_secret_;
|
||||||
std::vector<SSL_CTX *> quic_all_ssl_ctx_;
|
std::vector<SSL_CTX *> quic_all_ssl_ctx_;
|
||||||
std::vector<std::vector<SSL_CTX *>> quic_indexed_ssl_ctx_;
|
std::vector<std::vector<SSL_CTX *>> quic_indexed_ssl_ctx_;
|
||||||
#endif // ENABLE_HTTP3
|
#endif // ENABLE_HTTP3
|
||||||
|
|
|
@ -168,9 +168,8 @@ int get_new_connection_id(ngtcp2_conn *conn, ngtcp2_cid *cid, uint8_t *token,
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto config = get_config();
|
auto &quic_secret = worker->get_quic_secret();
|
||||||
auto &quicconf = config->quic;
|
auto &secret = quic_secret->stateless_reset_secret;
|
||||||
auto &secret = quicconf.stateless_reset.secret;
|
|
||||||
|
|
||||||
if (generate_quic_stateless_reset_token(token, cid, secret.data(),
|
if (generate_quic_stateless_reset_token(token, cid, secret.data(),
|
||||||
secret.size()) != 0) {
|
secret.size()) != 0) {
|
||||||
|
@ -483,11 +482,12 @@ int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr,
|
||||||
static_cast<ngtcp2_tstamp>(quicconf.timeout.idle * NGTCP2_SECONDS);
|
static_cast<ngtcp2_tstamp>(quicconf.timeout.idle * NGTCP2_SECONDS);
|
||||||
params.original_dcid = initial_hd.dcid;
|
params.original_dcid = initial_hd.dcid;
|
||||||
|
|
||||||
auto &stateless_resetconf = quicconf.stateless_reset;
|
auto &quic_secret = worker->get_quic_secret();
|
||||||
|
auto &stateless_reset_secret = quic_secret->stateless_reset_secret;
|
||||||
|
|
||||||
rv = generate_quic_stateless_reset_token(params.stateless_reset_token, &scid,
|
rv = generate_quic_stateless_reset_token(params.stateless_reset_token, &scid,
|
||||||
stateless_resetconf.secret.data(),
|
stateless_reset_secret.data(),
|
||||||
stateless_resetconf.secret.size());
|
stateless_reset_secret.size());
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
LOG(ERROR) << "generate_quic_stateless_reset_token failed";
|
LOG(ERROR) << "generate_quic_stateless_reset_token failed";
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -180,4 +180,12 @@ int generate_quic_stateless_reset_token(uint8_t *token, const ngtcp2_cid *cid,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int generate_quic_stateless_reset_secret(uint8_t *secret) {
|
||||||
|
return RAND_bytes(secret, SHRPX_QUIC_STATELESS_RESET_SECRETLEN) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int generate_quic_token_secret(uint8_t *secret) {
|
||||||
|
return RAND_bytes(secret, SHRPX_QUIC_TOKEN_SECRETLEN) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -38,6 +38,8 @@ struct UpstreamAddr;
|
||||||
constexpr size_t SHRPX_QUIC_SCIDLEN = 20;
|
constexpr size_t SHRPX_QUIC_SCIDLEN = 20;
|
||||||
constexpr size_t SHRPX_QUIC_CID_PREFIXLEN = 8;
|
constexpr size_t SHRPX_QUIC_CID_PREFIXLEN = 8;
|
||||||
constexpr size_t SHRPX_MAX_UDP_PAYLOAD_SIZE = 1280;
|
constexpr size_t SHRPX_MAX_UDP_PAYLOAD_SIZE = 1280;
|
||||||
|
constexpr size_t SHRPX_QUIC_STATELESS_RESET_SECRETLEN = 32;
|
||||||
|
constexpr size_t SHRPX_QUIC_TOKEN_SECRETLEN = 32;
|
||||||
|
|
||||||
ngtcp2_tstamp quic_timestamp();
|
ngtcp2_tstamp quic_timestamp();
|
||||||
|
|
||||||
|
@ -55,6 +57,10 @@ int generate_quic_stateless_reset_token(uint8_t *token, const ngtcp2_cid *cid,
|
||||||
const uint8_t *secret,
|
const uint8_t *secret,
|
||||||
size_t secretlen);
|
size_t secretlen);
|
||||||
|
|
||||||
|
int generate_quic_stateless_reset_secret(uint8_t *secret);
|
||||||
|
|
||||||
|
int generate_quic_token_secret(uint8_t *secret);
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
||||||
#endif // SHRPX_QUIC_H
|
#endif // SHRPX_QUIC_H
|
||||||
|
|
|
@ -254,13 +254,11 @@ int QUICConnectionHandler::send_stateless_reset(const UpstreamAddr *faddr,
|
||||||
|
|
||||||
ngtcp2_cid_init(&cid, dcid, dcidlen);
|
ngtcp2_cid_init(&cid, dcid, dcidlen);
|
||||||
|
|
||||||
auto config = get_config();
|
auto &quic_secret = worker_->get_quic_secret();
|
||||||
auto &quicconf = config->quic;
|
auto &secret = quic_secret->stateless_reset_secret;
|
||||||
auto &stateless_resetconf = quicconf.stateless_reset;
|
|
||||||
|
|
||||||
rv = generate_quic_stateless_reset_token(token.data(), &cid,
|
rv = generate_quic_stateless_reset_token(token.data(), &cid, secret.data(),
|
||||||
stateless_resetconf.secret.data(),
|
secret.size());
|
||||||
stateless_resetconf.secret.size());
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -954,6 +954,14 @@ int Worker::create_quic_server_socket(UpstreamAddr &faddr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *Worker::get_cid_prefix() const { return cid_prefix_.data(); }
|
const uint8_t *Worker::get_cid_prefix() const { return cid_prefix_.data(); }
|
||||||
|
|
||||||
|
void Worker::set_quic_secret(const std::shared_ptr<QUICSecret> &secret) {
|
||||||
|
quic_secret_ = secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<QUICSecret> &Worker::get_quic_secret() const {
|
||||||
|
return quic_secret_;
|
||||||
|
}
|
||||||
#endif // ENABLE_HTTP3
|
#endif // ENABLE_HTTP3
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -367,6 +367,10 @@ public:
|
||||||
|
|
||||||
const uint8_t *get_cid_prefix() const;
|
const uint8_t *get_cid_prefix() const;
|
||||||
|
|
||||||
|
void set_quic_secret(const std::shared_ptr<QUICSecret> &secret);
|
||||||
|
|
||||||
|
const std::shared_ptr<QUICSecret> &get_quic_secret() const;
|
||||||
|
|
||||||
# ifdef HAVE_LIBBPF
|
# ifdef HAVE_LIBBPF
|
||||||
bool should_attach_bpf() const;
|
bool should_attach_bpf() const;
|
||||||
|
|
||||||
|
@ -402,6 +406,7 @@ private:
|
||||||
std::array<uint8_t, SHRPX_QUIC_CID_PREFIXLEN> cid_prefix_;
|
std::array<uint8_t, SHRPX_QUIC_CID_PREFIXLEN> cid_prefix_;
|
||||||
std::vector<UpstreamAddr> quic_upstream_addrs_;
|
std::vector<UpstreamAddr> quic_upstream_addrs_;
|
||||||
std::vector<std::unique_ptr<QUICListener>> quic_listeners_;
|
std::vector<std::unique_ptr<QUICListener>> quic_listeners_;
|
||||||
|
std::shared_ptr<QUICSecret> quic_secret_;
|
||||||
#endif // ENABLE_HTTP3
|
#endif // ENABLE_HTTP3
|
||||||
|
|
||||||
std::shared_ptr<DownstreamConfig> downstreamconf_;
|
std::shared_ptr<DownstreamConfig> downstreamconf_;
|
||||||
|
|
Loading…
Reference in New Issue