узел js https minDHSize не закрывает соединение

#node.js #https #tls1.2 #diffie-hellman

Вопрос:

Я отправляю https-запрос на сервер, который предоставляет 2048-битный шифр Диффи-Хеллмана, и пытаюсь заставить свой код отклонить соединение и выдать сбой рукопожатия обратно на сервер и закрыть соединение. Я не думаю, что он используется, но у меня есть 4096-битный ключ DH в клиенте, и соединение выполняется идеально, если сервер также использует 4096-битный ключ DH.

 const dhparam = fs.readFileSync( "dhparam_4096.pem" ); const data = JSON.stringify({   part1 : "Hello",   part2 " "Name" }); const httpsOptions = {  host : address   "%"   Ethernet.GetIfaceName(),  port : service.port,  path : service.txt.path,  method : "PUT",  rejectUnauthorized : false,  ciphers : "ADH-AES256-GCM-SHA384:@SECLEVEL=0",  dhparam,  minDHSize : 4096,  headers : {   'Content-Type' : 'application/json',  'Content-Length' : data.length,  },  servername : "nameServer", } console.log( " httpsOptions =", httpsOptions );   /*** Send the request ***/   var req = https.request( httpsOptions, res =gt;  {  var data = "";  res.on( 'data', d =gt; data  = d );  res.on( 'end', d =gt;   {   if ( d ) data  = d;  console.log( "Received data =", data );  console.log( " ", data.toString() );  });  console.log( "response =", res.statusCode, res.statusMessage ); });  req.on( "error", err =gt;  {  console.log( "error =", err.code );  if ( err.code === "ERR_TLS_DH_PARAM_SIZE" )  {  console.log(" DH Key is not 4096 bits" );  req.socket.destroy();  }   }); console.log( " sending data: ". data ); req.write( data ); req.end();  

Значение minDHSize : 4096 приводит к срабатыванию события ошибки, поэтому я знаю, что механизм обнаружения работает.

У меня есть розетка.уничтожьте() на этом пути, но это, похоже, не работает.

на сервере у меня включена трассировка, и я получаю следующее:

 Received Record Header:  Version = TLS 1.0 (0x301)  Content Type = Handshake (22)  Length = 153  ClientHello, Length=149  client_version=0x303 (TLS 1.2)  Random:  gmt_unix_time=0xFE471FB1  random_bytes (len=28): 3B54266D9E916B151A9A8E940EE4D0BEE0E59C1F2693B6E637CC4D  session_id (len=0):   cipher_suites (len=4)  {0x00, 0xA7} TLS_DH_anon_WITH_AES_256_GCM_SHA384  {0x00, 0xFF} TLS_EMPTY_RENEGOTIATION_INFO_SCSV  compression_methods (len=1)  No Compression (0x00)  extensions, length = 104  extension_type=server_name(0), length=36  extension_type=session_ticket(35), length=0  extension_type=encrypt_then_mac(22), length=0  extension_type=extended_master_secret(23), length=0  extension_type=signature_algorithms(13), length=48  ecdsa_secp256r1_sha256 (0x0403)  ecdsa_secp384r1_sha384 (0x0503)  ecdsa_secp521r1_sha512 (0x0603)  ed25519 (0x0807)  ed448 (0x0808)  rsa_pss_pss_sha256 (0x0809)  rsa_pss_pss_sha384 (0x080a)  rsa_pss_pss_sha512 (0x080b)  rsa_pss_rsae_sha256 (0x0804)  rsa_pss_rsae_sha384 (0x0805)  rsa_pss_rsae_sha512 (0x0806)  rsa_pkcs1_sha256 (0x0401)  rsa_pkcs1_sha384 (0x0501)  rsa_pkcs1_sha512 (0x0601)  ecdsa_sha224 (0x0303)  ecdsa_sha1 (0x0203)  rsa_pkcs1_sha224 (0x0301)  rsa_pkcs1_sha1 (0x0201)  dsa_sha224 (0x0302)  dsa_sha1 (0x0202)  dsa_sha256 (0x0402)  dsa_sha384 (0x0502)  dsa_sha512 (0x0602)   Sent Record Header:  Version = TLS 1.2 (0x303)  Content Type = Handshake (22)  Length = 57  ServerHello, Length=53  server_version=0x303 (TLS 1.2)  Random:  gmt_unix_time=0xDB67568F  random_bytes (len=28): BF81EBFB16471C15ED8D7D0D5273232CFBD6E70E933CC00747B57899  session_id (len=0):   cipher_suite {0x00, 0xA7} TLS_DH_anon_WITH_AES_256_GCM_SHA384  compression_method: No Compression (0x00)  extensions, length = 13  extension_type=renegotiate(65281), length=1  lt;EMPTYgt;  extension_type=session_ticket(35), length=0  extension_type=extended_master_secret(23), length=0  Sent Record Header:  Version = TLS 1.2 (0x303)  Content Type = Handshake (22)  Length = 523  ServerKeyExchange, Length=519  KeyExchangeAlgorithm=DHE  dh_p (len=256): C0C8B68E3EAADEB2ECCA8863B8017D63D3259FEC711A97D84E8100DC427BA45684DF962C00C8116DCE797BD02CA3D02FB2C01F7F212AA1E899CB108A57156841A1CE40F4E2EF65AC1598964851F4DB874BD9E8031B2467B7624CE3CC950B0167C23A91896CAF44199B45A046A9EA1D274D6545AC1AC11542ED9F1C0CA3F8DDF5CB215436C3416FFE20242AA5C3270858D07314C58478F771D201B54D47DFAFD87F127FC3E8C11F40CE5B1A063AF7C6C50347C3049A9EE479EA685499E57A49DE1287DC96AE71E0E7F10B42BB09DC8BAFBE96F710FE20F0FC296C1D951CD258946E1AEF5876494B524809B14F12F393B40AEF0BD4E44F6E67E8A579184CAB393B  dh_g (len=1): 02  dh_Ys (len=256): AE3E9B2D557F7A862D323911B17061471865880B8CDA469D94CCEC11A74B6C081A2F0389BF2B961E5A54C7A6DE41D1AFB9388B5BB51EC6F129BA093A83DA68288D5246869B52B54D2CF5CD0F1BDEAA206FC7C680B02B18903969B061817479545BF8EA17901CF86A9E580DF860FD29E25A2EB56D00FE319D2DA17F9E3F33986D4716D86882E76E774A7CB717AD08E60AA182843B139E6EFB63F2EFCD6E351503352F3E5A23D397AAA4BB359A8EF125FF10FE20805B083B15135247E1B08F57B3B43EF13E9B60EEB2EB1743466DD10922ABD588E9031BC1BDF10353484BC10B2E32D24E513E58092373E96360836BE4FFDC3395CB4044BCEE11248E0E5EDA412F  Sent Record Header:  Version = TLS 1.2 (0x303)  Content Type = Handshake (22)  Length = 4  ServerHelloDone, Length=0  Received Record Header:  Version = TLS 1.2 (0x303)  Content Type = Handshake (22)  Length = 262  ClientKeyExchange, Length=258  KeyExchangeAlgorithm=DHE  dh_Yc (len=256): 060D2565ABCE52B7480CB72D2DEF6F5B8FC25B15FB070BB97DC0B509143CFC562BF8483D24959B8192B292DE1D17FBEB281734DF062F48313AEBE3F1398EC9C535086D3DBDB7F2F52FB1F656B078908520B2B2285F2382C16E0731AAF00CAF098EBB32AE89CEB50940BA1EBE8A08EF86739CFC6DABD9965E9D2325DA73F53045C686C74006A525A35E27180D51BED9EEB9831EF617C7D78AF19CCBB6EE9F016911E1C2F0D9CEF6F3E31E14109EFDBF1187720AA34324C94CB166DAAA4D2E69D1182D5B86C8F1EA89FB02C5E9420DFC333ABBA4050F8C782F1B16B74F87F0251B06B4D725FC6FE26B3FC5C2CB54FBA94174576F694A02D1FC707BABD2E03FB854  Received Record Header:  Version = TLS 1.2 (0x303)  Content Type = ChangeCipherSpec (20)  Length = 1 Received Record Header:  Version = TLS 1.2 (0x303)  Content Type = Handshake (22)  Length = 40  Finished, Length=12  verify_data (len=12): DCA9352457FDBF48674FE0B8  Sent Record Header:  Version = TLS 1.2 (0x303)  Content Type = Handshake (22)  Length = 202  NewSessionTicket, Length=198  ticket_lifetime_hint=7200  ticket (len=192): 06B807C486272F454FC553528EC5B6932A5989321D4171F7A6DAF4A2F0E9FA9A3620F9F90499FF5FD7C2566D4A5E7574DD6863353CC428E7656168799B3501613A67AF605746F034571AA9264A53A3DCCE4CACCB72FA54FF9B4C735666F4FA0AEC56A6F8819E375BEC01DC9FC282052E4FBFF88D07596247CE2AC92870B4CE759D946FD18E78B48EBF4474F9D6D51BB6924662B9CB3A312E9D7AD76B97C335A07531841F2D7A5A02BCBCE4857EE43626FF07CD4D44937CFF74401FFE2787740C  Sent Record Header:  Version = TLS 1.2 (0x303)  Content Type = ChangeCipherSpec (20)  Length = 1  change_cipher_spec (1)  Sent Record Header:  Version = TLS 1.2 (0x303)  Content Type = Handshake (22)  Length = 40  Finished, Length=12  verify_data (len=12): E72603E1A716815F94F9AAEE  Sent Record Header:  Version = TLS 1.2 (0x303)  Content Type = Alert (21)  Length = 26  Level=warning(1), description=close notify(0)  

От клиента не приходит сообщение, указывающее на сбой рукопожатия, и TCP-соединение не было закрыто.

Что я упускаю?

Ответ №1:

От клиента не приходит сообщение, указывающее на сбой рукопожатия, и TCP-соединение не было закрыто.

Рукопожатие, как таковое, не подводит. В OpenSSL не имеет возможности требовать минимального классическом DH размер в keyexchange (для dhe и DH_anon где OpenSSL звонки АдГ), так nodejs применяет это ограничение после OpenSSL и завершает рукопожатие , но, прежде чем разрешить любые сведения, чтобы передать … как это также делает для сервера сертификатов именем проверить, где OpenSSL изначально не реализовали и теперь реализуется по-другому от того, что выбрал nodejs. Загляни onSecureConnect внутрь _tls_wrap.js .

TCP-соединение закрыто, и, вероятно, именно поэтому ваш сервер отправляет close_notify -или пытается это сделать; эта отправка фактически завершится неудачей из-за закрытия TCP. Серверы, которые я тестировал (OpenSSL и Java), показывают, что TCP закрыт от клиента (nodejs), хотя OpenSSL делает это неявно (количество считываний 0), и они реагируют по-разному: только более старая Java 8 (до того, как новый стек 11 был перенесен в 8u261) пыталась отправить close_notify в «ответе». Я подозреваю, что ваш сервер просто не регистрирует закрытие TCP; попробуйте внешний инструмент, такой как wireshark или аналогичный.

Чтобы было понятно, вы задаете в клиенте 4096-разрядные параметры DH, а не ключ. На сервере задаются только параметры; ключи на обоих концах генерируются для каждого рукопожатия (в подгруппе, определенной параметрами), поэтому они называются эфемерными. И (выбранные пользователем) параметры DH, установленные в клиенте, игнорируются (но см. Далее).

К вашему сведению: Существует довольно недавний вариант протокола RFC7919 для TLS1.2* для использования стандартизированных (не выбранных пользователем) групп DHE/anon, которые теперь называются FFDHE для отличия от ECDHE, которые клиент может запросить с помощью прежнего расширения supported_curves, которое теперь используется как supported_groups (в частности, может потребоваться 4096), но OpenSSL и, следовательно, nodejs не реализует эту опцию. В 1.3 требуются поддерживаемые группы, но группы FFDHE не требуются и даже не особо поощряются, и AFAICT OpenSSL также (пока?) Не поддерживает их там-и в любом случае 1.3 вообще не разрешает «анон». (* Формально 7919 также относится к 1.1 и 1.0, но я не могу представить, чтобы какая-либо реализация включала 7919, но не 1.2, поэтому вам никогда не понадобятся более низкие протоколы.)

Комментарии:

1. Подробный ответ — очень признателен