前提・実現したいこと
Scapyを使用して、HTTP通信を行うためのスクリプトを作成しています。
試験通信ではWEBサーバ側からFINを送る必要があるため、HTTPリクエストを送信した後、
HTTPレスポンス×2パケット(MSSを超えるため)とFINの3パケットを受信します。
クローズシーケンスを完了させるため、FINのシーケンス番号を確認して、
+1をack番号としたACKを送信したいと考えています。
発生している問題・エラーメッセージ
複数パケットを受信する場合はsr()を使用する必要があると理解していますが、
最初の1パケットしか受信できていません。
パケットキャプチャより、3WayハンドシェイクおよびHTTPリクエスト&レスポンス、
WEBサーバからのFINが正常に送られていることは確認済みです。
その上で、sr()を実行したところ27packetsを受信したメッセージが表示されました。
このパケット数は毎回変わるため、このソケット外の通信も含まれている(?)と
想定しています。これについても、もし理由が分かれば教えていただきたいです。
>>> ans=sr(http,multi=1,timeout=1) Begin emission: Finished sending 1 packets. .*......................... Received 27 packets, got 1 answers, remaining 0 packets
パケット受信後、sr()ではtuple型になるため、例えばans.seqのような
取得方法はできないと考えています。
print(ans)とすると以下のようになりました。
>>> print(ans) (<Results: TCP:1 UDP:0 ICMP:0 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)
ans[0][0]で1つ目の受信パケットが表示できました。
>>> print(ans[0][0]) (<IP frag=0 proto=tcp dst=10.x.x.x |<TCP sport=50000 dport=http seq=101 ack=4290404129 flags=A |<Raw load='GET /2k.txt HTTP/1.1\r\nHost: xxx.yyy.zzz\r\nConnection: Close\r\n\r\n' |>>>, <IP version=4 ihl=5 tos=0x0 len=576 id=24220 flags=DF frag=0 ttl=254 proto=tcp chksum=0xc594 src=10.x.x.x dst=10.y.y.y |<TCP sport=http dport=50000 seq=4290404129 ack=163 dataofs=5 reserved=0 flags=A window=5422 chksum=0xad6f urgptr=0 |<Raw load='HTTP/1.1 200 OK\r\nDate: Fri, 15 Nov 2019 05:32:30 GMT\r\nServer: Apache/2.2.15 (CentOS)\r\nLast-Modified: Wed, 05 Jun 2019 05:50:37 GMT\r\nETag: "8430b-7d1-58a8d2d3c0ac9"\r\nAccept-Ranges: bytes\r\nContent-Length: 2001\r\nSet-Cookie: JSESSIONID=111\r\nConnection: close\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' |>>>)
ans[0][1]とすることで後続の受信パケットが表示できるかと思ったのですが、
"list index out of range"エラーが表示されるため、これ以外のパケットは
受信できていないようです。
>>> print(ans[0][1]) Traceback (most recent call last): File "<console>", line 1, in <module> File "/usr/local/lib/python3.6/site-packages/scapy/plist.py", line 118, in __getitem__ return self.res.__getitem__(item) IndexError: list index out of range
実際にはHTTPレスポンスが2パケット、その後にFINが送られています。
Scapyでは最初のパケットのみ受信しているように見えます。
http://python.zombie-hunting-club.com/entry/2018/04/18/112124#sr
上記URLを拝見したところ、sr()ではHTTPレスポンスのみしか受信しないようにも読めますが、
それにしてもHTTPレスポンスの1パケット目しか受信できていない理由が分かりません。
該当のソースコード
from scapy.all import * args=sys.argv dstip=args[1] dstport=int(args[2]) sourceport=50000 seqnum=100 ###3way handshake### ip=IP(dst=dstip) tcp=TCP(sport=sourceport,dport=dstport,seq=seqnum) tcp.flags = 'S' SYN=ip/tcp SYNACK=sr1(SYN) tcp.seq += 1 tcp.ack = SYNACK.seq + 1 tcp.flags = 'A' ack=ip/tcp send(ack) ### http request ### get='GET /2k.txt HTTP/1.1\r\nHost: xxx.yyy.zzz\r\nConnection: Close\r\n\r\n' http=ip/tcp/get ans=sr(http,multi=1,timeout=1) print(ans[0][0]) print(ans[0][1])
###質問
・HTTPレスポンスとFINを同時に受信する方法を教えてください。
・FINが受信できた後、ACKを送信するためにFINのシーケンス番号を取得したいと考えています。
tuple型の変数からシーケンス番号を取得する方法を教えてください。
どちらかの回答だけでもいただけると大変助かります。
よろしくお願いします。
環境
CentOS Linux release 7.2.1511 (Core)
Python 3.6.8
Scapy2.4.3
あなたの回答
tips
プレビュー