1*e7abe75aSbluhm#!/usr/local/bin/python3 2b83a2f27Sbluhm 3b83a2f27Sbluhmimport os 42b21f7bdSbluhmimport threading 5b83a2f27Sbluhmfrom addr import * 6b83a2f27Sbluhmfrom scapy.all import * 7b83a2f27Sbluhm 82b21f7bdSbluhmclass Sniff1(threading.Thread): 92b21f7bdSbluhm filter = None 102b21f7bdSbluhm captured = None 112b21f7bdSbluhm packet = None 122b21f7bdSbluhm def __init__(self): 132b21f7bdSbluhm # clear packets buffered by scapy bpf 142b21f7bdSbluhm sniff(iface=LOCAL_IF, timeout=1) 152b21f7bdSbluhm super(Sniff1, self).__init__() 162b21f7bdSbluhm def run(self): 172b21f7bdSbluhm self.captured = sniff(iface=LOCAL_IF, filter=self.filter, 182b21f7bdSbluhm count=1, timeout=3) 192b21f7bdSbluhm if self.captured: 202b21f7bdSbluhm self.packet = self.captured[0] 212b21f7bdSbluhm 22b83a2f27Sbluhmip=IP(src=FAKE_NET_ADDR, dst=REMOTE_ADDR) 239ae5678bSbluhmtport=os.getpid() & 0xffff 24b83a2f27Sbluhm 25*e7abe75aSbluhmprint("Send SYN packet, receive SYN+ACK.") 269ae5678bSbluhmsyn=TCP(sport=tport, dport='chargen', seq=1, flags='S', window=(2**16)-1) 27b83a2f27Sbluhmsynack=sr1(ip/syn, iface=LOCAL_IF, timeout=5) 28b83a2f27Sbluhm 29140ee0aaSbluhmif synack is None: 30*e7abe75aSbluhm print("ERROR: No SYN+ACK from chargen server received.") 31140ee0aaSbluhm exit(1) 32140ee0aaSbluhm 33*e7abe75aSbluhmprint("Send ACK packet, receive chargen data.") 34b83a2f27Sbluhmack=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='A', 35b83a2f27Sbluhm ack=synack.seq+1, window=(2**16)-1) 36b83a2f27Sbluhmdata=sr1(ip/ack, iface=LOCAL_IF, timeout=5) 37b83a2f27Sbluhm 38140ee0aaSbluhmif data is None: 39*e7abe75aSbluhm print("ERROR: No data from chargen server received.") 40140ee0aaSbluhm exit(1) 41140ee0aaSbluhm 42*e7abe75aSbluhmprint("Fill our receive buffer.") 43b83a2f27Sbluhmtime.sleep(1) 44b83a2f27Sbluhm 452b21f7bdSbluhm# sr1 cannot be used, TCP data will not match outgoing ICMP packet 462b21f7bdSbluhmsniffer = Sniff1() 472b21f7bdSbluhmsniffer.filter = \ 482b21f7bdSbluhm "ip and src %s and tcp port %u and dst %s and tcp port %u" % \ 492b21f7bdSbluhm (ip.dst, syn.dport, ip.src, syn.sport) 502b21f7bdSbluhmsniffer.start() 512b21f7bdSbluhmtime.sleep(1) 522b21f7bdSbluhm 53*e7abe75aSbluhmprint("Send ICMP fragmentation needed packet with MTU 1300.") 54b83a2f27Sbluhmicmp=ICMP(type="dest-unreach", code="fragmentation-needed", 55b83a2f27Sbluhm nexthopmtu=1300)/data 56b83a2f27Sbluhmsend(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR)/icmp, iface=LOCAL_IF) 57b83a2f27Sbluhm 58*e7abe75aSbluhmprint("Path MTU discovery will resend first data with length 1300.") 592b21f7bdSbluhmsniffer.join(timeout=5) 602b21f7bdSbluhmans = sniffer.packet 61b83a2f27Sbluhm 62caed3289Sbluhmif len(ans) == 0: 63*e7abe75aSbluhm print("ERROR: No data retransmit from chargen server received.") 64140ee0aaSbluhm exit(1) 65caed3289Sbluhmdata=ans[0] 66140ee0aaSbluhm 67*e7abe75aSbluhmprint("Cleanup the other's socket with a reset packet.") 68b83a2f27Sbluhmrst=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='AR', 69b83a2f27Sbluhm ack=synack.seq+1) 70b83a2f27Sbluhmsend(ip/rst, iface=LOCAL_IF) 71b83a2f27Sbluhm 72b83a2f27Sbluhmlen = data.len 73*e7abe75aSbluhmprint("len=%d" % len) 74b83a2f27Sbluhmif len != 1300: 75*e7abe75aSbluhm print("ERROR: TCP data packet len is %d, expected 1300." % len) 76b83a2f27Sbluhm exit(1) 7703da3b73Sbluhm 78b83a2f27Sbluhmexit(0) 79