Отправка необработанного IP-трафика с помощью Python: определение MTU

Как я могу реализовать обнаружение MTU вручную с помощью Python?

От: /questions/42684188/luchshij-javascript-kompressor/42684220#42684220

Отправьте пинг цели, в моем примере я буду использовать DNS-сервер Google (8.8.8.8). Установите бит DF в пинге, чтобы предотвратить фрагментацию пинга. Установите размер пакета на некоторое большое число или стандартный MTU 1500. Обратите внимание, что некоторые реализации ping устанавливают размер только полезной нагрузки, что означает, что вы должны учитывать 8-байтовый заголовок ICMP и 20-байтовый заголовок IP.

2 ответа

Решение

Я хотел бы добавить, что вы можете сделать это и с необработанными сокетами.
scapy - это хороший уровень абстракции, который делает для вас большую часть магии, но, если честно, если вы собираетесь опускаться до минимума, вы можете пройти весь путь для обучения. (Обратите внимание, что необработанные сокеты требуют повышенных разрешений в большинстве современных ОС, и по мере углубления реализации могут отличаться от Windows и Linux.)

import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))

Это даст вам необработанный сокет на основе пакетов, который буквально доставит вам все кадры. В Windows и Linux она немного различается, но в этом ответе я остановлюсь на Linux. Также обратите внимание, что все исходящие пакеты могут не приниматься этим сокетом, если вам нужна эта функциональность (анализатор), подумайте о поиске совпадений, связанных с беспорядочным режимом.

Все, что вам нужно сделать сейчас, это воспринимать каждый пакет как сегменты, к которым они приходят или уходят, например - распаковка кадра Ethernet и IP будет выглядеть примерно так:

frame, meta = s.recvfrom(65565)
print(frame, meta)

ethernet = frame[0:14]
ethernet_segments = struct.unpack("!6s6s2s", ethernet)

mac_source, mac_dest = (binascii.hexlify(mac) for mac in ethernet_segments[:2])

ip = frame[14:34]
ip_segments = struct.unpack("!12s4s4s", ip)

ip_source, ip_dest = (socket.inet_ntoa(section) for section in ip_segments[1:3])

print('MAC Source:', b':'.join(mac_source[i:i+2] for i in range(0, len(mac_source), 2)))
print('MAC Dest:', b':'.join(mac_dest[i:i+2] for i in range(0, len(mac_dest), 2)))
print('IP Source:', ip_source)
print('IP Dest:', ip_dest)

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

Отправка так же проста, используйте struct и посмотрите на множество примеров ICMP, в том числе с вычислениями контрольной суммы:

Что касается MTU, это логика, которую вы должны реализовать самостоятельно, потому что нет заранее созданной библиотеки, которая бы делала это, о чем я знаю.

Но это мой вклад в отправку необработанного IP-трафика с помощью Python.

Отправляя что-нибудь необработанное в python, вы смотрите на использование на scapy.

Для получения информации о том, как отправлять сообщения ping:

http://www.secdev.org/projects/scapy/doc/usage.html

Чтобы установить флаг DF:

IP(flags='DF')

Как отрегулировать конкретный размер, чтобы можно было имитировать фрагментацию:

Добавление полезной нагрузки в пакет (scapy)

Собираем все вместе:

data = "x" * 1473
ans,unans = sr(IP(dst="<target_ip>", flags='DF' )/ICMP() / Raw(load=data))

Если вы на самом деле не заинтересованы в создании этих необработанных вещей, то этот вопрос является двойным: как найти значение mtu сети через код (в python)?

Другие вопросы по тегам