Jacek Wielemborek
2014-06-22 12:46:44 UTC
Hello,
(This post is based on my StackOverflow question, which can be
found here: http://stackoverflow.com/q/24340455/1091116)
I was recently trying to write a Scapy script that performs a
full TCP handshake. The idea was that I connect two Qemu VMs
using `-net socket` userspace interface (which seems to handle
raw IP/ethernet fine) and instruct machine B to block all input
from A (to prevent it from sending the RSTs). Then, I used telnet
to `connect()` from machine A to B and ran the following script
on machine B:
#!/usr/bin/python
import scapy.all as scapy
filter = "port 31337"
iface = "eth0"
def prepare_response(t):
print("Received: %s" % repr(t))
t.src, t.dst = t.dst, t.src # swap ethernet addresses
ip = t.getlayer("IP")
ip.src, ip.dst = ip.dst, ip.src
t.dport, t.sport = t.sport, t.dport
t.ack = t.seq
t.ack += 1
syn = scapy.sniff(filter=filter, count=1, iface=iface)[0]
print(syn.sprintf('%TCP.flags%'))
syn_ack = syn
prepare_response(syn_ack)
syn_ack.getlayer("TCP").flags |= 0x10 # set the ACK flag
print(syn_ack.sprintf('%TCP.flags%'))
print("Sending: %s" % repr(syn_ack))
scapy.sendp(syn_ack, iface=iface, verbose=False)
ack = scapy.sniff(filter=filter, count=1, iface=iface)[0]
assert(ack.flags & 0x10)
The problem is that instead of receiving an ACK from A to B, I
seem to get a SYN retransmission as if SYN+ACK wasn't interpreted
correctly:
(A Wireshark screenshot can be found here:
https://imgur.com/kv7A3Hr )
tcp on machine A confirms that SYN+ACK reached the machine:
05:47:03.925100 IP 10.0.0.1.39634 > debian.31337: Flags [S],
seq 2426802888, win 14600, options [mss
1460,nop,nop,sackOK,nop,wscale 4], length 0
05:47:03.927515 IP debian.31337 > 10.0.0.1.39634: Flags [S.],
seq 2426802888, ack 2426802889, win 14600, options [mss
1460,nop,nop,sackOK,nop,wscale 4], length 0
Here's the PCAP file from machine B's perspective in Base64 form:
1MOyoQIABAAAAAAAAAAAAP//AAABAAAAYlilUwieDgARAQAAEQEAAAEAXgAA+1J
UABI0VggARQABA2UUQAD/ESrYCgAAAuAAAPsU6RTpAO/r/QAAAAAAAwAAAAUAAA
E2ATUBNAEzATIBMQFlAWYBZgFmATABMAE0ATUBMAE1ATABMAEwATABMAEwATABM
AEwATABMAEwATABOAFlAWYDaXA2BGFycGEAAP8AAQtkZWJpYW4tMTA5MwVsb2Nh
bAAA/wABATIBMAEwAjEwB2luLWFkZHLAUAD/AAHAWgANAAEAAAB4AAsESTY4NgV
MSU5VWMBaAAEAAQAAAHgABAoAAALAcQAMAAEAAAB4AALAWsBaABwAAQAAAHgAEP
6AAAAAAAAAUFQA//4SNFbADAAMAAEAAAB4AALAWmJYpVMJoA4AnAAAAJwAAAABA
F4AAPtSVAASNFYIAEUAAI4GlEAA/xGJzgoAAAHgAAD7FOkU6QB6hFgAAIQAAAAA
AQAAAAABNgE1ATQBMwEyATEBZQFmAWYBZgEwATABNAE1ATABNQEwATABMAEwATA
BMAEwATABMAEwATABMAEwATgBZQFmA2lwNgRhcnBhAAAMgAEAAAB4ABIKZGViaW
FuLTQwNwVsb2NhbABnWKVTvIYIAEIAAABCAAAAUlQAEjRWUlQAEjRWCABFAAA0H
dtAAEAGCOcKAAABCgAAAprbemmul/p8AAAAAIACOQhjsAAAAgQFtAEBBAIBAwME
Z1ilU5COCABCAAAAQgAAAFJUABI0VlJUABI0VggARQAANB3bQABABgjnCgAAAgo
AAAF6aZrbrpf6fK6X+n2AEjkIY7AAAAIEBbQBAQQCAQMDBGhYpVPTfggAQgAAAE
IAAABSVAASNFZSVAASNFYIAEUAADQd3EAAQAYI5goAAAEKAAACmtt6aa6X+nwAA
AAAgAI5CGOwAAACBAW0AQEEAgEDAwRqWKVTrI4IAEIAAABCAAAAUlQAEjRWUlQA
EjRWCABFAAA0Hd1AAEAGCOUKAAABCgAAAprbemmul/p8AAAAAIACOQhjsAAAAgQ
FtAEBBAIBAwME
And one from A to B's perspective:
1MOyoQIABAAAAAAAAAAAAP//AAABAAAAVVilU9NXCABCAAAAQgAAAFJUABI0VlJ
UABI0VggARQAANB3bQABABgjnCgAAAQoAAAKa23pprpf6fAAAAACAAjkIFCkAAA
IEBbQBAQQCAQMDBFVYpVPIYAgAQgAAAEIAAABSVAASNFZSVAASNFYIAEUAADQd2
0AAQAYI5woAAAIKAAABemma266X+nyul/p9gBI5CGOwAAACBAW0AQEEAgEDAwRW
WKVT008IAEIAAABCAAAAUlQAEjRWUlQAEjRWCABFAAA0HdxAAEAGCOYKAAABCgA
AAprbemmul/p8AAAAAIACOQgUKQAAAgQFtAEBBAIBAwMEWFilU4FfCABCAAAAQg
AAAFJUABI0VlJUABI0VggARQAANB3dQABABgjlCgAAAQoAAAKa23pprpf6fAAAA
ACAAjkIFCkAAAIEBbQBAQQCAQMDBA==
At first I thought that this is somehow related to some Linux
TCP/IP quirk, so I experimented with turning off TCP timestamps
and SYN cookies. I also tried increasing IP ID, which didn't help
either. Both machines are running Debian 7.5 with linux-
image-3.2.0-4-686-pae under qemu 1.6.2.
What am I missing?
Yours,
Jacek Wielemborek
(This post is based on my StackOverflow question, which can be
found here: http://stackoverflow.com/q/24340455/1091116)
I was recently trying to write a Scapy script that performs a
full TCP handshake. The idea was that I connect two Qemu VMs
using `-net socket` userspace interface (which seems to handle
raw IP/ethernet fine) and instruct machine B to block all input
from A (to prevent it from sending the RSTs). Then, I used telnet
to `connect()` from machine A to B and ran the following script
on machine B:
#!/usr/bin/python
import scapy.all as scapy
filter = "port 31337"
iface = "eth0"
def prepare_response(t):
print("Received: %s" % repr(t))
t.src, t.dst = t.dst, t.src # swap ethernet addresses
ip = t.getlayer("IP")
ip.src, ip.dst = ip.dst, ip.src
t.dport, t.sport = t.sport, t.dport
t.ack = t.seq
t.ack += 1
syn = scapy.sniff(filter=filter, count=1, iface=iface)[0]
print(syn.sprintf('%TCP.flags%'))
syn_ack = syn
prepare_response(syn_ack)
syn_ack.getlayer("TCP").flags |= 0x10 # set the ACK flag
print(syn_ack.sprintf('%TCP.flags%'))
print("Sending: %s" % repr(syn_ack))
scapy.sendp(syn_ack, iface=iface, verbose=False)
ack = scapy.sniff(filter=filter, count=1, iface=iface)[0]
assert(ack.flags & 0x10)
The problem is that instead of receiving an ACK from A to B, I
seem to get a SYN retransmission as if SYN+ACK wasn't interpreted
correctly:
(A Wireshark screenshot can be found here:
https://imgur.com/kv7A3Hr )
tcp on machine A confirms that SYN+ACK reached the machine:
05:47:03.925100 IP 10.0.0.1.39634 > debian.31337: Flags [S],
seq 2426802888, win 14600, options [mss
1460,nop,nop,sackOK,nop,wscale 4], length 0
05:47:03.927515 IP debian.31337 > 10.0.0.1.39634: Flags [S.],
seq 2426802888, ack 2426802889, win 14600, options [mss
1460,nop,nop,sackOK,nop,wscale 4], length 0
Here's the PCAP file from machine B's perspective in Base64 form:
1MOyoQIABAAAAAAAAAAAAP//AAABAAAAYlilUwieDgARAQAAEQEAAAEAXgAA+1J
UABI0VggARQABA2UUQAD/ESrYCgAAAuAAAPsU6RTpAO/r/QAAAAAAAwAAAAUAAA
E2ATUBNAEzATIBMQFlAWYBZgFmATABMAE0ATUBMAE1ATABMAEwATABMAEwATABM
AEwATABMAEwATABOAFlAWYDaXA2BGFycGEAAP8AAQtkZWJpYW4tMTA5MwVsb2Nh
bAAA/wABATIBMAEwAjEwB2luLWFkZHLAUAD/AAHAWgANAAEAAAB4AAsESTY4NgV
MSU5VWMBaAAEAAQAAAHgABAoAAALAcQAMAAEAAAB4AALAWsBaABwAAQAAAHgAEP
6AAAAAAAAAUFQA//4SNFbADAAMAAEAAAB4AALAWmJYpVMJoA4AnAAAAJwAAAABA
F4AAPtSVAASNFYIAEUAAI4GlEAA/xGJzgoAAAHgAAD7FOkU6QB6hFgAAIQAAAAA
AQAAAAABNgE1ATQBMwEyATEBZQFmAWYBZgEwATABNAE1ATABNQEwATABMAEwATA
BMAEwATABMAEwATABMAEwATgBZQFmA2lwNgRhcnBhAAAMgAEAAAB4ABIKZGViaW
FuLTQwNwVsb2NhbABnWKVTvIYIAEIAAABCAAAAUlQAEjRWUlQAEjRWCABFAAA0H
dtAAEAGCOcKAAABCgAAAprbemmul/p8AAAAAIACOQhjsAAAAgQFtAEBBAIBAwME
Z1ilU5COCABCAAAAQgAAAFJUABI0VlJUABI0VggARQAANB3bQABABgjnCgAAAgo
AAAF6aZrbrpf6fK6X+n2AEjkIY7AAAAIEBbQBAQQCAQMDBGhYpVPTfggAQgAAAE
IAAABSVAASNFZSVAASNFYIAEUAADQd3EAAQAYI5goAAAEKAAACmtt6aa6X+nwAA
AAAgAI5CGOwAAACBAW0AQEEAgEDAwRqWKVTrI4IAEIAAABCAAAAUlQAEjRWUlQA
EjRWCABFAAA0Hd1AAEAGCOUKAAABCgAAAprbemmul/p8AAAAAIACOQhjsAAAAgQ
FtAEBBAIBAwME
And one from A to B's perspective:
1MOyoQIABAAAAAAAAAAAAP//AAABAAAAVVilU9NXCABCAAAAQgAAAFJUABI0VlJ
UABI0VggARQAANB3bQABABgjnCgAAAQoAAAKa23pprpf6fAAAAACAAjkIFCkAAA
IEBbQBAQQCAQMDBFVYpVPIYAgAQgAAAEIAAABSVAASNFZSVAASNFYIAEUAADQd2
0AAQAYI5woAAAIKAAABemma266X+nyul/p9gBI5CGOwAAACBAW0AQEEAgEDAwRW
WKVT008IAEIAAABCAAAAUlQAEjRWUlQAEjRWCABFAAA0HdxAAEAGCOYKAAABCgA
AAprbemmul/p8AAAAAIACOQgUKQAAAgQFtAEBBAIBAwMEWFilU4FfCABCAAAAQg
AAAFJUABI0VlJUABI0VggARQAANB3dQABABgjlCgAAAQoAAAKa23pprpf6fAAAA
ACAAjkIFCkAAAIEBbQBAQQCAQMDBA==
At first I thought that this is somehow related to some Linux
TCP/IP quirk, so I experimented with turning off TCP timestamps
and SYN cookies. I also tried increasing IP ID, which didn't help
either. Both machines are running Debian 7.5 with linux-
image-3.2.0-4-686-pae under qemu 1.6.2.
What am I missing?
Yours,
Jacek Wielemborek