Метод проверки не срабатывает после второго ClientHello с BIO памяти OpenSSL - PullRequest
0 голосов
/ 31 декабря 2018

Я пишу собственный модуль 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), но важно отметить, что если вы присоединяете отладчик и ставите точку останова напроверка лямбда не ударится.

1 Ответ

0 голосов
/ 07 января 2019

Вы можете попробовать использовать nodejs-dtls

Пример использования можно найти в IOTBroker.клиент cloudjs

Посмотрите протоколы CoAP и MQTT-SN

BR

Юлиан Ойфа

Mobius Software

...