Использование параллельной обработки в C# для проверки способности сайта противостоять DDOS

У меня есть веб-сайт, и я также изучаю параллельную обработку на C#, и я подумал, что было бы неплохо посмотреть, смогу ли я написать свой собственный тестовый сценарий DDOS, чтобы посмотреть, как сайт справится с DDOS-атакой. Однако, когда я запускаю его, кажется, что используется только 13 потоков, и они всегда возвращают 200 кодов состояния, никогда ничего, что указывало бы на то, что ответ не был быстрым и точным, и при переходе на сайт и обновлении одновременно со сценарием работает, сайт загружается быстро.

Я знаю, что есть инструменты для тестов на проникновение и так далее, но мне просто интересно, почему я не могу использовать цикл Parallel для выполнения достаточного количества одновременных HTTP-запросов к сайту, чтобы он не мог быстро загрузиться и вернуть ответ. Кажется, я получаю больше проблем от Twitter Rush, просто публикуя в Твиттере ссылку на новую страницу на сайте и сотни ботов, которые одновременно спешат на сайт, чтобы копировать, сканировать, проверять его и т. д., чем что-либо, что я могу бросить в него с помощью параллельного цикла.

Есть ли что-то, что я делаю неправильно, что ограничивает количество одновременных потоков, или это то, что я не могу контролировать? Я мог бы просто бросить множество длинных поисковых запросов, которые, как я знаю, будут сканировать всю БД, возвращая 0 результатов в каждом запросе, поскольку я видел это в действии и в зависимости от размера сканируемых данных и сложности поискового запроса, который он может вызывают всплески ЦП и медленную загрузку.

Итак, без лекции по использованию других инструментов есть ли способ бросить более 100 параллельных запросов на загрузку страницы, а не максимум 13 потоков, с которыми он отлично справляется.

Вот код, URL-адрес и количество HTTP-запросов, которые нужно сделать, передаются в качестве параметров командной строки.

static void Attack(string url, int limit)
{
    Console.WriteLine("IN Attack = {0}, requests = {1}", url, limit);
    try
    {
        Parallel.For(0, limit, i =>
        {

            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
            webRequest.ServicePoint.ConnectionLimit = limit;
            HttpWebResponse webResponse = webRequest.GetResponse() as HttpWebResponse;

            int statuscode = Convert.ToInt32(webResponse.StatusCode);

            Console.WriteLine("iteration {0} on thread {1} Status {2}", i,
                                Thread.CurrentThread.ManagedThreadId, statuscode);
        });
    }
    catch (AggregateException exc)
    {
        exc.InnerExceptions.ToList().ForEach(e =>
        {
            Console.WriteLine(e.Message);
        });
    }
    catch (Exception ex)
    {
        Console.WriteLine("In Exception: " + ex.Message.ToString());
    }
    finally
    {
        Console.WriteLine("All finished");
    }
}

person MonkeyMagix    schedule 23.04.2020    source источник
comment
какой фреймворк или версию ядра вы используете? У меня была проблема с .NET Core 2.1, из-за которой мы не могли контролировать ConnectionLimit, и он всегда был равен 2.   -  person Sergii Bidnyi    schedule 24.04.2020
comment
DDOS-атака буквально означает распределенную атаку. Вы используете одну машину. Атака не распространяется. Обнаружение уязвимости, которая может быть использована одной машиной, отправляющей запросы, является гораздо более серьезной уязвимостью, указывающей на какую-то серьезную проблему на сервере, которую можно так легко вывести из строя.   -  person Servy    schedule 24.04.2020
comment
docs.microsoft.com/en-us/dotnet/csharp/programming-guide/ может быть отправной точкой для рассмотрения, а не ненужным раскручиванием темы с Parallel. Кроме того, установите docs.microsoft. .com/en-us/dotnet/api/ только один раз, а не несколько раз.   -  person mjwills    schedule 24.04.2020
comment
Крайне маловероятно, что одна машина, ограниченная производительностью своего сетевого адаптера, сможет генерировать достаточно трафика, чтобы беспокоить специально созданный веб-хост — независимо от того, как вы запрограммируете генератор трафика.   -  person Tom W    schedule 24.04.2020
comment
Я знаю, что DDOS-атака означает распределенную DOS, но в основном я получаю это каждый день от Twitter Rush. SIte публикует один твит со ссылкой в ​​нем, и сотни ботов одновременно посещают эту связанную страницу. Иногда вызывает проблемы, иногда нет, но я просто хотел попробовать имитировать запрос как можно большего количества страниц, чтобы увидеть, не вызову ли я проблему. Очевидно, что если бы все это запускалось на нескольких машинах одновременно, это вызвало бы проблемы x (n x машин), но у меня их нет, так как я не делаю настоящий DDOS, просто пытаюсь смоделировать, если это возможно.   -  person MonkeyMagix    schedule 29.04.2020


