Я пишу собственный модуль DTLS для NodeJS, используя OpenSSL.Он использует память BIO, поэтому собственные сокеты узла могут использоваться для управления потоком данных.Кажется, все работает, но я сталкиваюсь с некоторыми проблемами, связанными со смягчением DOS.
Согласно спецификации, исходное ClientHello, отправленное на сервер, должно быть отклонено, и сервер отправит HelloVerifyRequest, содержащий cookie, который будетвозмущаться от клиента.Это все работает нормально, но когда клиент отправляет обратно второй ClientHello, по какой-то причине вызов DTLSv1_listen () вызывает мой метод генерации файлов cookie во второй раз вместо метода проверки файлов cookie.Как ни странно, если я отправлю обратно второй HelloVerifyRequest (точно такой же длины и содержания, что и первый), я получу ClientHello, который, кажется, вызывает метод проверки.
Вот небольшой тест, который я написал для иллюстрациичто я делаю (не совсем, пропустил некоторые вещи, такие как импорт сертификата / ключа, проверка кода результата для чтения / записи после вызова рукопожатия, освобождение памяти и т. д.).
TEST(New, Test) {
// Init context
auto ctx = SSL_CTX_new(DTLS_method());
SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, [](int ok, X509_STORE_CTX * context) { return 1; });
SSL_CTX_set_cookie_generate_cb(ctx, [](SSL * ssl, unsigned char * cookie, unsigned int * cookie_len) {
return 1;
});
SSL_CTX_set_cookie_verify_cb(ctx, [](SSL * ssl, const unsigned char * cookie, unsigned int cookie_len) {
return 1;
});
// Init connections
auto client = SSL_new(ctx);
auto client_rbio = BIO_new(BIO_s_mem());
auto client_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(client, client_rbio, client_wbio);
SSL_set_connect_state(client);
auto server = SSL_new(ctx);
auto server_rbio = BIO_new(BIO_s_mem());
auto server_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(server, server_rbio, server_wbio);
SSL_set_accept_state(server);
std::vector<unsigned char> data;
// Client Hello, no cookie
SSL_do_handshake(client);
auto data_len = BIO_ctrl_pending(client_wbio);
data.resize(data_len);
BIO_read(client_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 1);
// Hello Verify Request
BIO_write(server_rbio, data.data(), data.size());
DTLSv1_listen(server, NULL);
data_len = BIO_ctrl_pending(server_wbio);
data.resize(data_len);
BIO_read(server_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 3);
// Client Hello, with cookie
BIO_write(client_rbio, data.data(), data.size());
SSL_do_handshake(client);
data_len = BIO_ctrl_pending(client_wbio);
data.resize(data_len);
BIO_read(client_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 1);
// Should be pass...?
BIO_write(server_rbio, data.data(), data.size());
ASSERT_EQ(DTLSv1_listen(server, NULL), 1);
}
Последнее утверждениетерпит неудачу - это -1 в этом примере, 0 в моем фактическом коде (и последующий BIO_read возвращает мне данные [13] = 3, иначе HelloVerifyRequest), но важно отметить, что если вы присоединяете отладчик и ставите точку останова напроверка лямбда не ударится.