1 /** @file
2 *
3 * A brief file description
4 *
5 * @section license License
6 *
7 * Licensed to the Apache Software Foundation (ASF) under one
8 * or more contributor license agreements. See the NOTICE file
9 * distributed with this work for additional information
10 * regarding copyright ownership. The ASF licenses this file
11 * to you under the Apache License, Version 2.0 (the
12 * "License"); you may not use this file except in compliance
13 * with the License. You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24 #include "QUICConfig.h"
25
26 #include <openssl/ssl.h>
27
28 #include <records/I_RecHttp.h>
29
30 #include "P_SSLConfig.h"
31
32 #include "QUICGlobals.h"
33 #include "QUICTransportParameters.h"
34
35 int QUICConfig::_config_id = 0;
36 int QUICConfigParams::_connection_table_size = 65521;
37
38 SSL_CTX *
quic_new_ssl_ctx()39 quic_new_ssl_ctx()
40 {
41 SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
42
43 SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
44 SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
45
46 #ifndef OPENSSL_IS_BORINGSSL
47 // FIXME: OpenSSL (1.1.1-alpha) enable this option by default. But this should be removed when OpenSSL disable this by default.
48 SSL_CTX_clear_options(ssl_ctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
49
50 SSL_CTX_set_max_early_data(ssl_ctx, UINT32_C(0xFFFFFFFF));
51
52 #else
53 // QUIC Transport Parameters are accessible with SSL_set_quic_transport_params and SSL_get_peer_quic_transport_params
54 #endif
55
56 #ifdef SSL_MODE_QUIC_HACK
57 // tatsuhiro-t's custom OpenSSL for QUIC draft-13
58 // https://github.com/tatsuhiro-t/openssl/tree/quic-draft-13
59 SSL_CTX_set_mode(ssl_ctx, SSL_MODE_QUIC_HACK);
60 SSL_CTX_add_custom_ext(ssl_ctx, QUICTransportParametersHandler::TRANSPORT_PARAMETER_ID,
61 SSL_EXT_TLS_ONLY | SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
62 &QUICTransportParametersHandler::add, &QUICTransportParametersHandler::free, nullptr,
63 &QUICTransportParametersHandler::parse, nullptr);
64
65 #endif
66
67 return ssl_ctx;
68 }
69
70 /**
71 ALPN and SNI should be set to SSL object with NETVC_OPTIONS
72 **/
73 static shared_SSL_CTX
quic_init_client_ssl_ctx(const QUICConfigParams * params)74 quic_init_client_ssl_ctx(const QUICConfigParams *params)
75 {
76 std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> ssl_ctx(nullptr, &SSL_CTX_free);
77 ssl_ctx.reset(quic_new_ssl_ctx());
78
79 #if defined(SSL_CTX_set1_groups_list) || defined(SSL_CTX_set1_curves_list)
80 if (params->client_supported_groups() != nullptr) {
81 #ifdef SSL_CTX_set1_groups_list
82 if (SSL_CTX_set1_groups_list(ssl_ctx.get(), params->client_supported_groups()) != 1) {
83 #else
84 if (SSL_CTX_set1_curves_list(ssl_ctx.get(), params->client_supported_groups()) != 1) {
85 #endif
86 Error("SSL_CTX_set1_groups_list failed");
87 }
88 }
89 #endif
90
91 if (params->client_session_file() != nullptr) {
92 SSL_CTX_set_session_cache_mode(ssl_ctx.get(), SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE);
93 SSL_CTX_sess_set_new_cb(ssl_ctx.get(), QUIC::ssl_client_new_session);
94 }
95
96 #ifdef SSL_MODE_QUIC_HACK
97 if (params->client_keylog_file() != nullptr) {
98 SSL_CTX_set_keylog_callback(ssl_ctx.get(), QUIC::ssl_client_keylog_cb);
99 }
100 #endif
101
102 return ssl_ctx;
103 }
104
105 //
106 // QUICConfigParams
107 //
108 QUICConfigParams::~QUICConfigParams()
109 {
110 this->_server_supported_groups = (char *)ats_free_null(this->_server_supported_groups);
111 this->_client_supported_groups = (char *)ats_free_null(this->_client_supported_groups);
112
113 SSL_CTX_free(this->_client_ssl_ctx.get());
114 };
115
116 void
117 QUICConfigParams::initialize()
118 {
119 REC_EstablishStaticConfigInt32U(this->_instance_id, "proxy.config.quic.instance_id");
120 REC_EstablishStaticConfigInt32(this->_connection_table_size, "proxy.config.quic.connection_table.size");
121 REC_EstablishStaticConfigInt32U(this->_stateless_retry, "proxy.config.quic.server.stateless_retry_enabled");
122 REC_EstablishStaticConfigInt32U(this->_vn_exercise_enabled, "proxy.config.quic.client.vn_exercise_enabled");
123 REC_EstablishStaticConfigInt32U(this->_cm_exercise_enabled, "proxy.config.quic.client.cm_exercise_enabled");
124 REC_EstablishStaticConfigInt32U(this->_quantum_readiness_test_enabled_out,
125 "proxy.config.quic.client.quantum_readiness_test_enabled");
126 REC_EstablishStaticConfigInt32U(this->_quantum_readiness_test_enabled_in,
127 "proxy.config.quic.server.quantum_readiness_test_enabled");
128
129 REC_ReadConfigStringAlloc(this->_server_supported_groups, "proxy.config.quic.server.supported_groups");
130 REC_ReadConfigStringAlloc(this->_client_supported_groups, "proxy.config.quic.client.supported_groups");
131 REC_ReadConfigStringAlloc(this->_client_session_file, "proxy.config.quic.client.session_file");
132 REC_ReadConfigStringAlloc(this->_client_keylog_file, "proxy.config.quic.client.keylog_file");
133 REC_ReadConfigStringAlloc(this->_qlog_dir, "proxy.config.quic.qlog_dir");
134
135 // Transport Parameters
136 REC_EstablishStaticConfigInt32U(this->_no_activity_timeout_in, "proxy.config.quic.no_activity_timeout_in");
137 REC_EstablishStaticConfigInt32U(this->_no_activity_timeout_out, "proxy.config.quic.no_activity_timeout_out");
138 REC_ReadConfigStringAlloc(this->_preferred_address_ipv4, "proxy.config.quic.preferred_address_ipv4");
139 if (this->_preferred_address_ipv4) {
140 ats_ip_pton(this->_preferred_address_ipv4, &this->_preferred_endpoint_ipv4);
141 }
142 REC_ReadConfigStringAlloc(this->_preferred_address_ipv6, "proxy.config.quic.preferred_address_ipv6");
143 if (this->_preferred_address_ipv6) {
144 ats_ip_pton(this->_preferred_address_ipv6, &this->_preferred_endpoint_ipv6);
145 }
146 REC_EstablishStaticConfigInt32U(this->_initial_max_data_in, "proxy.config.quic.initial_max_data_in");
147 REC_EstablishStaticConfigInt32U(this->_initial_max_data_out, "proxy.config.quic.initial_max_data_out");
148 REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_bidi_local_in,
149 "proxy.config.quic.initial_max_stream_data_bidi_local_in");
150 REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_bidi_local_out,
151 "proxy.config.quic.initial_max_stream_data_bidi_local_out");
152 REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_bidi_remote_in,
153 "proxy.config.quic.initial_max_stream_data_bidi_remote_in");
154 REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_bidi_remote_out,
155 "proxy.config.quic.initial_max_stream_data_bidi_remote_out");
156 REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_uni_in, "proxy.config.quic.initial_max_stream_data_uni_in");
157 REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_uni_out, "proxy.config.quic.initial_max_stream_data_uni_out");
158 REC_EstablishStaticConfigInt32U(this->_initial_max_streams_bidi_in, "proxy.config.quic.initial_max_streams_bidi_in");
159 REC_EstablishStaticConfigInt32U(this->_initial_max_streams_bidi_out, "proxy.config.quic.initial_max_streams_bidi_out");
160 REC_EstablishStaticConfigInt32U(this->_initial_max_streams_uni_in, "proxy.config.quic.initial_max_streams_uni_in");
161 REC_EstablishStaticConfigInt32U(this->_initial_max_streams_uni_out, "proxy.config.quic.initial_max_streams_uni_out");
162 REC_EstablishStaticConfigInt32U(this->_ack_delay_exponent_in, "proxy.config.quic.ack_delay_exponent_in");
163 REC_EstablishStaticConfigInt32U(this->_ack_delay_exponent_out, "proxy.config.quic.ack_delay_exponent_out");
164 REC_EstablishStaticConfigInt32U(this->_max_ack_delay_in, "proxy.config.quic.max_ack_delay_in");
165 REC_EstablishStaticConfigInt32U(this->_max_ack_delay_out, "proxy.config.quic.max_ack_delay_out");
166 REC_EstablishStaticConfigInt32U(this->_active_cid_limit_in, "proxy.config.quic.active_cid_limit_in");
167 REC_EstablishStaticConfigInt32U(this->_active_cid_limit_out, "proxy.config.quic.active_cid_limit_out");
168 REC_EstablishStaticConfigInt32U(this->_disable_active_migration, "proxy.config.quic.disable_active_migration");
169
170 // Loss Detection
171 REC_EstablishStaticConfigInt32U(this->_ld_packet_threshold, "proxy.config.quic.loss_detection.packet_threshold");
172 REC_EstablishStaticConfigFloat(this->_ld_time_threshold, "proxy.config.quic.loss_detection.time_threshold");
173
174 uint32_t timeout = 0;
175 REC_EstablishStaticConfigInt32U(timeout, "proxy.config.quic.loss_detection.granularity");
176 this->_ld_granularity = HRTIME_MSECONDS(timeout);
177
178 REC_EstablishStaticConfigInt32U(timeout, "proxy.config.quic.loss_detection.initial_rtt");
179 this->_ld_initial_rtt = HRTIME_MSECONDS(timeout);
180
181 // Congestion Control
182 REC_EstablishStaticConfigInt32U(this->_cc_initial_window, "proxy.config.quic.congestion_control.initial_window");
183 REC_EstablishStaticConfigInt32U(this->_cc_minimum_window, "proxy.config.quic.congestion_control.minimum_window");
184 REC_EstablishStaticConfigFloat(this->_cc_loss_reduction_factor, "proxy.config.quic.congestion_control.loss_reduction_factor");
185 REC_EstablishStaticConfigInt32U(this->_cc_persistent_congestion_threshold,
186 "proxy.config.quic.congestion_control.persistent_congestion_threshold");
187
188 this->_client_ssl_ctx = quic_init_client_ssl_ctx(this);
189 }
190
191 uint32_t
192 QUICConfigParams::no_activity_timeout_in() const
193 {
194 return this->_no_activity_timeout_in;
195 }
196
197 uint32_t
198 QUICConfigParams::no_activity_timeout_out() const
199 {
200 return this->_no_activity_timeout_out;
201 }
202
203 const IpEndpoint *
204 QUICConfigParams::preferred_address_ipv4() const
205 {
206 if (!this->_preferred_address_ipv4) {
207 return nullptr;
208 }
209
210 return &this->_preferred_endpoint_ipv4;
211 }
212
213 const IpEndpoint *
214 QUICConfigParams::preferred_address_ipv6() const
215 {
216 if (!this->_preferred_address_ipv6) {
217 return nullptr;
218 }
219
220 return &this->_preferred_endpoint_ipv6;
221 }
222
223 uint32_t
224 QUICConfigParams::instance_id() const
225 {
226 return this->_instance_id;
227 }
228
229 int
230 QUICConfigParams::connection_table_size()
231 {
232 return _connection_table_size;
233 }
234
235 uint32_t
236 QUICConfigParams::stateless_retry() const
237 {
238 return this->_stateless_retry;
239 }
240
241 uint32_t
242 QUICConfigParams::vn_exercise_enabled() const
243 {
244 return this->_vn_exercise_enabled;
245 }
246
247 uint32_t
248 QUICConfigParams::cm_exercise_enabled() const
249 {
250 return this->_cm_exercise_enabled;
251 }
252
253 uint32_t
254 QUICConfigParams::quantum_readiness_test_enabled_in() const
255 {
256 return this->_quantum_readiness_test_enabled_in;
257 }
258
259 uint32_t
260 QUICConfigParams::quantum_readiness_test_enabled_out() const
261 {
262 return this->_quantum_readiness_test_enabled_out;
263 }
264
265 uint32_t
266 QUICConfigParams::initial_max_data_in() const
267 {
268 return this->_initial_max_data_in;
269 }
270
271 uint32_t
272 QUICConfigParams::initial_max_data_out() const
273 {
274 return this->_initial_max_data_out;
275 }
276
277 uint32_t
278 QUICConfigParams::initial_max_stream_data_bidi_local_in() const
279 {
280 return this->_initial_max_stream_data_bidi_local_in;
281 }
282
283 uint32_t
284 QUICConfigParams::initial_max_stream_data_bidi_local_out() const
285 {
286 return this->_initial_max_stream_data_bidi_local_out;
287 }
288
289 uint32_t
290 QUICConfigParams::initial_max_stream_data_bidi_remote_in() const
291 {
292 return this->_initial_max_stream_data_bidi_remote_in;
293 }
294
295 uint32_t
296 QUICConfigParams::initial_max_stream_data_bidi_remote_out() const
297 {
298 return this->_initial_max_stream_data_bidi_remote_out;
299 }
300
301 uint32_t
302 QUICConfigParams::initial_max_stream_data_uni_in() const
303 {
304 return this->_initial_max_stream_data_uni_in;
305 }
306
307 uint32_t
308 QUICConfigParams::initial_max_stream_data_uni_out() const
309 {
310 return this->_initial_max_stream_data_uni_out;
311 }
312
313 uint64_t
314 QUICConfigParams::initial_max_streams_bidi_in() const
315 {
316 return this->_initial_max_streams_bidi_in;
317 }
318
319 uint64_t
320 QUICConfigParams::initial_max_streams_bidi_out() const
321 {
322 return this->_initial_max_streams_bidi_out;
323 }
324
325 uint64_t
326 QUICConfigParams::initial_max_streams_uni_in() const
327 {
328 return this->_initial_max_streams_uni_in;
329 }
330
331 uint64_t
332 QUICConfigParams::initial_max_streams_uni_out() const
333 {
334 return this->_initial_max_streams_uni_out;
335 }
336
337 uint8_t
338 QUICConfigParams::ack_delay_exponent_in() const
339 {
340 return this->_ack_delay_exponent_in;
341 }
342
343 uint8_t
344 QUICConfigParams::ack_delay_exponent_out() const
345 {
346 return this->_ack_delay_exponent_out;
347 }
348
349 uint8_t
350 QUICConfigParams::max_ack_delay_in() const
351 {
352 return this->_max_ack_delay_in;
353 }
354
355 uint8_t
356 QUICConfigParams::max_ack_delay_out() const
357 {
358 return this->_max_ack_delay_out;
359 }
360
361 uint8_t
362 QUICConfigParams::active_cid_limit_in() const
363 {
364 return this->_active_cid_limit_in;
365 }
366
367 uint8_t
368 QUICConfigParams::active_cid_limit_out() const
369 {
370 return this->_active_cid_limit_out;
371 }
372
373 bool
374 QUICConfigParams::disable_active_migration() const
375 {
376 return this->_disable_active_migration;
377 }
378
379 const char *
380 QUICConfigParams::server_supported_groups() const
381 {
382 return this->_server_supported_groups;
383 }
384
385 const char *
386 QUICConfigParams::client_supported_groups() const
387 {
388 return this->_client_supported_groups;
389 }
390
391 shared_SSL_CTX
392 QUICConfigParams::client_ssl_ctx() const
393 {
394 return this->_client_ssl_ctx;
395 }
396
397 uint32_t
398 QUICConfigParams::ld_packet_threshold() const
399 {
400 return _ld_packet_threshold;
401 }
402
403 float
404 QUICConfigParams::ld_time_threshold() const
405 {
406 return _ld_time_threshold;
407 }
408
409 ink_hrtime
410 QUICConfigParams::ld_granularity() const
411 {
412 return _ld_granularity;
413 }
414
415 ink_hrtime
416 QUICConfigParams::ld_initial_rtt() const
417 {
418 return _ld_initial_rtt;
419 }
420
421 uint32_t
422 QUICConfigParams::cc_initial_window() const
423 {
424 return _cc_initial_window;
425 }
426
427 uint32_t
428 QUICConfigParams::cc_minimum_window() const
429 {
430 return _cc_minimum_window;
431 }
432
433 float
434 QUICConfigParams::cc_loss_reduction_factor() const
435 {
436 return _cc_loss_reduction_factor;
437 }
438
439 uint32_t
440 QUICConfigParams::cc_persistent_congestion_threshold() const
441 {
442 return _cc_persistent_congestion_threshold;
443 }
444
445 uint8_t
446 QUICConfigParams::scid_len()
447 {
448 return QUICConfigParams::_scid_len;
449 }
450
451 const char *
452 QUICConfigParams::client_session_file() const
453 {
454 return this->_client_session_file;
455 }
456
457 const char *
458 QUICConfigParams::client_keylog_file() const
459 {
460 return this->_client_keylog_file;
461 }
462
463 const char *
464 QUICConfigParams::qlog_dir() const
465 {
466 return this->_qlog_dir;
467 }
468
469 //
470 // QUICConfig
471 //
472 void
473 QUICConfig::startup()
474 {
475 reconfigure();
476 }
477
478 void
479 QUICConfig::reconfigure()
480 {
481 QUICConfigParams *params;
482 params = new QUICConfigParams;
483 // re-read configuration
484 params->initialize();
485 _config_id = configProcessor.set(_config_id, params);
486
487 QUICConnectionId::SCID_LEN = params->scid_len();
488 }
489
490 QUICConfigParams *
491 QUICConfig::acquire()
492 {
493 return static_cast<QUICConfigParams *>(configProcessor.get(_config_id));
494 }
495
496 void
497 QUICConfig::release(QUICConfigParams *params)
498 {
499 configProcessor.release(_config_id, params);
500 }
501