DevGang
Авторизоваться

Написание стека TCP в Python

Недавно я начал посещать занятия по сетевым технологиям, и хотя концепция сетевых технологий меня очень увлекла, мне было трудно понять протокол управления передачей данных (Transmission Control Protocol).

Несколько основных понятий, которые мы будем использовать:

  1. Открытие сетевого сокета, позволяющего отправлять TCP-пакеты
  2. Отправка HTTP-запроса на сайт google.com с использованием GET
  3. Получение и чтение полученного ответа

Также следует отметить, что корректная обработка ошибок при этом не была предусмотрена.

Установление связи TCP

Первое, что нам понадобится, - это установить связь с google. Вот как работает TCP handshake:

Предположим, что у нас есть двухслоговое слово index, которое разбивается на IN-DEX.

Пользователь, посылающий HTTP-запрос, получает возможность использовать: IN. Google, принимающему этот запрос, присваивается: INDEX. А мне, пользователю, присваивается: DEX

В простом коде это будет выглядеть следующим образом:

# My local network IP
src_ip = "192.168.0.11"
# Google's IP
dest_ip = "96.127.250.29"
# IP header: this is coming from me, and going to Google
ip_header = IP(dst=dest_ip, src=src_ip)
# Specify a large random port number for myself (59333),
# and port 80 for Google The "S" flag means this is
# a SYN packet
syn = TCP(dport=80, sport=59333, 
          ack=0, flags="S")
# Send the SYN packet to Google
# scapy uses '/' to combine packets with headers
response = srp(ip_header / syn)
# Add the sequence number 
ack = TCP(dport=80, sport=self.src_port, 
          ack=response.seq, flags="A") 
# Reply with the ACK
srp(ip_header / ack)

Что такое порядковые номера?

Идея TCP заключается в том, чтобы обеспечить возможность повторной отправки пакетов в случае, когда некоторые пакеты пропали. Порядковые номера — это способ проверить, не пропущены ли пакеты. В данном случае google отправляет 3 пакета размером 100, 200 и 300 байт. При этом предполагается, что начальный порядковый номер равен 0. Теперь эти пакеты будут иметь номера 0, 100, 300 и 600.

TCP Sequence Number - это 4-байтовое поле в заголовке TCP, которое показывает первый байт исходящего сегмента. Оно также позволяет отслеживать, сколько данных было передано и получено. Поле TCP Sequence Number всегда установлено.

Например, порядковый номер пакета - X. Длина этого пакета - Y. Если пакет эффективно передается на другую сторону, то порядковый номер следующего пакета будет X+Y.

Когда мы отправляем или пересылаем пакеты, как Google узнает о пропущенном пакете? Каждый раз, когда google получает пакет, мы также должны отправлять ACK о том, что получили пакет с порядковым номером. Если в этот момент сервер заметит, что пакет не был получен (ACK-пакет — это любой TCP-пакет, подтверждающий получение сообщения или серии пакетов), он отправит его повторно.

Что происходит при наличии стека TCP?

Если вы запустили приведенный выше код, то вы можете заметить, что произошла ошибка и мы получили другой пакет. В этом случае происходит следующее:

Python prgram: IN
Google: INDEX
Kernel: Didn't ask for this
Python Program: ..

Вопрос заключается в том, как обойти ядро? Одним из способов является ARP-спуфинг, который заключается в том, чтобы сделать вид, будто у нас другой IP-адрес 192.168.0.129.

Теперь обмен выглядит следующим образом:

me: sends packets for 192.168.0.129 to the address
router: goes through with it
my Python program: IN (from 192.168.0.129)
google: INDEX
kernel: this isn't my IP address! <ignore>
my Python program: uses ACK 

Если вы заметили, это работает, и теперь мы можем посылать пакеты для получения ответов без вмешательства ядра.

Как создать веб-страницу?

Чтобы предотвратить отправку html Google, нам необходимо учесть следующее:

  1. Обеспечение формирования пакета с запросом HTTP GET
  2. Обеспечение возможности прослушивания большого количества пакетов при наличии одного пакета
  3. Исправление ошибок с порядковыми номерами
  4. Правильное закрытие соединения

Регресс с Python

Если вы заметили, то после того, как все заработало, использование wireshark для просмотра отправляемых пакетов выглядит следующим образом:

User/google: <tcp handshake>
User: GET google.com
google: 100 packets
User: 3 ACKs
google: <starts resending packets>
User: a few more ACKs
google: <reset connection>

В приведенном выше сценарии google будет отправлять пакеты быстрее, чем это может сделать программа python, посылая ACK. Сервер Google предположит, что были возможные проблемы с сетью, из-за которых пользователь не получил ACK-пакеты.

Это приведет к сбросу соединения, поскольку Google решит, что были проблемы с подключением. Но мы знаем, что с соединением все в порядке и программа адекватно реагировала. Проблема заключалась в том, что программа python медленно принимала пакеты.

Заключение

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

Источник:

#Python
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу