scapy send tcp packet on established connection

fhamad picture fhamad · Jan 13, 2018 · Viewed 7.9k times · Source

I have the following:

Server Side: TCP python server (not scapy) Client Side: Scapy to establish connection and sent TCP packet

I am trying to send TCP packet via scapy on established connection after 3 way handshaking

I am able to build the 3 way handshaking and the server side (other side -python TCP server- not scapy- create TCP socket, bind, listen, accpet, recv()) shows new connection comes and accept() returns the created FD

I am trying to send packet from scapy after the 3 way handshake succeeded but recv() on the not-scapy side can't get the packet

scapy side:

#!/usr/bin/env python
from scapy.all import *
import time

# VARIABLES
src = sys.argv[1]
dst = sys.argv[2]
sport = random.randint(1024,65535)
dport = int(sys.argv[3])

# SYN
ip=IP(src=src,dst=dst)
SYN=TCP(sport=sport,dport=dport,flags='S',seq=1000)
SYNACK=sr1(ip/SYN)

# ACK
ACK=TCP(sport=sport, dport=dport, flags='A', seq=SYNACK.ack, ack=SYNACK.seq + 1)
send(ip/ACK)

time.sleep(15)

ip = IP(src=src, dst=dst)
tcp = ip / TCP(sport=sport, dport=dport, flags="PA", seq=123, ack=1) / "scapy packet 123"
tcp.show2()

send(tcp)

Not scapy side:

#!/usr/bin/python

import socket
from scapy.all import *

ip = sys.argv[1]
port = sys.argv[2]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ip, int(port)))
s.listen(1)

while True :
    conn, addr = s.accept()
    print 'Connection address:', addr
    data = conn.recv(1024) # Stuck here .....

tcpdump output shows:

tcpdump: listening on ens1f1, link-type EN10MB (Ethernet), capture size 65535 bytes
18:09:35.820865 IP (tos 0x0, ttl 64, id 1, offset 0, flags [none], proto TCP (6), length 40)
    11.4.3.31.63184 > 11.4.3.30.strexec-d: Flags [S], cksum 0x6543 (correct), seq 1000, win 8192,                                                                        length 0
18:09:35.821017 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
    11.4.3.30.strexec-d > 11.4.3.31.63184: Flags [S.], cksum 0x748d (correct), seq 3017593595, ac                                                                       k 1001, win 29200, options [mss 1460], length 0
18:09:35.930593 IP (tos 0x0, ttl 64, id 1, offset 0, flags [none], proto TCP (6), length 40)
    11.4.3.31.63184 > 11.4.3.30.strexec-d: Flags [.], cksum 0xde5a (correct), seq 1, ack 1, win 8                                                                       192, length 0
18:09:51.057904 IP (tos 0x0, ttl 64, id 1, offset 0, flags [none], proto TCP (6), length 56)
    11.4.3.31.63184 > 11.4.3.30.strexec-d: Flags [P.], cksum 0x8eef (correct), seq 4294966419:429                                                                       4966435, ack 1277373702, win 8192, length 16
18:09:51.057996 IP (tos 0x0, ttl 64, id 1194, offset 0, flags [DF], proto TCP (6), length 40)
    11.4.3.30.strexec-d > 11.4.3.31.63184: Flags [.], cksum 0x8c4a (correct), seq 1, ack 1, win 2                                                                       9200, length 0

My question why receiver side is not getting the sent packet?

Note: My target to send TCP packet on established connection with bad checksum and receive it by not scapy tcp server Thanks in advance!!

Answer

Gil Hamilton picture Gil Hamilton · Jan 18, 2018

Your sequence numbers must accurately track the payload bytes you send. A packet with the SYN or FIN flag set is an exception and is treated as if it had a payload of length 1. In other words, you can use whatever initial sequence number you like, but then it must increase byte-for-byte with your sent payload (+1 for SYN or SYN+ACK [or FIN]).

So, if you start with a sequence number of 1000 in the SYN packet, then the next packet with payload (call this pktA) should have a sequence number of 1001. Then your next packet (pktB) should have sequence number 1001 + pktA.payload_size, and so forth.

Likewise, you cannot simply set the acknowledge number field in the TCP header to 1 (as you're doing with the "scapy packet 123"). Whenever you provide the ACK flag in the header, you need to acknowledge the other side's payload by setting the acknowledge number in the header to the last-received sequence number from the other side's last payload. In this case, you already sent a bare ACK packet with that acknowledge number, so you don't strictly need to include the ACK flag, but it's typical to always include it and if you are going to include the flag, the acknowledge sequence number should be set correctly.

See this link for a good overview: http://packetlife.net/blog/2010/jun/7/understanding-tcp-sequence-acknowledgment-numbers/