You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2018/04/04 06:21:31 UTC
[trafficserver] 04/04: Add Version Negotiation support on QUIC
client
This is an automated email from the ASF dual-hosted git repository.
masaori pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 6ff1a3f373f7af9339285c6f4b96d5636ca8912c
Author: Masaori Koshiba <ma...@apache.org>
AuthorDate: Wed Apr 4 15:15:47 2018 +0900
Add Version Negotiation support on QUIC client
To enforce version negotiation exercise, set below config 1.
```
proxy.config.quic.client.vn_exercise_enabled
```
---
iocore/net/P_QUICNetVConnection.h | 1 +
iocore/net/QUICNetVConnection.cc | 21 ++++++++++++++++-
iocore/net/quic/QUICConfig.cc | 8 +++++++
iocore/net/quic/QUICConfig.h | 3 +++
iocore/net/quic/QUICHandshake.cc | 49 +++++++++++++++++++++++++++++++++++----
iocore/net/quic/QUICHandshake.h | 4 +++-
mgmt/RecordsConfig.cc | 2 ++
7 files changed, 82 insertions(+), 6 deletions(-)
diff --git a/iocore/net/P_QUICNetVConnection.h b/iocore/net/P_QUICNetVConnection.h
index eb7defd..e68b2e2 100644
--- a/iocore/net/P_QUICNetVConnection.h
+++ b/iocore/net/P_QUICNetVConnection.h
@@ -285,6 +285,7 @@ private:
QUICErrorUPtr _recv_and_ack(QUICPacketUPtr packet);
QUICErrorUPtr _state_handshake_process_packet(QUICPacketUPtr packet);
+ QUICErrorUPtr _state_handshake_process_version_negotiation_packet(QUICPacketUPtr packet);
QUICErrorUPtr _state_handshake_process_initial_packet(QUICPacketUPtr packet);
QUICErrorUPtr _state_handshake_process_retry_packet(QUICPacketUPtr packet);
QUICErrorUPtr _state_handshake_process_handshake_packet(QUICPacketUPtr packet);
diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc
index a22a7b1..6ea5de4 100644
--- a/iocore/net/QUICNetVConnection.cc
+++ b/iocore/net/QUICNetVConnection.cc
@@ -186,7 +186,7 @@ QUICNetVConnection::start()
this->_handshake_handler = new QUICHandshake(this, params->server_ssl_ctx(), this->_reset_token, params->stateless_retry());
} else {
this->_handshake_handler = new QUICHandshake(this, params->client_ssl_ctx());
- this->_handshake_handler->start(&this->_packet_factory);
+ this->_handshake_handler->start(&this->_packet_factory, params->vn_exercise_enabled());
}
this->_application_map = new QUICApplicationMap();
this->_application_map->set(STREAM_ID_FOR_HANDSHAKE, this->_handshake_handler);
@@ -783,6 +783,9 @@ QUICNetVConnection::_state_handshake_process_packet(QUICPacketUPtr packet)
{
QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError());
switch (packet->type()) {
+ case QUICPacketType::VERSION_NEGOTIATION:
+ error = this->_state_handshake_process_version_negotiation_packet(std::move(packet));
+ break;
case QUICPacketType::INITIAL:
error = this->_state_handshake_process_initial_packet(std::move(packet));
break;
@@ -806,6 +809,22 @@ QUICNetVConnection::_state_handshake_process_packet(QUICPacketUPtr packet)
}
QUICErrorUPtr
+QUICNetVConnection::_state_handshake_process_version_negotiation_packet(QUICPacketUPtr packet)
+{
+ QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError());
+
+ if (packet->connection_id() != this->connection_id()) {
+ QUICConDebug("Ignore Version Negotiation packet");
+ return error;
+ }
+
+ error = this->_handshake_handler->negotiate_version(packet.get(), &this->_packet_factory);
+ // Initial packet will be retransmited with negotiated version
+
+ return error;
+}
+
+QUICErrorUPtr
QUICNetVConnection::_state_handshake_process_initial_packet(QUICPacketUPtr packet)
{
if (packet->size() < MINIMUM_INITIAL_PACKET_SIZE) {
diff --git a/iocore/net/quic/QUICConfig.cc b/iocore/net/quic/QUICConfig.cc
index 5d5654b..897002b 100644
--- a/iocore/net/quic/QUICConfig.cc
+++ b/iocore/net/quic/QUICConfig.cc
@@ -121,6 +121,8 @@ QUICConfigParams::initialize()
REC_EstablishStaticConfigInt32U(this->_server_id, "proxy.config.quic.server_id");
REC_EstablishStaticConfigInt32(this->_connection_table_size, "proxy.config.quic.connection_table.size");
REC_EstablishStaticConfigInt32U(this->_stateless_retry, "proxy.config.quic.stateless_retry");
+ REC_EstablishStaticConfigInt32U(this->_vn_exercise_enabled, "proxy.config.quic.client.vn_exercise_enabled");
+
REC_ReadConfigStringAlloc(this->_server_supported_groups, "proxy.config.quic.server.supported_groups");
REC_ReadConfigStringAlloc(this->_client_supported_groups, "proxy.config.quic.client.supported_groups");
@@ -184,6 +186,12 @@ QUICConfigParams::stateless_retry() const
}
uint32_t
+QUICConfigParams::vn_exercise_enabled() const
+{
+ return this->_vn_exercise_enabled;
+}
+
+uint32_t
QUICConfigParams::initial_max_data() const
{
return this->_initial_max_data;
diff --git a/iocore/net/quic/QUICConfig.h b/iocore/net/quic/QUICConfig.h
index af76499..3de36c7 100644
--- a/iocore/net/quic/QUICConfig.h
+++ b/iocore/net/quic/QUICConfig.h
@@ -46,6 +46,8 @@ public:
uint32_t server_id() const;
static int connection_table_size();
uint32_t stateless_retry() const;
+ uint32_t vn_exercise_enabled() const;
+
const char *server_supported_groups() const;
const char *client_supported_groups() const;
@@ -76,6 +78,7 @@ private:
uint32_t _initial_max_stream_data = 0;
uint32_t _server_id = 0;
uint32_t _stateless_retry = 0;
+ uint32_t _vn_exercise_enabled = 0;
uint32_t _initial_max_stream_id_bidi_in = 100;
uint32_t _initial_max_stream_id_bidi_out = 101;
diff --git a/iocore/net/quic/QUICHandshake.cc b/iocore/net/quic/QUICHandshake.cc
index f6a6cec..5d2484e 100644
--- a/iocore/net/quic/QUICHandshake.cc
+++ b/iocore/net/quic/QUICHandshake.cc
@@ -116,10 +116,16 @@ QUICHandshake::~QUICHandshake()
}
QUICErrorUPtr
-QUICHandshake::start(QUICPacketFactory *packet_factory)
+QUICHandshake::start(QUICPacketFactory *packet_factory, bool vn_exercise_enabled)
{
- this->_load_local_client_transport_parameters(QUIC_SUPPORTED_VERSIONS[0]);
- packet_factory->set_version(QUIC_SUPPORTED_VERSIONS[0]);
+ QUICVersion initital_version = QUIC_SUPPORTED_VERSIONS[0];
+ if (vn_exercise_enabled) {
+ initital_version = QUIC_EXERCISE_VERSIONS;
+ }
+
+ this->_load_local_client_transport_parameters(initital_version);
+ packet_factory->set_version(initital_version);
+
return QUICErrorUPtr(new QUICNoError());
}
@@ -147,6 +153,36 @@ QUICHandshake::start(const QUICPacket *initial_packet, QUICPacketFactory *packet
return QUICErrorUPtr(new QUICNoError());
}
+QUICErrorUPtr
+QUICHandshake::negotiate_version(const QUICPacket *vn, QUICPacketFactory *packet_factory)
+{
+ // Client side only
+ ink_assert(this->_netvc_context == NET_VCONNECTION_OUT);
+
+ // If already negotiated, just ignore it
+ if (this->_version_negotiator->status() == QUICVersionNegotiationStatus::NEGOTIATED ||
+ this->_version_negotiator->status() == QUICVersionNegotiationStatus::VALIDATED) {
+ QUICHSDebug("Ignore Version Negotiation packet");
+ return QUICErrorUPtr(new QUICNoError());
+ }
+
+ if (vn->version() != 0x00) {
+ QUICHSDebug("Version field must be 0x00000000");
+ return QUICErrorUPtr(new QUICConnectionError(QUICTransErrorCode::PROTOCOL_VIOLATION));
+ }
+
+ if (this->_version_negotiator->negotiate(vn) == QUICVersionNegotiationStatus::NEGOTIATED) {
+ QUICVersion version = this->_version_negotiator->negotiated_version();
+ QUICHSDebug("Version negotiation succeeded: 0x%x", version);
+ packet_factory->set_version(version);
+ } else {
+ QUICHSDebug("Version negotiation failed");
+ return QUICErrorUPtr(new QUICConnectionError(QUICTransErrorCode::VERSION_NEGOTIATION_ERROR));
+ }
+
+ return QUICErrorUPtr(new QUICNoError());
+}
+
bool
QUICHandshake::is_version_negotiated() const
{
@@ -235,7 +271,12 @@ QUICHandshake::set_transport_parameters(std::shared_ptr<QUICTransportParametersI
this->_remote_transport_parameters = tp;
- // TODO Add client side implementation
+ // Version revalidation
+ if (this->_version_negotiator->validate(tp.get()) != QUICVersionNegotiationStatus::VALIDATED) {
+ QUICHSDebug("Version revalidation failed");
+ this->_abort_handshake(QUICTransErrorCode::VERSION_NEGOTIATION_ERROR);
+ return;
+ }
return;
}
diff --git a/iocore/net/quic/QUICHandshake.h b/iocore/net/quic/QUICHandshake.h
index 2005041..37e316e 100644
--- a/iocore/net/quic/QUICHandshake.h
+++ b/iocore/net/quic/QUICHandshake.h
@@ -52,7 +52,9 @@ public:
~QUICHandshake();
// for client side
- QUICErrorUPtr start(QUICPacketFactory *packet_factory);
+ QUICErrorUPtr start(QUICPacketFactory *packet_factory, bool vn_exercise_enabled);
+ QUICErrorUPtr negotiate_version(const QUICPacket *packet, QUICPacketFactory *packet_factory);
+
// for server side
QUICErrorUPtr start(const QUICPacket *initial_packet, QUICPacketFactory *packet_factory);
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index 4705eed..b69e2b5 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -1330,6 +1330,8 @@ static const RecordElement RecordsConfig[] =
,
{RECT_CONFIG, "proxy.config.quic.stateless_retry", RECD_INT, "0", RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
,
+ {RECT_CONFIG, "proxy.config.quic.client.vn_exercise_enabled", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
+ ,
{RECT_CONFIG, "proxy.config.quic.server.supported_groups", RECD_STRING, "P-256:X25519:P-384:P-521" , RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
,
{RECT_CONFIG, "proxy.config.quic.client.supported_groups", RECD_STRING, "P-256:X25519:P-384:P-521" , RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
--
To stop receiving notification emails like this one, please contact
masaori@apache.org.