Подтвердить что ты не робот

Соединение TCP с гнездом SOCK_RAW

Хорошо, я понимаю, что эта ситуация несколько необычна, но мне нужно установить TCP-соединение (трехстороннее рукопожатие) с использованием только сырых сокетов (в C, в Linux) - то есть мне нужно построить заголовки IP и TCP-заголовки. Я пишу сервер (поэтому я должен сначала ответить на входящий пакет SYN), и по какой-то причине я не могу понять, что это правильно. Да, я понимаю, что SOCK_STREAM справится с этим для меня, но по причинам, по которым я не хочу входить, это не вариант.

В учебниках, которые я нашел в Интернете по использованию raw-сокетов, описывается, как создать SYN-флудер, но это несколько проще, чем фактически устанавливать TCP-соединение, поскольку вам не нужно создавать ответ на основе исходного пакета, Я получил примеры сценариев SYN, и я могу прочитать входящий SYN-пакет как раз из сырого сокета, но мне все еще не удается создать корректный ответ SYN/ACK на входящий SYN от клиента.

Итак, кто-нибудь знает хороший учебник по использованию сырых сокетов, который выходит за рамки создания SYN-флудера, или у кого-нибудь есть код, который мог бы это сделать (используя SOCK_RAW, а не SOCK_STREAM)? Я был бы очень благодарен.


MarkR абсолютно прав - проблема в том, что ядро ​​отправляет пакеты reset в ответ на исходный пакет, потому что он считает, что порт закрыт. Ядро отбивает меня от ответа, и соединение умирает. Я использовал tcpdump для мониторинга соединения уже - я должен был быть более наблюдательным и заметил, что были ДВА ответов, один из которых был reset, который искажал вещи, а также ответ, который создал моя программа. D'OH!

Решение, которое, как представляется, работает лучше всего, - это использовать правило iptables, как это было предложено MarkR, для блокировки исходящих пакетов. Однако есть более простой способ сделать это, чем использовать параметр метки, как это было предложено. Я просто сопоставляю, установлен ли флаг reset TCP. Во время обычной связи это вряд ли понадобится, и это не имеет большого значения для моего приложения, если я блокирую все исходящие пакеты reset из используемого порта. Это эффективно блокирует нежелательный ответ ядра, но не мои собственные пакеты. Если порт, который прослушивает моя программа, равен 9999, тогда правило iptables выглядит так:

iptables -t filter -I OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP
4b9b3361

Ответ 1

Вы хотите реализовать часть стека TCP в пользовательском пространстве... это нормально, некоторые другие приложения делают это.

Одна проблема, с которой вы столкнетесь, заключается в том, что ядро ​​будет отправлять (в целом отрицательные, бесполезные) ответы на входящие пакеты. Это приведет к испорчению любого сообщения, которое вы пытаетесь инициировать.

Один из способов избежать этого - использовать IP-адрес и интерфейс, в которых ядро ​​не имеет собственного стека IP, что прекрасно, но вам нужно будет иметь дело с файлом link-layer (в частности, arp) самостоятельно. Для этого потребуется сокет ниже IPPROTO_IP, SOCK_RAW - вам нужен пакетный сокет (я думаю).

Также возможно заблокировать ответы ядра с помощью правила iptables, но я скорее подозреваю, что правила будут применяться и к вашим собственным пакетам так или иначе, если только вам не удастся заставить их обращаться по-разному (возможно, используя сетевой фильтр) отметьте "ваши собственные пакеты?)

Прочтите справочные страницы

разъем (7) ф (7) пакет (7)

Которые объясняют различные варианты и ioctls, которые применяются к типам сокетов.

Конечно, вам понадобится такой инструмент, как Wireshark, чтобы проверить, что происходит. Для тестирования вам понадобятся несколько машин, я рекомендую использовать vmware (или подобное), чтобы уменьшить количество требуемого оборудования.

Извините, я не могу рекомендовать конкретный учебник.

Удачи.

Ответ 2

Я понимаю, что это старый поток, но вот учебник, который выходит за рамки обычных SYN-флудеров: http://www.enderunix.org/docs/en/rawipspoof/

Надеюсь, что это может помочь кому-то.

Ответ 3

Я не могу помочь вам в любых учебниках.

Но я могу дать вам несколько советов по инструментам, которые вы могли бы использовать для помощи в отладке.

Прежде всего, поскольку bmdhacks предложил, сделайте себе копию wireshark (или tcpdump - но wirehark проще в использовании). Захватите хорошее рукопожатие. Убедитесь, что вы сохранили это.

Захватите одно из ваших рукопожатий, которое терпит неудачу. Wireshark имеет неплохую парсинг пакетов и проверку ошибок, поэтому, если есть прямая ошибка, это, вероятно, скажет вам.

Затем сделайте копию tcpreplay. Это также должно включать инструмент под названием "tcprewrite". tcprewrite позволит вам разделить ваши ранее сохраненные файлы захвата на два - по одному для каждой стороны рукопожатия. Затем вы можете использовать tcpreplay для воспроизведения одной стороны рукопожатия, чтобы у вас был последовательный набор пакетов для воспроизведения.

Затем вы используете wirehark (снова), чтобы проверить свои ответы.

Ответ 4

У меня нет учебника, но я недавно использовал Wireshark, чтобы отладить некоторые программы сокетов, которые я делал, Если вы захватите пакеты, которые вы отправляете, wirehark сделает хорошую работу, чтобы показать вам, если они неверные. Это полезно для сравнения с обычным подключением.

Ответ 5

Существуют структуры для заголовков IP и TCP, объявленных в netinet/ip.h и netinet/tcp.h соответственно. Возможно, вам захочется взглянуть на другие заголовки в этом каталоге для дополнительных макросов и всего, что может быть полезно.

Вы отправляете пакет с установленным флагом SYN и случайным порядковым номером (x). Вы должны получить SYN + ACK с другой стороны. Этот пакет будет иметь номер подтверждения (y), который указывает следующий порядковый номер, который ожидает другая сторона, а также другой порядковый номер (z). Вы отправляете обратно пакет ACK с порядковым номером x + 1 и номером z + 1 для завершения соединения.

Вам также необходимо убедиться, что вы вычисляете соответствующие контрольные суммы TCP/IP и заполняете оставшуюся часть заголовка для отправляемых вами пакетов. Кроме того, не забывайте о таких вещах, как хост и сетевой порядок байтов.

TCP определен в RFC 793, который доступен здесь: http://www.faqs.org/rfcs/rfc793.html

Ответ 6

В зависимости от того, что вы пытаетесь сделать, может быть проще получить существующее программное обеспечение для обработки подтверждения TCP для вас.

Один IP-стек с открытым исходным кодом - это lwIP (http://savannah.nongnu.org/projects/lwip/), который обеспечивает полный стек tcp/ip. Очень возможно запустить его в пользовательском режиме, используя SOCK_RAW или pcap.

Ответ 7

если вы используете сырые сокеты, если вы отправляете с использованием другого исходного MAC-адреса на фактический, linux будет игнорировать пакет ответа и не отправлять первый.