Use deterministic replacement connection IDs
This CL removes a DoS attack vector where an attacker could grow QuicDispatcher::connection_id_map_ unboundedly. It does so by no longer using random connection IDs that are saved in connection_id_map_; instead we now generate deterministic replacement connection IDs, removing the need for a map. It should not impact the GFE because the GFE overrides QuicDispatcher::GenerateNewServerConnectionId with an already deterministic method, but is still flag protected just in case.
gfe-relnote: use deterministic replacement connection IDs, protected by new disabled flag gfe2_restart_flag_quic_deterministic_replacement_connection_ids
PiperOrigin-RevId: 264192278
Change-Id: I843bf0d846830d4b13e0bb1b470a71b2428ad7c8
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index b659bda..553fcd4 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -305,18 +305,29 @@
}
DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
version.transport_version));
- auto it = connection_id_map_.find(server_connection_id);
- if (it != connection_id_map_.end()) {
- return it->second;
+
+ if (!GetQuicRestartFlag(quic_deterministic_replacement_connection_ids)) {
+ auto it = connection_id_map_.find(server_connection_id);
+ if (it != connection_id_map_.end()) {
+ return it->second;
+ }
+ } else {
+ // TODO(dschinazi) Remove QuicDispatcher::connection_id_map_ entirely
+ // when quic_deterministic_replacement_connection_ids is deprecated.
+ QUIC_RESTART_FLAG_COUNT_N(quic_deterministic_replacement_connection_ids, 1,
+ 2);
}
QuicConnectionId new_connection_id =
GenerateNewServerConnectionId(version, server_connection_id);
DCHECK_EQ(expected_server_connection_id_length_, new_connection_id.length());
- // TODO(dschinazi) Prevent connection_id_map_ from growing indefinitely
- // before we ship a version that supports variable length connection IDs
- // to production.
- connection_id_map_.insert(
- std::make_pair(server_connection_id, new_connection_id));
+ if (!GetQuicRestartFlag(quic_deterministic_replacement_connection_ids)) {
+ connection_id_map_.insert(
+ std::make_pair(server_connection_id, new_connection_id));
+ } else {
+ // Verify that GenerateNewServerConnectionId is deterministic.
+ DCHECK_EQ(new_connection_id,
+ GenerateNewServerConnectionId(version, server_connection_id));
+ }
QUIC_DLOG(INFO) << "Replacing incoming connection ID " << server_connection_id
<< " with " << new_connection_id;
return new_connection_id;
@@ -324,8 +335,15 @@
QuicConnectionId QuicDispatcher::GenerateNewServerConnectionId(
ParsedQuicVersion /*version*/,
- QuicConnectionId /*connection_id*/) const {
- return QuicUtils::CreateRandomConnectionId();
+ QuicConnectionId connection_id) const {
+ if (!GetQuicRestartFlag(quic_deterministic_replacement_connection_ids)) {
+ return QuicUtils::CreateRandomConnectionId();
+ }
+
+ QUIC_RESTART_FLAG_COUNT_N(quic_deterministic_replacement_connection_ids, 2,
+ 2);
+
+ return QuicUtils::CreateReplacementConnectionId(connection_id);
}
bool QuicDispatcher::MaybeDispatchPacket(