Ответы (2)


вы можете попробовать это так:

        var socketsHandler = new SocketsHttpHandler
        {
            PooledConnectionLifetime = TimeSpan.FromSeconds(1),
            PooledConnectionIdleTimeout = TimeSpan.FromSeconds(1),
            MaxConnectionsPerServer = 10
        };

        var client = new HttpClient(socketsHandler);

        for (var i = 0; i < limit; i++)
        {
            _ = await client.GetAsync(url);
        }
person Sergii Bidnyi    schedule 23.04.2020
comment
await сериализует запросы. Вы можете просто удалить его, чтобы все операции выполнялись одновременно, или, что еще лучше, сохранить задачи в массиве или списке и await с Task.WhenAll в конце. - person Theodor Zoulias; 24.04.2020
comment
Не могли бы вы добавить сборки, необходимые для этого, так как при поиске SocketsHttpHandler я получаю информацию для добавления System.Net.Http, которые ничего не делают. Так что, если вы можете поставить сборки, которые мне нужны для этого, то это было бы здорово. - person MonkeyMagix; 25.04.2020
comment
@MonkeyMagix вы используете .NET Core или .NET Framework? - person Sergii Bidnyi; 27.04.2020
comment
Я использую .NET 4.6.1. Думаю, мне нужно добавить некоторые сборки, чтобы последний фрагмент кода работал как new System.Net.SocketsHttpHandler(); все в красном, спрашивая, забыл ли я добавить сборку, и я использую System.Net и System.Net.Http в моем разделе использования вверху и не могу найти другую соответствующую сборку в списке, когда собираюсь добавить ссылку. - person MonkeyMagix; 30.04.2020

Метод Parallel.For использует потоки из ThreadPool. Начальное количество потоков в пуле обычно невелико (сравнимо с количеством логических процессоров в машине). Когда пул недоступен, новые потоки внедряются со скоростью один каждые 500 мс. Самый простой способ решить вашу проблему — просто увеличить количество потоков, создающих сразу по требованию, с помощью SetMinThreads:

ThreadPool.SetMinThreads(1000, 10);

Однако это не масштабируется, потому что каждый поток выделяет 1 МБ памяти для своего стека, поэтому у вас не может быть их миллионов. Масштабируемое решение — перейти на асинхронный режим, при котором потоки используются минимально.

person Theodor Zoulias    schedule 24.04.2020
comment
Этот ответ можно улучшить, добавив дополнительную информацию (например, пример кода) для последнего абзаца. - person mjwills; 24.04.2020
comment
Да, последний фрагмент кода › _ = await client.GetAsync(url); просто дал мне ошибки без исправлений. Я не могу найти сборку, которой у меня нет, и я хотел бы сравнить их, если это возможно, например, время на выполнение X HTTP-запросов, отсутствие 200 кодов состояния, количество потоков, время простоя на сайте и т. д., более низкая скорость отклика и т. д. , Так что пример с использованием async был бы хорош. Если бы я мог заставить его работать, - person MonkeyMagix; 02.05.2020
comment
@MonkeyMagix эта статья может оказаться полезной: Как сделать несколько веб-запросов параллельно с помощью async и await - person Theodor Zoulias; 02.05.2020