1#!/usr/local/bin/python3 2# check wether path mtu to dst is as expected 3 4import os 5import threading 6from addr import * 7from scapy.all import * 8 9# 10# we can not use scapy's sr() function as receive side 11# ignores the packet we expect to see. Packet is ignored 12# due to mismatching sequence numbers. 'bogus_syn' is using 13# seq = 1000000, while response sent back by PF has ack, 14# which fits regular session opened by 'syn'. 15# 16class Sniff1(threading.Thread): 17 filter = None 18 captured = None 19 packet = None 20 def run(self): 21 self.captured = sniff(iface=LOCAL_IF, filter=self.filter, 22 count=1, timeout=5) 23 if self.captured: 24 self.packet = self.captured[0] 25 26tport=os.getpid() & 0xffff 27 28ip=IP(src=FAKE_NET_ADDR, dst=REMOTE_ADDR) 29 30print("Send SYN packet, receive SYN+ACK") 31syn=TCP(sport=tport, dport='echo', seq=1, flags='S', window=(2**16)-1) 32synack=sr1(ip/syn, iface=LOCAL_IF, timeout=5) 33 34if synack is None: 35 print("ERROR: no matching SYN+ACK packet received") 36 exit(1) 37 38print("Send ACK packet to finish handshake.") 39ack=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='A', 40 ack=synack.seq+1) 41send(ip/ack, iface=LOCAL_IF) 42 43print("Connection is established, send bogus SYN, expect challenge ACK") 44bogus_syn=TCP(sport=syn.sport, dport=syn.dport, seq=1000000, flags='S', 45 window=(2**16)-1) 46sniffer = Sniff1(); 47sniffer.filter = "src %s and tcp port %u and dst %s and tcp port %u " \ 48 "and tcp[tcpflags] = tcp-ack" % (ip.dst, syn.dport, ip.src, syn.sport) 49sniffer.start() 50time.sleep(1) 51send(ip/bogus_syn, iface=LOCAL_IF) 52sniffer.join(timeout=7) 53challenge_ack = sniffer.packet 54 55if challenge_ack is None: 56 print("ERROR: no matching ACK packet received") 57 exit(1) 58 59if challenge_ack.getlayer(TCP).seq != (synack.seq + 1): 60 print("ERROR: expecting seq %d got %d in challange ack" % \ 61 (challenge_ack.getlayer(TCP).seq, (synack.seq + 1))) 62 exit(1) 63 64exit(0) 65