scapy で http response の tcp segment length が知りたい。そう思うことがありませんか?皆さん。tcp segment length さえ分かればコネクションの切断などの処理など書きまくれるのにと。。
調べてみるとどうも sr や sr1 の返り値からは tcp segment length は得られないようで sniff の返り値から以下のように得る必要があるようです。
len(rcv[TCP].payload)
または
len(rcv[TCP])
以下 http response の tcp segment length を見てコネクションの切断をするサンプルとなります。
意外となにかデータを受け取ってからコネクションの切断まで処理している scapy のサンプルがネットに落ちてない気がしますので参考になれば幸いです。
scapy_http_get.py
# !/usr/bin/env python3
from scapy.all import *
conf.L3socket=L3RawSocket
def main():
src_ip='192.168.1.20'
src_port=20000
dst_ip='192.168.1.100'
dst_port=80
iface='ens3'
http_req = 'GET / HTTP/1.1\r\nHost: ' + dst_ip + '\r\n\r\n'
http_get(src_ip, src_port, dst_ip, dst_port, iface, http_req)
def http_get(src_ip, src_port, dst_ip, dst_port, iface, http_req):
pkt_ip = IP(src=src_ip, dst=dst_ip)
pkt_tcp = TCP(sport=src_port, dport=dst_port)
# 3WHS SYN
pkt_tcp.flags = 'S'
syn = pkt_ip/pkt_tcp;
synack = sr1(syn)
# 3WHS ACK
pkt_tcp.flags = 'A'
pkt_tcp.seq = synack.ack
pkt_tcp.ack = synack.seq + 1
ack = pkt_ip/pkt_tcp
send(ack)
# HTTP GET (This code is expected to get only one packet from the HTTP server.)
send(pkt_ip/pkt_tcp/http_req)
pkts = sniff(count=1,filter='host ' + dst_ip + ' and port ' + str(dst_port), iface=iface)
# The HTTP 200 OK may be retransmitted from the server becauase it takes about 3 seconds here...
# ACK for HTTP 200 OK
rcv = pkts[0]
tcp_len = len(rcv[TCP].payload)
pkt_tcp.seq = rcv.ack
pkt_tcp.ack = rcv.seq + tcp_len
http_req_ack = pkt_ip/pkt_tcp
send(http_req_ack)
# FIN
pkt_tcp.flags = 'FA'
fin = pkt_ip/pkt_tcp
fin_ack = sr1(fin)
# LAST ACK
pkt_tcp.flags = 'A'
pkt_tcp.seq = fin_ack.ack
pkt_tcp.ack = fin_ack.seq + 1
last_ack = pkt_ip/pkt_tcp
send(last_ack)
if __name__ == '__main__':
main()
参考: Stack Overflow: How to get the length of http response python scapy