nghttpx: Send nghttpx-0rtt-uniq header if request is replayable
The incoming nghttpx-0rtt-uniq header fields from inbound client are stripped by default. Use --no-strip-incoming-nghttpx-0rtt-uniq in order not to strip them.
This commit is contained in:
parent
8c6612d338
commit
5e59577e93
|
@ -31,6 +31,7 @@ HEADERS = [
|
||||||
"user-agent",
|
"user-agent",
|
||||||
"date",
|
"date",
|
||||||
"content-type",
|
"content-type",
|
||||||
|
"nghttpx-0rtt-uniq",
|
||||||
# disallowed h1 headers
|
# disallowed h1 headers
|
||||||
'connection',
|
'connection',
|
||||||
'keep-alive',
|
'keep-alive',
|
||||||
|
|
|
@ -172,6 +172,7 @@ OPTIONS = [
|
||||||
"tls-anti-replay-memcached-cert-file",
|
"tls-anti-replay-memcached-cert-file",
|
||||||
"tls-anti-replay-memcached-private-key-file",
|
"tls-anti-replay-memcached-private-key-file",
|
||||||
"tls-anti-replay-memcached-address-family",
|
"tls-anti-replay-memcached-address-family",
|
||||||
|
"no-strip-incoming-nghttpx-0rtt-uniq",
|
||||||
]
|
]
|
||||||
|
|
||||||
LOGVARS = [
|
LOGVARS = [
|
||||||
|
|
10
src/http2.cc
10
src/http2.cc
|
@ -434,6 +434,11 @@ void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva,
|
||||||
kv = &(*it_via);
|
kv = &(*it_via);
|
||||||
it_via = it;
|
it_via = it;
|
||||||
break;
|
break;
|
||||||
|
case HD_NGHTTPX_0RTT_UNIQ:
|
||||||
|
if (flags & HDOP_STRIP_NGHTTPX_ZERO_RTT_UNIQ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
nva.push_back(
|
nva.push_back(
|
||||||
make_nv_internal(kv->name, kv->value, kv->no_index, nv_flags));
|
make_nv_internal(kv->name, kv->value, kv->no_index, nv_flags));
|
||||||
|
@ -920,6 +925,11 @@ int lookup_token(const uint8_t *name, size_t namelen) {
|
||||||
return HD_X_FORWARDED_PROTO;
|
return HD_X_FORWARDED_PROTO;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'q':
|
||||||
|
if (util::streq_l("nghttpx-0rtt-uni", name, 16)) {
|
||||||
|
return HD_NGHTTPX_0RTT_UNIQ;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,9 +203,13 @@ enum HeaderBuildOp {
|
||||||
// Via header fields must be stripped. If this flag is not set, all
|
// Via header fields must be stripped. If this flag is not set, all
|
||||||
// Via header fields other than last one are added.
|
// Via header fields other than last one are added.
|
||||||
HDOP_STRIP_VIA = 1 << 3,
|
HDOP_STRIP_VIA = 1 << 3,
|
||||||
|
// nghttpx-0rtt-uniq header fields must be stripped. If this flag
|
||||||
|
// is not set, all nghttpx-0rtt-uniq header fields are added.
|
||||||
|
HDOP_STRIP_NGHTTPX_ZERO_RTT_UNIQ = 1 << 4,
|
||||||
// Strip above all header fields.
|
// Strip above all header fields.
|
||||||
HDOP_STRIP_ALL = HDOP_STRIP_FORWARDED | HDOP_STRIP_X_FORWARDED_FOR |
|
HDOP_STRIP_ALL = HDOP_STRIP_FORWARDED | HDOP_STRIP_X_FORWARDED_FOR |
|
||||||
HDOP_STRIP_X_FORWARDED_PROTO | HDOP_STRIP_VIA,
|
HDOP_STRIP_X_FORWARDED_PROTO | HDOP_STRIP_VIA |
|
||||||
|
HDOP_STRIP_NGHTTPX_ZERO_RTT_UNIQ,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Appends headers in |headers| to |nv|. |headers| must be indexed
|
// Appends headers in |headers| to |nv|. |headers| must be indexed
|
||||||
|
@ -312,6 +316,7 @@ enum {
|
||||||
HD_KEEP_ALIVE,
|
HD_KEEP_ALIVE,
|
||||||
HD_LINK,
|
HD_LINK,
|
||||||
HD_LOCATION,
|
HD_LOCATION,
|
||||||
|
HD_NGHTTPX_0RTT_UNIQ,
|
||||||
HD_PROXY_CONNECTION,
|
HD_PROXY_CONNECTION,
|
||||||
HD_SERVER,
|
HD_SERVER,
|
||||||
HD_TE,
|
HD_TE,
|
||||||
|
|
11
src/shrpx.cc
11
src/shrpx.cc
|
@ -1486,6 +1486,7 @@ void fill_default_config(Config *config) {
|
||||||
httpconf.max_requests = std::numeric_limits<size_t>::max();
|
httpconf.max_requests = std::numeric_limits<size_t>::max();
|
||||||
httpconf.xfp.add = true;
|
httpconf.xfp.add = true;
|
||||||
httpconf.xfp.strip_incoming = true;
|
httpconf.xfp.strip_incoming = true;
|
||||||
|
httpconf.zero_rtt_uniq.strip_incoming = true;
|
||||||
|
|
||||||
auto &http2conf = config->http2;
|
auto &http2conf = config->http2;
|
||||||
{
|
{
|
||||||
|
@ -2615,6 +2616,9 @@ HTTP:
|
||||||
Default: obfuscated
|
Default: obfuscated
|
||||||
--no-via Don't append to Via header field. If Via header field
|
--no-via Don't append to Via header field. If Via header field
|
||||||
is received, it is left unaltered.
|
is received, it is left unaltered.
|
||||||
|
--no-strip-incoming-nghttpx-0rtt-uniq
|
||||||
|
Don't strip nghttpx-0rtt-uniq header field from inbound
|
||||||
|
client requests.
|
||||||
--no-location-rewrite
|
--no-location-rewrite
|
||||||
Don't rewrite location header field in default mode.
|
Don't rewrite location header field in default mode.
|
||||||
When --http2-proxy is used, location header field will
|
When --http2-proxy is used, location header field will
|
||||||
|
@ -3457,6 +3461,8 @@ int main(int argc, char **argv) {
|
||||||
required_argument, &flag, 162},
|
required_argument, &flag, 162},
|
||||||
{SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE.c_str(),
|
{SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE.c_str(),
|
||||||
required_argument, &flag, 163},
|
required_argument, &flag, 163},
|
||||||
|
{SHRPX_OPT_NO_STRIP_INCOMING_NGHTTPX_0RTT_UNIQ.c_str(), no_argument,
|
||||||
|
&flag, 164},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
|
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
@ -4239,6 +4245,11 @@ int main(int argc, char **argv) {
|
||||||
SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE,
|
SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE,
|
||||||
StringRef{optarg});
|
StringRef{optarg});
|
||||||
break;
|
break;
|
||||||
|
case 164:
|
||||||
|
// --no-strip-incoming-nghttpx-0rtt-uniq
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_NO_STRIP_INCOMING_NGHTTPX_0RTT_UNIQ,
|
||||||
|
StringRef::from_lit("yes"));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2269,6 +2269,11 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
return SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO;
|
return SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'q':
|
||||||
|
if (util::strieq_l("no-strip-incoming-nghttpx-0rtt-uni", name, 34)) {
|
||||||
|
return SHRPX_OPTID_NO_STRIP_INCOMING_NGHTTPX_0RTT_UNIQ;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
if (util::strieq_l("frontend-http2-dump-response-heade", name, 34)) {
|
if (util::strieq_l("frontend-http2-dump-response-heade", name, 34)) {
|
||||||
return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER;
|
return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER;
|
||||||
|
@ -3590,6 +3595,10 @@ int parse_config(Config *config, int optid, const StringRef &opt,
|
||||||
case SHRPX_OPTID_NO_VERIFY_OCSP:
|
case SHRPX_OPTID_NO_VERIFY_OCSP:
|
||||||
config->tls.ocsp.no_verify = util::strieq_l("yes", optarg);
|
config->tls.ocsp.no_verify = util::strieq_l("yes", optarg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
case SHRPX_OPTID_NO_STRIP_INCOMING_NGHTTPX_0RTT_UNIQ:
|
||||||
|
config->http.zero_rtt_uniq.strip_incoming = !util::strieq_l("yes", optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_CONF:
|
case SHRPX_OPTID_CONF:
|
||||||
LOG(WARN) << "conf: ignored";
|
LOG(WARN) << "conf: ignored";
|
||||||
|
|
|
@ -351,6 +351,8 @@ constexpr auto SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE =
|
||||||
StringRef::from_lit("tls-anti-replay-memcached-private-key-file");
|
StringRef::from_lit("tls-anti-replay-memcached-private-key-file");
|
||||||
constexpr auto SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_ADDRESS_FAMILY =
|
constexpr auto SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_ADDRESS_FAMILY =
|
||||||
StringRef::from_lit("tls-anti-replay-memcached-address-family");
|
StringRef::from_lit("tls-anti-replay-memcached-address-family");
|
||||||
|
constexpr auto SHRPX_OPT_NO_STRIP_INCOMING_NGHTTPX_0RTT_UNIQ =
|
||||||
|
StringRef::from_lit("no-strip-incoming-nghttpx-0rtt-uniq");
|
||||||
|
|
||||||
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
|
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
|
||||||
|
|
||||||
|
@ -704,6 +706,9 @@ struct HttpConfig {
|
||||||
bool add;
|
bool add;
|
||||||
bool strip_incoming;
|
bool strip_incoming;
|
||||||
} xfp;
|
} xfp;
|
||||||
|
struct {
|
||||||
|
bool strip_incoming;
|
||||||
|
} zero_rtt_uniq;
|
||||||
std::vector<AltSvc> altsvcs;
|
std::vector<AltSvc> altsvcs;
|
||||||
std::vector<ErrorPage> error_pages;
|
std::vector<ErrorPage> error_pages;
|
||||||
HeaderRefs add_request_headers;
|
HeaderRefs add_request_headers;
|
||||||
|
@ -1096,6 +1101,7 @@ enum {
|
||||||
SHRPX_OPTID_NO_OCSP,
|
SHRPX_OPTID_NO_OCSP,
|
||||||
SHRPX_OPTID_NO_SERVER_PUSH,
|
SHRPX_OPTID_NO_SERVER_PUSH,
|
||||||
SHRPX_OPTID_NO_SERVER_REWRITE,
|
SHRPX_OPTID_NO_SERVER_REWRITE,
|
||||||
|
SHRPX_OPTID_NO_STRIP_INCOMING_NGHTTPX_0RTT_UNIQ,
|
||||||
SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO,
|
SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO,
|
||||||
SHRPX_OPTID_NO_VERIFY_OCSP,
|
SHRPX_OPTID_NO_VERIFY_OCSP,
|
||||||
SHRPX_OPTID_NO_VIA,
|
SHRPX_OPTID_NO_VIA,
|
||||||
|
|
|
@ -61,6 +61,8 @@ struct TLSConnection {
|
||||||
DefaultPeekMemchunks rbuf;
|
DefaultPeekMemchunks rbuf;
|
||||||
// Stores TLSv1.3 early data.
|
// Stores TLSv1.3 early data.
|
||||||
DefaultMemchunks earlybuf;
|
DefaultMemchunks earlybuf;
|
||||||
|
// Message digest of ClientHello in hex string.
|
||||||
|
StringRef ch_hex_md;
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
SSL_SESSION *cached_session;
|
SSL_SESSION *cached_session;
|
||||||
MemcachedRequest *cached_session_lookup_req;
|
MemcachedRequest *cached_session_lookup_req;
|
||||||
|
|
|
@ -271,7 +271,7 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
num_cookies = downstream_->count_crumble_request_cookie();
|
num_cookies = downstream_->count_crumble_request_cookie();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9 means:
|
// 10 means:
|
||||||
// 1. :method
|
// 1. :method
|
||||||
// 2. :scheme
|
// 2. :scheme
|
||||||
// 3. :path
|
// 3. :path
|
||||||
|
@ -281,8 +281,9 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
// 7. x-forwarded-proto (optional)
|
// 7. x-forwarded-proto (optional)
|
||||||
// 8. te (optional)
|
// 8. te (optional)
|
||||||
// 9. forwarded (optional)
|
// 9. forwarded (optional)
|
||||||
|
// 10. nghttpx-0rtt-uniq (optional)
|
||||||
auto nva = std::vector<nghttp2_nv>();
|
auto nva = std::vector<nghttp2_nv>();
|
||||||
nva.reserve(req.fs.headers().size() + 9 + num_cookies +
|
nva.reserve(req.fs.headers().size() + 10 + num_cookies +
|
||||||
httpconf.add_request_headers.size());
|
httpconf.add_request_headers.size());
|
||||||
|
|
||||||
nva.push_back(
|
nva.push_back(
|
||||||
|
@ -311,11 +312,15 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
auto &fwdconf = httpconf.forwarded;
|
auto &fwdconf = httpconf.forwarded;
|
||||||
auto &xffconf = httpconf.xff;
|
auto &xffconf = httpconf.xff;
|
||||||
auto &xfpconf = httpconf.xfp;
|
auto &xfpconf = httpconf.xfp;
|
||||||
|
auto &zero_rtt_uniqconf = httpconf.zero_rtt_uniq;
|
||||||
|
|
||||||
uint32_t build_flags =
|
uint32_t build_flags =
|
||||||
(fwdconf.strip_incoming ? http2::HDOP_STRIP_FORWARDED : 0) |
|
(fwdconf.strip_incoming ? http2::HDOP_STRIP_FORWARDED : 0) |
|
||||||
(xffconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_FOR : 0) |
|
(xffconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_FOR : 0) |
|
||||||
(xfpconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_PROTO : 0);
|
(xfpconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_PROTO : 0) |
|
||||||
|
(zero_rtt_uniqconf.strip_incoming
|
||||||
|
? http2::HDOP_STRIP_NGHTTPX_ZERO_RTT_UNIQ
|
||||||
|
: 0);
|
||||||
|
|
||||||
http2::copy_headers_to_nva_nocopy(nva, req.fs.headers(), build_flags);
|
http2::copy_headers_to_nva_nocopy(nva, req.fs.headers(), build_flags);
|
||||||
|
|
||||||
|
@ -326,6 +331,15 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
auto upstream = downstream_->get_upstream();
|
auto upstream = downstream_->get_upstream();
|
||||||
auto handler = upstream->get_client_handler();
|
auto handler = upstream->get_client_handler();
|
||||||
|
|
||||||
|
#if OPENSSL_1_1_1_API
|
||||||
|
auto conn = handler->get_connection();
|
||||||
|
|
||||||
|
if (!SSL_is_init_finished(conn->tls.ssl)) {
|
||||||
|
nva.push_back(
|
||||||
|
http2::make_nv_ls_nocopy("nghttpx-0rtt-uniq", conn->tls.ch_hex_md));
|
||||||
|
}
|
||||||
|
#endif // OPENSSL_1_1_1_API
|
||||||
|
|
||||||
auto fwd =
|
auto fwd =
|
||||||
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
|
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
|
||||||
|
|
||||||
|
|
|
@ -535,11 +535,15 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
auto &fwdconf = httpconf.forwarded;
|
auto &fwdconf = httpconf.forwarded;
|
||||||
auto &xffconf = httpconf.xff;
|
auto &xffconf = httpconf.xff;
|
||||||
auto &xfpconf = httpconf.xfp;
|
auto &xfpconf = httpconf.xfp;
|
||||||
|
auto &zero_rtt_uniqconf = httpconf.zero_rtt_uniq;
|
||||||
|
|
||||||
uint32_t build_flags =
|
uint32_t build_flags =
|
||||||
(fwdconf.strip_incoming ? http2::HDOP_STRIP_FORWARDED : 0) |
|
(fwdconf.strip_incoming ? http2::HDOP_STRIP_FORWARDED : 0) |
|
||||||
(xffconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_FOR : 0) |
|
(xffconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_FOR : 0) |
|
||||||
(xfpconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_PROTO : 0);
|
(xfpconf.strip_incoming ? http2::HDOP_STRIP_X_FORWARDED_PROTO : 0) |
|
||||||
|
(zero_rtt_uniqconf.strip_incoming
|
||||||
|
? http2::HDOP_STRIP_NGHTTPX_ZERO_RTT_UNIQ
|
||||||
|
: 0);
|
||||||
|
|
||||||
http2::build_http1_headers_from_headers(buf, req.fs.headers(), build_flags);
|
http2::build_http1_headers_from_headers(buf, req.fs.headers(), build_flags);
|
||||||
|
|
||||||
|
@ -580,6 +584,16 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
auto upstream = downstream_->get_upstream();
|
auto upstream = downstream_->get_upstream();
|
||||||
auto handler = upstream->get_client_handler();
|
auto handler = upstream->get_client_handler();
|
||||||
|
|
||||||
|
#if OPENSSL_1_1_1_API
|
||||||
|
auto conn = handler->get_connection();
|
||||||
|
|
||||||
|
if (!SSL_is_init_finished(conn->tls.ssl)) {
|
||||||
|
buf->append("Nghttpx-0rtt-uniq: ");
|
||||||
|
buf->append(conn->tls.ch_hex_md);
|
||||||
|
buf->append("\r\n");
|
||||||
|
}
|
||||||
|
#endif // OPENSSL_1_1_1_API
|
||||||
|
|
||||||
auto fwd =
|
auto fwd =
|
||||||
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
|
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
|
||||||
|
|
||||||
|
|
|
@ -580,7 +580,7 @@ int early_cb(SSL *ssl, int *al, void *arg) {
|
||||||
|
|
||||||
auto &tlsconf = get_config()->tls;
|
auto &tlsconf = get_config()->tls;
|
||||||
|
|
||||||
auto hex_md =
|
conn->tls.ch_hex_md =
|
||||||
util::format_hex(balloc, StringRef{std::begin(md), std::end(md)});
|
util::format_hex(balloc, StringRef{std::begin(md), std::end(md)});
|
||||||
|
|
||||||
if (tlsconf.anti_replay.memcached.host.empty()) {
|
if (tlsconf.anti_replay.memcached.host.empty()) {
|
||||||
|
@ -590,7 +590,7 @@ int early_cb(SSL *ssl, int *al, void *arg) {
|
||||||
auto req = make_unique<MemcachedRequest>();
|
auto req = make_unique<MemcachedRequest>();
|
||||||
req->op = MEMCACHED_OP_ADD;
|
req->op = MEMCACHED_OP_ADD;
|
||||||
req->key = MEMCACHED_ANTI_REPLY_KEY_PREFIX.str();
|
req->key = MEMCACHED_ANTI_REPLY_KEY_PREFIX.str();
|
||||||
req->key += hex_md;
|
req->key += conn->tls.ch_hex_md;
|
||||||
|
|
||||||
// TODO No value at the moment
|
// TODO No value at the moment
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue