以下の方が対象な感じです。まぁ私なんですけど…
- Pythonで多少コードが組める
- Scapyのインストールとかは終わっている(あまりここで細かい説明はしません)
- たまにしか使わないので、よく使い方を忘れる。
自分用のメモ的意味合いも兼ねてます。また確認は全てLinuxでやっています。
インストールなど
公式から。
パケット解析
公式では以下の「Reading PCAP files」辺りから説明があります。
https://scapy.readthedocs.io/en/latest/usage.html
すみません、にわかなんで私の場合WireSharkとの併用というのをよくやります。なので、そことの関係も考慮したサンプルにしています。また結果がどーっと表示されるかもしれません。解析データをログにしたい場合は
python <pythonファイル名> > test.log
みたいにして下さい。
以下例示しますが、キャプチャファイルは適当に採集(※)し、設定値や検出条件(以下のコードでis_this_target_packet関数として書いた部分)は自分の環境に合ったものにして下さい。
※:そこらのWebページをcurlで取るとか。
全パケットのサマリ表示
#!/usr/bin/env python
# coding: shift-jis
from scapy.all import *
from datetime import datetime
# -----> 設定値ここから
PCAP_filename = "sample.pcap"
# <----- 設定値ここまで
def parse_pcap(filename):
packets = rdpcap(filename)
print("----------------------------------")
for cnt, packet in enumerate(packets, 1):
datetime_text = datetime.fromtimestamp(packet.time).isoformat()
print("No:", cnt, " ", datetime_text, " ", packet.summary())
print("----------------------------------")
if __name__ == "__main__":
parse_pcap(PCAP_filename)
print("completed.")
- PCAP_filenameに解析対象のキャプチャファイル名を入れます。
- 以下のように summary が出ます。NoはWireSharkのNoと連動させてます。
No: 1 2019-04-14T07:09:37.526395 Ether / IP / TCP 10.0.0.11:35152 > 35.186.254.217:https PA / Raw
No: 2 2019-04-14T07:09:37.526454 Ether / IP / TCP 10.0.0.11:48508 > 183.79.249.252:https PA / Raw
No: 3 2019-04-14T07:09:37.526477 Ether / IP / TCP 10.0.0.11:43764 > 13.113.199.4:https PA / Raw
No: 4 2019-04-14T07:09:37.526497 Ether / IP / TCP 10.0.0.11:42710 > 172.217.25.202:https PA / Raw
No: 5 2019-04-14T07:09:37.535457 Ether / IP / TCP 35.186.254.217:https > 10.0.0.11:35152 A
: 以下同じ感じで繰り返されます
特定のソケットだけ抽出(その1)
特定のデータ通信部分を抽出して、そのサマリと内容ダンプとを行います。内容についてはScapyのAPIをそのまま使っています。
#!/usr/bin/env python
# coding: shift-jis
from scapy.all import *
from datetime import datetime
# -----> 設定値ここから
PCAP_filename = "sample.pcap"
SHOW_Detail = True
# <----- 設定値ここまで
def is_this_target_packet(packet):
return TCP in packet and (packet[TCP].sport == 80 or packet[TCP].dport == 80)
def parse_pcap(filename, show_details):
packets = rdpcap(filename)
print("----------------------------------")
target_cnt = 0
for cnt, packet in enumerate(packets, 1):
if is_this_target_packet(packet) == True:
datetime_text = datetime.fromtimestamp(packet.time).isoformat()
print("No:", cnt, " ", datetime_text, " ", packet.summary())
target_cnt += 1
print("target_cnt = ", target_cnt)
print("----------------------------------")
if show_details == False:
return
target_cnt = 0
for cnt, packet in enumerate(packets, 1):
if is_this_target_packet(packet) == True:
datetime_text = datetime.fromtimestamp(packet.time).isoformat()
print("No:", cnt, " ", datetime_text,
" TARGET_CNT", target_cnt, packet.summary())
print(packet.show())
print("----------------------------------")
target_cnt += 1
if __name__ == "__main__":
parse_pcap(PCAP_filename, SHOW_Detail)
print("completed.")
- PCAP_filenameに解析対象のキャプチャファイル名を入れます。
- SHOW_Detailフラグは詳細データを表示するかしないかを決めます。
- is_this_target_packet関数にて対象パケットかどうかの判定を行っています。この関数の記述を変更する事で条件を変えられます。自分で取ったキャプチャのデータに合わせてください。
- 以下のように summary が出ます。NoはWireSharkのNoと連動させてます。Noを見ると分かりますが、該当パケットのみが抽出されている事が分かります。
----------------------------------
No: 39 2019-04-14T07:09:40.035476 Ether / IP / TCP 10.0.0.11:34892 > 216.58.197.195:http A
No: 43 2019-04-14T07:09:40.043278 Ether / IP / TCP 216.58.197.195:http > 10.0.0.11:34892 A
No: 49 2019-04-14T07:09:40.547620 Ether / IP / TCP 10.0.0.11:36018 > 117.18.237.29:http A
No: 50 2019-04-14T07:09:40.555924 Ether / IP / TCP 117.18.237.29:http > 10.0.0.11:36018 A
No: 52 2019-04-14T07:09:40.803730 Ether / IP / TCP 10.0.0.11:37494 > 23.219.39.8:http A
: 以下同じ感じで繰り返されます
- SHOW_DetailフラグがTrue(デフォ)だと一覧の下に、以下のように個別解析結果がずらーっと並びます。
----------------------------------
No: 39 2019-04-14T07:09:40.035476 TARGET_CNT 0 Ether / IP / TCP 10.0.0.11:34892 > 216.58.197.195:http A
###[ Ethernet ]###
dst = 00:3a:9d:dd:0a:54
src = 08:00:27:ef:c4:5d
type = 0x800
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 52
id = 58129
flags = DF
frag = 0
ttl = 64
proto = tcp
chksum = 0xafa9
src = 10.0.0.11
dst = 216.58.197.195
\options \
###[ TCP ]###
sport = 34892
dport = http
seq = 277691606
ack = 3896429984
dataofs = 8
reserved = 0
flags = A
window = 240
chksum = 0xa82f
urgptr = 0
options = [('NOP', None), ('NOP', None), ('Timestamp', (2762835695, 356793874))]
None
: 以下同じ感じで繰り返されます
- 解析を行う際は上記の項目に対して行う感じです。例えばTTLをチェックしたければ packet[IP].ttl を見ることになりますし、Windowsサイズを見たければ packet[TCP].window の値を見ることとなります。
- 項目が分からない場合、キャプチャデータをとりまshowさせて確認するという方法もあったります(ちゃんと調べないダメな私…汗)
特定のソケットだけ抽出(その2)
内容を出す所を変えます。showではなく各項目を個別に表示させる方法です。
#!/usr/bin/env python
# coding: shift-jis
from scapy.all import *
from datetime import datetime
# -----> 設定値ここから
PCAP_filename = "sample.pcap"
SHOW_Detail = True
# <----- 設定値ここまで
def is_this_target_packet(packet):
return TCP in packet and (packet[TCP].sport == 80 or packet[TCP].dport == 80)
def parse_pcap(filename, show_details):
packets = rdpcap(filename)
print("----------------------------------")
target_cnt = 0
for cnt, packet in enumerate(packets, 1):
if is_this_target_packet(packet) == True:
datetime_text = datetime.fromtimestamp(packet.time).isoformat()
print("No:", cnt, " ", datetime_text, " ", packet.summary())
target_cnt += 1
print("target_cnt = ", target_cnt)
print("----------------------------------")
if show_details == False:
return
target_cnt = 0
for cnt, packet in enumerate(packets, 1):
if is_this_target_packet(packet) == True:
datetime_text = datetime.fromtimestamp(packet.time).isoformat()
print("No:", cnt, " ", datetime_text,
" TARGET_CNT", target_cnt, packet.summary())
print("IP.len = ", packet[IP].len)
print("TCP.sport = ", packet[TCP].sport)
print("TCP.dport = ", packet[TCP].dport)
print("TCP.seq = ", hex(packet[TCP].seq))
print("TCP.ack = ", hex(packet[TCP].ack))
print("TCP.dataofs = ", packet[TCP].dataofs)
print("TCP.reserved = ", packet[TCP].reserved)
print("TCP.flags = ", packet[TCP].flags)
print("TCP.window = ", packet[TCP].window)
print("TCP.chksum = ", packet[TCP].chksum)
print("TCP.urgptr = ", packet[TCP].urgptr)
print("TCP.options = ", packet[TCP].options)
if Raw in packet:
print("[RAW] ", packet[Raw])
print("RAW:len = ", len(packet[Raw]))
print("----------------------------------")
target_cnt += 1
if __name__ == "__main__":
parse_pcap(PCAP_filename, SHOW_Detail)
print("completed.")
- 設定などは前のサンプルと同じです。
- summaryは前と同じなので省略します。
- 上記のコードだと各パケットは以下のように出ます(情報量が少なくなってます)
----------------------------------
No: 39 2019-04-14T07:09:40.035476 TARGET_CNT 0 Ether / IP / TCP 10.0.0.11:34892 > 216.58.197.195:http A
IP.len = 52
TCP.sport = 34892
TCP.dport = 80
TCP.seq = 0x108d3cd6
TCP.ack = 0xe83ecda0
TCP.dataofs = 8
TCP.reserved = 0
TCP.flags = A
TCP.window = 240
TCP.chksum = 43055
TCP.urgptr = 0
TCP.options = [('NOP', None), ('NOP', None), ('Timestamp', (2762835695, 356793874))]
----------------------------------
: 以下同じ感じで繰り返されます
- 前と異なり各項目を個別にprintしています。この例ではprintしていますが、例えば各項目のデータを抽出して集めたり、各値を比較するとか、項目ごとに分析が出来そうだなーというのが見て分かるかと思います。
パケット出力
今度は試験パケットを出す側の話で。公式では以下の「Generating sets of packets」辺りから説明があります。
https://scapy.readthedocs.io/en/latest/usage.html
キャプチャファイルとしてはローカルパソコン相手に通信したキャプチャファイルを使って下さい。私は試験HTTPSサーバ(ポート4001)をcurlして作りました。インターネット先が相手だと攻撃になってしまう可能性があります!
ここからはWireSharkの画面も使いながら見ていきます。図が小さいときはクリックすると元のサイズでの絵が出るです。
キャプチャファイルから特定ソケットのパケットを送出
例えば既にキャプチャしたものと同じものをどーっと送るだけなら割に簡単です。以下のようにする事で通信が可能です。
#!/usr/bin/env python
# coding: shift-jis
from scapy.all import *
from datetime import datetime
# -----> 設定値ここから
PCAP_filename = "test.pcap"
PCAP_ifname = "eth1"
# <----- 設定値ここまで
def is_this_target_packet(packet):
return TCP in packet and packet[TCP].dport == 4001
def pcap_resend(filename):
packets = rdpcap(filename)
target_cnt = 0
for cnt, packet in enumerate(packets, 1):
if is_this_target_packet(packet) == True:
# パケット加工
#packet[IP].dst = "255.255.255.255"
# 送信
sendp(packet, iface=PCAP_ifname) # layer2に送ります。
#send(packet, iface=PCAP_ifname) # layer3に送ります。
datetime_text = datetime.fromtimestamp(packet.time).isoformat()
print("No:", cnt, " ", datetime_text, " ", packet.summary())
target_cnt += 1
if target_cnt == 10: # とりあえず10個でやめてます。
break
print("target_cnt = ", target_cnt)
if __name__ == "__main__":
pcap_resend(PCAP_filename)
print("completed.")
- PCAP_filenameに解析対象のキャプチャファイル名を入れます。
- PCAP_ifnameにはパケットをどこに出すかをデバイス名で指定します。
- is_this_target_packet関数にて対象パケットかどうかの判定を行っています。この関数の記述を変えられます。自分で取ったキャプチャのデータに合わせてください。
- 10パケット送ったら打ち切るようにしています。
上記の例はsendp(レイヤ2から転送)を使った例です。HTTPS(ポート4001)のデータをひたすら送るだけという、あまり意味がない物となっていますが、UDP系のデータとかTCPでもファジング的に送り込むとか、そういう用途では使えるかもしれません。
この例では元と同じパケットが出ます。WireSharkで見るとこんな感じでした(ちなみにScapyは10.0.0.14)
ちなみにIPを変更する事も可能です。上記の packet[IP].dst = "255.255.255.255" のコメントアウトを外すと以下のようになるです。
単に置き換えているだけなのが分かるかと思います。で、Wiresharkにてチェックサムで怒られていると。
パラメータを変えて、チェックサムを再計算させたい
2019/09/08追記です
単に書き換えるだけでなく、相手先が確実に受け取るようにチェックサムを再計算させたい場合は以下のような感じで消すコードを追加すればScapyで勝手に計算してくれるようです。
# チェックサムを再計算させるため、現在のチェックサムをクリアします。以下2行を追加
# 以下のような記述を送信前に記載すれば、IPとTCP共に再計算されるっぽい?
del packet[IP].chksum
del packet[TCP].chksum
# パケット加工(ここからは同じです)
packet[IP].dst = "255.255.255.255"
# 送信
sendp(packet, iface=PCAP_ifname) # layer2に送ります。
で、以下のようにチェックサムもOKとなりますです(255.255.255.255にtcpというのもなかなかですが…)。
レイヤー3からの送出
コメントアウトの場所を変更してsendpではなく、sendを使うようにしますとレイヤー3からの送出となり。もう少し色々変化します。以下のようなデータが出てきます。
こんな感じでキャプチャデータを出す事が可能です。
TCP通信をやってみる
HTTPサーバに対して
- 接続
- 無効なURLを発行して、Not foundを受信
- 切断
というシナリオをScapyで実現します。前の例とは異なりレイヤ3に投げるサンプルです。私はラズパイに立てたWordpressサーバに投げて確認しました。
RST対策
レイヤ3から投げる関係で、Linuxの標準スタックと挙動がぶつかる可能性があります。今回の例だとLinux様のTCPが勝手にRSTを出してしまうという事があります(※)。この場合はiptablesを使って以下のようにRSTを出さないようにします。sudoでやりましょう。
※:まぁ通常では問題のない挙動ではあるのですが。
■RSTを出さない設定に
# iptables -A OUTPUT -p tcp --tcp-flags RST RST -s <<自分のIP>> -j DROP
自分のIPとあるのはscapyを使っているパソコンのIPを指しています。
■元に戻す
実験が終わったら元に戻しましょう。こちらは以下のサンプル等を使った後で操作する感じです。
まずはリストを確認します。
# iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- kali anywhere tcp flags:RST/RST
上のようにOUTPUTのどこかにいるはずです(例では1)。で、次の感じで削除します。
# iptables -D OUTPUT 1
サンプルコード
#!/usr/bin/env python
# coding: shift-jis
from scapy.all import *
from datetime import datetime
import random
import time
# -----> 設定値ここから
PCAP_http_ip = "10.0.0.8"
PCAP_http_port = 80
# <----- 設定値ここまで
def send_only(text, packet):
"""パケット送信のみ行う。送信のサマリも表示。
レイヤ3に対して
Parameters
----------
text : str
サマリの時に付与したい文字列
packet : scapy.layers.inet.IP
送信パケット
"""
print("----> SEND_ONLY:", text)
print(packet.summary())
send(packet)
def send_recv(text, send_packet, tmout=None):
"""パケット送信と受信をセットで行う。送信のサマリ、受信パケットの詳細も表示。
レイヤ3に対して
Parameters
----------
text : str
サマリ、詳細表示の時に付与したい文字列
packet : scapy.layers.inet.IP
送信パケット
tmout : int
タイムアウト(秒)。Noneなら無制限
Returns
---------
recv_packet : scapy.layers.inet.IP
受信パケット
raw_len : int
payloadがある場合、その長さ
"""
print("----> SEND:", text)
print(send_packet.summary())
if tmout == None:
recv_packet = sr1(send_packet)
else:
recv_packet = sr1(send_packet, timeout=tmout)
print("<---- RECV:", text)
raw_len = 0
if recv_packet != None:
print(recv_packet.show())
if Raw in recv_packet:
raw_len = len(recv_packet[Raw])
else:
print("TIMEOUT!")
return recv_packet, raw_len
def sniff_one_packet(text, target_ip):
"""1パケットだけ受信。パケットの詳細も表示。
Parameters
----------
text : str
詳細表示の時に付与したい文字列
target_ip : str
パケットを待つ相手
Returns
---------
recv_packet : scapy.layers.inet.IP
受信パケット
raw_len : int
payloadがある場合、その長さ
"""
print("<---- SNIFF:", text)
raw_len = 0
s = sniff(filter="tcp and ip src host " +
target_ip, count=1) # 1packet決め打ち
recv_packet = s[0]
print(recv_packet.show())
if Raw in recv_packet:
raw_len = len(recv_packet[Raw].load)
print ("raw_len = ", raw_len)
return recv_packet, raw_len
def http_send_test():
"""HTTP試験の本体"""
time_out = 5 # 秒
# IP/TCP パケット作成
ip = IP(dst=PCAP_http_ip)
random_port = int(random.uniform(32768.0, 63353.00))
tcp = TCP(sport=random_port, dport=PCAP_http_port)
# SYNを投げて、SYNACK(になるはず)を受け取る
tcp.flags = "S"
tcp.seq = 1000
send_packet = ip/tcp
recv_packet, _ = send_recv("SYN->ACK", send_packet)
# ACKを投げる(3way-handshakeのラスト)
tcp.seq += 1
tcp.ack = recv_packet[TCP].seq + 1
tcp.flags = "A"
send_packet = ip/tcp
send_only("3WAY_ACK", send_packet)
# GETを投げて、応答を受け取る
# Not Foundで受けるイメージ(短いデータを期待)
http = "GET /hoge HTTP/1.1\r\nHost:" + PCAP_http_ip + \
"\r\nUser-Agent: scapy/0.0\r\nAccept: */*\r\n\r\n"
send_packet = ip/tcp/http
recv_packet, raw_len = send_recv("GET", send_packet, time_out)
# 相手から実体のないACKが来た場合は、実体が1個来るまで待つ
if raw_len == 0:
recv_packet, raw_len = sniff_one_packet("GET BODY", PCAP_http_ip)
# FIN/ACKを投げ、パケットを受信(FIN/ACKが来ることを想定)
tcp.seq = recv_packet[TCP].ack
tcp.ack = recv_packet[TCP].seq + raw_len
tcp.flags = "FA"
send_packet = ip/tcp
recv_packet, _ = send_recv("FIN-ACK", send_packet, time_out)
# ACKを投げる(3way-handshakeのラスト)
tcp.seq = recv_packet[TCP].ack
tcp.ack = recv_packet[TCP].seq + 1
tcp.flags = "A"
send_packet = ip/tcp
send_only("3WAY_ACK", send_packet)
if __name__ == "__main__":
http_send_test()
print("completed.")
Python不慣れな老害が書き殴ったので非常に汚いコードになってますですごめんなさい…
関数的にはhttp_send_test関数から見て後は追っていけばよいかなと思います。以下に各関数の概要をば。
関数名 | 何してるか |
---|---|
send_only | 1パケット送信するだけ |
send_recv | 1パケット送信後、1パケット受信して内容表示 |
sniff_one_packet | 1パケット受信して内容表示 |
http_send_test | HTTP通信のメインです |
http_send_test関数を見ると分かりますが、必要なTCP/IP系の操作して投げているだけな事が分かります。あとはScapy様がよしなにしてくれてるみたいです凄いです。
ちなみに受信パケットの中身ですがはpayloadのサイズ以外は見ていません。もしも解析とか必要であればrecv_packetの中を適時チェックする感じとなりますでしょうか。
私の環境では以下の感じでログが出ました。
.*.**.----> SEND: SYN->ACK
IP / TCP 10.0.0.14:55884 > 10.0.0.8:http S
Begin emission:
Finished sending 1 packets.
Received 2 packets, got 1 answers, remaining 0 packets
<---- RECV: SYN->ACK
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 44
id = 0
flags = DF
frag = 0
ttl = 64
proto = tcp
chksum = 0x26b7
src = 10.0.0.8
dst = 10.0.0.14
\options \
###[ TCP ]###
sport = http
dport = 55884
seq = 3602122109
ack = 1001
dataofs = 6
reserved = 0
flags = SA
window = 29200
chksum = 0x5739
urgptr = 0
options = [('MSS', 1460)]
###[ Padding ]###
load = '\x00\x00'
None
----> SEND_ONLY: 3WAY_ACK
IP / TCP 10.0.0.14:55884 > 10.0.0.8:http A
Sent 1 packets.
----> SEND: GET
IP / TCP 10.0.0.14:55884 > 10.0.0.8:http A / Raw
Begin emission:
Finished sending 1 packets.
Received 1 packets, got 1 answers, remaining 0 packets
<---- RECV: GET
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 40
id = 60835
flags = DF
frag = 0
ttl = 64
proto = tcp
chksum = 0x3917
src = 10.0.0.8
dst = 10.0.0.14
\options \
###[ TCP ]###
sport = http
dport = 55884
seq = 3602122110
ack = 1074
dataofs = 5
reserved = 0
flags = A
window = 29200
chksum = 0x6ead
urgptr = 0
options = []
###[ Padding ]###
load = '\x00\x00\x00\x00\x00\x00'
None
<---- SNIFF: GET BODY
###[ Ethernet ]###
dst = 08:00:27:4c:7d:d3
src = b8:27:eb:e0:64:dc
type = 0x800
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 481
id = 60837
flags = DF
frag = 0
ttl = 64
proto = tcp
chksum = 0x375c
src = 10.0.0.8
dst = 10.0.0.14
\options \
###[ TCP ]###
sport = http
dport = 55884
seq = 3602122110
ack = 1074
dataofs = 5
reserved = 0
flags = PA
window = 29200
chksum = 0xcc7e
urgptr = 0
options = []
###[ Raw ]###
load = 'HTTP/1.1 404 Not Found\r\nDate: Mon, 15 Jul 2019 09:06:02 GMT\r\nServer: Apache/2.4.25 (Raspbian)\r\nContent-Length: 278\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">\n<html><head>\n<title>404 Not Found</title>\n</head><body>\n<h1>Not Found</h1>\n<p>The requested URL /hoge was not found on this server.</p>\n<hr>\n<address>Apache/2.4.25 (Raspbian) Server at 10.0.0.8 Port 80</address>\n</body></html>\n'
None
raw_len = 441
----> SEND: FIN-ACK
IP / TCP 10.0.0.14:55884 > 10.0.0.8:http FA
Begin emission:
Finished sending 1 packets.
Received 1 packets, got 1 answers, remaining 0 packets
<---- RECV: FIN-ACK
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 40
id = 60838
flags = DF
frag = 0
ttl = 64
proto = tcp
chksum = 0x3914
src = 10.0.0.8
dst = 10.0.0.14
\options \
###[ TCP ]###
sport = http
dport = 55884
seq = 3602122551
ack = 1075
dataofs = 5
reserved = 0
flags = FA
window = 29200
chksum = 0x6cf2
urgptr = 0
options = []
###[ Padding ]###
load = '\x00\x00\x00\x00\x00\x00'
None
----> SEND_ONLY: 3WAY_ACK
IP / TCP 10.0.0.14:55884 > 10.0.0.8:http A
Sent 1 packets.
completed.
WireSharkで見るとこんな感じです。
PS
リアルタイムにとなると厳しいかもしれませんが、とにかく投げて受けての試験をするのが割に簡単に出来るように思います。またEther系までやってガンガン介入したい場合は、レイヤ2から投げるとかの工夫が必要なのかもしれませんですね。
ちょっと宣伝
つっても私が儲かるとかでは全くありませんが(汗
Scapyでpcap解析してエクセルに出すサンプルとかGitHubに公開してます。まーもし良かったらご参考まで。
参考
以下のサイトを参考にさせていただきました。皆様ありがとうございます。
-
公式です
-
TCPの出し方について、非常に参考になりました
-
ScapyのAPIなどについて、以下が参考になりました(戻り値の型式とか)
http://python.zombie-hunting-club.com/entry/2018/04/18/112124
https://github.com/secdev/scapy/blob/master/scapy/sendrecv.py
-
RSTの件はここを参考に対策しました
https://stackoverflow.com/questions/9058052/unwanted-rst-tcp-packet-with-scapy
-
チェックサムの再計算はここを参考にしました。
https://stackoverflow.com/questions/5953371/how-to-calculate-a-packet-checksum-without-sending-it
以上です。(いるかどうかは分からないですが)ここまで読んで下さりありがとうございました。