2012-06-12 19 views
13

私はscapyをtwistedと統合する作業をしていますが、私はOSX上でこの非常に奇妙なバグを見つけました。PythonのRawソケットとsendto

基本的に、rawソケットを介して有効な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)) 

私はこれを実行すると、私は次のエラーを取得:あなたはそれをこれを使用しないでscapyを持っていない場合は

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

を符号化されたパケットのbase64である:

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

非常に奇妙なことがほとんど同一であるパケットが正しく送信されるように見えることである。

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

これは、2つのパケットがどのように見えるかです:彼らは唯一のTCPの一部が異なるのwiresharkでそれらをチェックアウトすることで

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........ 

私は多くの異なる実験を行いましたが、最終的に特定の特定の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 

あなたがゼロを追加しない場合、それは動作しません。

+0

最初のコードスニペットで 'import'を修正できますか? (また、あなたがあなたの質問の要求を読んでいる間、funの事実:あなたは '' ... '' .decode( "base64")と '' ... "(' 'import base64'の代わりに.encode(" base64 ")' 'を使うことができます) 。 OK、申し訳ありませんが、この1つを助けることはできません。しかし、あなたは私のアップヴォートを持っています。 –

+0

はい、インポートを修正しました。 –

+0

FWIW、あなたのコードで同じエラーが発生しています。 –

答えて

3

私はRawソケットが使用可能であると盗聴されていると判断しました。特に、このソフトウェアはクロスプラットフォームである必要があるため、OSXの特徴は他のOSには適用されない可能性があります。

当面は、私はscapyによって提供される「ソケット」を単に巻きました。将来、私はlibdnetだけに依存するものを書いていきます(それは生のフレームを書くためにscapyが何をするのかと同じです)。

あなたは、これはここで実装見つけることができます:

https://github.com/hellais/txscapy

0

0.0.0.0は、有効なIP送信元アドレスのようには見えません。これを他の値に変更すると何か違いはありますか?

+0

それは違いがないように見えます。 –

+0

いいえ、違いはありません。このパケットはうまくいっているようです: pkt = IP(len = 16384、src = '0.0.0.0'、dst = '127.0.0.1'、 id = RandShort()、ttl = 2)/ TCP(スポーツ= 255、 DPORT = 900、フラグ= "S"、ウィンドウ= 200、 オプション= [( 'MSS'、1460)、( 'WScale'、2)]) SPKT =バイト(PKT) spkt + = '\ x00' * 20 20個のゼロを追加しないと、他のものと同じように失敗します。 (適切に書式設定されたポストにパケットを追加) –

+0

奇妙です。ダニー。私の次の考えは、OS Xのカーネルはこのようなあいまいなバグでいっぱいです。 ;) –

0
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 

私はすべてのエラーパケットの特定のセットを書き込みしていないようです - 私は2.6.38- * GNU/Linuxカーネルとx86_64版を使用しています。

おそらく、あなたの問題は、Mac OS Xの脳のダメージとRAWソケットに関するものでしょうか?

0

別の関連の問題。 Python impacketモジュールには、ホストにpingするためのping.pyスクリプトがあります。このスクリプトを使用している間はMac OS Xのライオンに私はエラーを得た:

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の上ですべてが正常に動作し、私はホストからの応答を取得しています。

0

私は確かな証拠はありませんが、これはイーサネットの最小ペイロードサイズに関連していると思います。 wikipediaから

The minimum payload is 42 octets when 802.1Q tag is present and 46 octets when absent.

あなたの最初の例パケットはわずか40バイトだったので、いずれの場合にも限界を下回ることと思います。パディングを20バイトからそれらの値に変更して、限界値の1つで動作が停止していることを確認することができます。

もしそうなら、その動作は理にかなっています。有効なパケットを構築するのに十分なデータを与えていないため、OSはパケットを拒否しています。

1

IPヘッダーは、32ビットの倍数が有効であることが必要です。また、最後にはパディングエリアがあります。

可変のビット量を占めるヘッダーに設定されたIPオプションに応じて、ビットパディングを数える必要があります。

異なるOSのように見えますが、これは異なっています。巧妙なOSがあなたのためにこのパディングを行うと考えるかもしれません。

関連する問題