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

Необработанные сокеты и sendto в python

Я работаю над интеграцией scapy с скрученной, но я столкнулся с этой очень странной ошибкой OSX, которую я не могу понять.

В принципе, я не могу отправить действительный пакет TCP (включая заголовки IP) через сырой сокет. Это то, что я делаю:

import socket
from scapy.all import IP, TCP
pkt = IP(src='0.0.0.0', dst='127.0.0.1')/TCP()
spkt1 = str(pkt)
outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
outs.sendto(spkt1, ('127.0.0.1', 0))

Когда я запускаю это, я получаю следующую ошибку:

outs.sendto(spkt1, ('127.0.0.1', 0)) socket.error: [Errno 22] Invalid argument

Если вы не используете scapy, вы не хотите его использовать, это кодировка base64:

import base64
spkt1 = base64.b64decode("RQAAKAABAABABvvOAAAAAH8AAAEAFABQAAAAAAAAAABQAiAAEH4AAA==")

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

spkt2 = base64.b64decode("RQBAAAWwAAACBgAAAAAAAH8AAAEAyAOEAAAAAAAAAACwAgDIAHsAAAIEBbQBAwMBAQEICk3PUjMAAAAABAIAAA==")

Вот как выглядят два пакета:

SPKT1
0000   45 00 00 28 00 01 00 00  40 06 FB CE 00 00 00 00   E..([email protected]
0010   7F 00 00 01 00 14 00 50  00 00 00 00 00 00 00 00   .......P........
0020   50 02 20 00 10 7E 00 00                            P. ..~..
SPKT2
0000   45 00 40 00 05 B0 00 00  02 06 00 00 00 00 00 00   [email protected]
0010   7F 00 00 01 00 C8 03 84  00 00 00 00 00 00 00 00   ................
0020   B0 02 00 C8 00 7B 00 00  02 04 05 B4 01 03 03 01   .....{..........
0030   01 01 08 0A 4D CF 52 33  00 00 00 00 04 02 00 00   ....M.R3........

Проверяя их в wirehark, они отличаются только в части TCP.

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

Есть ли у кого-нибудь идеи, почему это может происходить?

EDIT:

Этот пакет действительно работает:

pkt = IP(len=16384, src='0.0.0.0', dst='127.0.0.1',
     id=RandShort(), ttl=2)/TCP(sport=255,
      dport=900, flags="S", window=200,
      options=[('MSS', 1460), ('WScale', 2)])
spkt = bytes(pkt)
spkt += '\x00'*20

Если вы не добавляете нули, он не работает.

4b9b3361

Ответ 1

В итоге я решил, что Raw Sockets просто прослушиваются, чтобы их можно было использовать. Тем более, что это программное обеспечение должно быть кросс-платформой, причуды для OSX могут быть неприменимы к другим ОС.

Пока я просто обертываю "сокеты", которые предоставляются scapy. В будущем я напишу что-то, что зависит только от libdnet (как это делает scapy для записи необработанных кадров).

Вы можете найти это здесь:

https://github.com/hellais/txscapy

Ответ 2

Требуется, чтобы IP-заголовок имел кратное 32 бита. На конце есть также область заполнения.

Таким образом, в зависимости от параметров IP, заданных в заголовке, который занимает переменное количество бит, нужно подсчитывать бит и отступы.

Похоже, что разные ОС обрабатывают это по-другому. Можно подумать, что умная ОС сделает это дополнение для вас.

Ответ 3

0.0.0.0 не похож на действительный IP-адрес источника. Меняет ли это значение на любое другое значение?

Ответ 4

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> from scapy.all import IP, TCP
WARNING: No route found for IPv6 destination :: (no default route?)
>>> pkt = IP(src='0.0.0.0', dst='127.0.0.1')/TCP()
>>> spkt1 = str(pkt)
>>> 
>>> outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
>>> outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
>>> outs.sendto(spkt1, ('127.0.0.1', 0))
40

Кажется, у меня нет ошибок при написании определенного набора пакетов - я использую x86_64 с ядром 2.6.38- * Gnu/Linux.

Возможно, ваша проблема связана с повреждением мозга Mac OS X с помощью сырых сокетов?

Ответ 5

Другая связанная с этим проблема. Python impacket имеет ping.py script для хостов ping. В Mac OS X Lion я получил ошибку при использовании этого script:

Traceback (most recent call last):
  File "/private/var/www/env/bin/ping.py", line 73, in <module>
    s.sendto(ip.get_packet(), (dst, 0))
socket.error: [Errno 22] Invalid argument

Но на Ubuntu все работает нормально, и я получаю ответы от хостов.

Ответ 6

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

Из wikipedia:

Минимальная полезная нагрузка составляет 42 октета при наличии тега 802.1Q и 46 октетов при отсутствии.

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

Если это так, поведение имеет смысл; ОС отклоняет пакет, потому что вы не даете ему достаточно данных для создания действительного пакета.