Today we started discussing the algorithmic aspects of TCP.
We will continue on Tuesday.

=======================[ Readings ]========================

Continue reading textbook chapters about TCP. Note that TCP
gets 5 chapters in the book, Ch. 12--16, whereas all other
protocols get at most one plus a few mentions in others.

Ch. 12, previously assigned, gets you the overview of TCP.
It mentions TCP options that you see in our actual pcaps.
These options are further discussed in Ch. 13.3.1--4.  

Read 13.5.1, which explains the states that a TCP connection
can be in. This state machine is a part of the standard,
and answers the question of what TCP behavior is expected 
in response to certain packets in each state.

Read 15.1--5 about the delayed ACK, Nagle's algorithm, and their
interaction.

Read http://www.stuartcheshire.org/papers/nagledelayedack/ about
a real-life example of Nagle's algorithm conflicting with the delayed
ACK (cf. https://en.wikipedia.org/wiki/Nagle%27s_algorithm). 

Read 14.1--4 about retransmission timeouts. 

I found a succinct set of slides that summarizes these issues:
http://www.cs.uah.edu/~gcox/670docs/670s08lec4-tcpimplementation.pdf

-------------------------[ Tarpits ]-------------------------

Tarpits weaponize the use of TCP window set to 0. This causes a spammer's
machine to be stuck in a connection to the "tarpit" machine, rather than
moving on to connecting to actual production machines. 

https://en.wikipedia.org/wiki/Tarpit_%28networking%29#The_original_tarpit_idea

Of course, an attacker aware of the tarpit trick can program their TCP
stack to get unstuck, but that requires the attacker to understand and
reprogram TCP internals.

-------------------------[ Scapy ]-----------------------

Scapy is an extremely versatile Python environment for packet
crafting. Scapy encodes, in fairly readable Python code, a lot
of protocol RFC knowledge. 

See http://www.cs.dartmouth.edu/~sergey/cs60/misc-tools/scapy-log.txt 

For Scapy cheatsheets:
https://blogs.sans.org/pen-testing/files/2016/04/ScapyCheatSheet_v0.2.pdf
http://packetlife.net/media/library/36/scapy.pdf
http://www.packetlevel.ch/html/scapy/docs/scapy_sans.pdf

Scapy tutorial (skip to Ch. 3 for examples; Ch. 1 is general info, and
  Ch. 2 is about installation on different systems.  A simple "apt-get
  install python-scapy" on Linux, "port install scapy" worked for me
  on MacPorts. Scapy is already installed in your VMs):

  http://www.dirk-loss.de/scapy-doc/Scapy.pdf

-------------------------[ Scapy startup bug ]-----------------------

I managed to find the reason for Scapy failing to start on my Mac in
class (and, possibly, for some of your Scapy installations crashing,
too).

Some scapy initialization routines are confused by the vboxnet0
virtual interface being up. They fail to parse the information about
it, which leads to a crash. However, bringing this interface down
allows Scapy to start up with no problem.

This is a bug in Scapy, due to Scapy being too aggressive about
finding out which interfaces it can listen on and inject through.  I
will file a bug report; in the meantime, bring vboxnet0 down before
you start scapy at your MacOS rootshell; then you can bring it up
again:

# scapy
Traceback (most recent call last):
  File "/opt/local/bin/scapy", line 25, in <module>
    interact()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scapy/main.py", line 278, in interact
    scapy_builtins = __import__("all",globals(),locals(),".").__dict__
<crash skipped>

# ifconfig vboxnet0 down
# scapy
INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().
WARNING: No route found for IPv6 destination :: (no default route?)
Welcome to Scapy (2.3.1)
>>> a = IP()
>>> a.show()
###[ IP ]###
  version= 4
  ihl= None
  tos= 0x0
  len= None
  id= 1
<skipped>

# ifconfig vboxnet0 up

-----------------------[ Naive TCP handshake responder ]-----------------------

We saw a very naive approach to responding to a TCP handshake today in
class. It is posted, with some additions, in 
http://www.cs.dartmouth.edu/~sergey/cs60/lab4/tcp-raw-responder.c


This code falls *far* short of a real TCP implementation, but
it shows several things:

1) You really do need a well-defined state machine to make sure your
   code reacts right to incoming packets in each situation. A collection
   of if -- if else -- else would simply not do! The states 
   are enumerated in /usr/include/netinet/tcp.h (on Linux) 
   /usr/include/netinet/tcp_fsm.h (on MacOS/Darwin). See 13.5.1, 
   http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentSequenceNumberSynchroniz-2.htm, and 
   http://tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm

2) TCP checksum is a nuisance, because it involves a "pseudo-header"
   (http://www.tcpipguide.com/free/t_TCPChecksumCalculationandtheTCPPseudoHeader-2.htm)
   that does not occur in any packet received or sent. My code
   collects the bytes over which the TCP checksum is run by copying
   them into a buffer, but this is hugely wasteful: a TCP/IP stack has
   better things to do than wasting CPU cycles on copying bytes
   around! In fact, modern TCP/IP stacks are "zero-copy": they never
   copy the bytes received from the network device until these bytes
   are given to a userland application (and thus much be copied from
   kernel space into userland space).
 
   Examples of a zero-copy checksum are many; e.g.,
    http://minirighi.sourceforge.net/html/tcp_8c-source.html

3) You can pre-compute the TCP packets to send out for a valid
   response to an HTTP request for a static message or file.

   My code breaks the "file" into three lines and sends them one after
   another, but one can precompute an entire packet-level response to
   an HTTP request: http://dunkels.com/adam/miniweb/  Then the only
   remaining thing is to change the destination IP and port in these
   stored packets, recompute the checksums, and send. This, it turns
   out, can be done in 30 bytes of binary code.
 
   This is a weird example that doesn't belong in production, but it
   shows that without its algorithms TCP is really simple.

In a VM, running 
# ./tcp-raw-responder

In a host window:

$  nc 192.168.56.100 80
Hello TCP
Great to meet you!
Nice weather we are having, but they say it will rain on Monday.
^D

In another host window as root:

# tcpdump -vx -i vboxnet0 -n tcp

// SYN as sent by nc:

# tcpdump -vx -i vboxnet0 -n tcp
tcpdump: listening on vboxnet0, link-type EN10MB (Ethernet), capture size 65535 bytes
01:35:59.849805 IP (tos 0x0, ttl 64, id 23344, offset 0, flags [DF], proto TCP (6), length 64)
    192.168.56.1.62438 > 192.168.56.100.80: Flags [S], cksum 0x844d (correct), seq 255257674, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 387824164 ecr 0,sackOK,eol], length 0
	0x0000:  4500 0040 5b30 4000 4006 edd1 c0a8 3801
	0x0010:  c0a8 3864 f3e6 0050 0f36 ec4a 0000 0000
	0x0020:  b002 ffff 844d 0000 0204 05b4 0103 0305
	0x0030:  0101 080a 171d ba24 0000 0000 0402 0000

// My faked SYN+ACK. Sending RSTs from the VM is blocked by an IPtables rule
//  (see previous lecture notes).

01:35:59.850215 IP (tos 0x0, ttl 64, id 23344, offset 0, flags [DF], proto TCP (6), length 64)
    192.168.56.100.80 > 192.168.56.1.62438: Flags [S.], cksum 0x1dd6 (correct), seq 2863315899, ack 255257675, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 387824164 ecr 0,sackOK,eol], length 0
	0x0000:  4500 0040 5b30 4000 4006 edd1 c0a8 3864
	0x0010:  c0a8 3801 0050 f3e6 aaaa bbbb 0f36 ec4b
	0x0020:  b012 ffff 1dd6 0000 0204 05b4 0103 0305
	0x0030:  0101 080a 171d ba24 0000 0000 0402 0000

// My SYN+ACK passes muster. I get an ACK back, completing the handshake:

01:35:59.850249 IP (tos 0x0, ttl 64, id 24559, offset 0, flags [DF], proto TCP (6), length 52)
    192.168.56.1.62438 > 192.168.56.100.80: Flags [.], cksum 0x7c4e (correct), ack 1, win 4117, options [nop,nop,TS val 387824164 ecr 387824164], length 0
	0x0000:  4500 0034 5fef 4000 4006 e91e c0a8 3801
	0x0010:  c0a8 3864 f3e6 0050 0f36 ec4b aaaa bbbc
	0x0020:  8010 1015 7c4e 0000 0101 080a 171d ba24
	0x0030:  171d ba24

// Now I send my "Hello TCP\n\0" payload (NOTE: seq 1:12)

01:35:59.850415 IP (tos 0x0, ttl 64, id 24559, offset 0, flags [DF], proto TCP (6), length 63)
    192.168.56.100.80 > 192.168.56.1.62438: Flags [.], cksum 0xb403 (correct), seq 1:12, ack 1, win 4117, options [nop,nop,TS val 387824164 ecr 387824164], length 11
	0x0000:  4500 003f 5fef 4000 4006 e913 c0a8 3864
	0x0010:  c0a8 3801 0050 f3e6 aaaa bbbc 0f36 ec4b
	0x0020:  8010 1015 b403 0000 0101 080a 171d ba24
	0x0030:  171d ba24 4865 6c6c 6f20 5443 500a 00

// ...and my next payload... (NOTE: seq 12:32)

01:35:59.850494 IP (tos 0x0, ttl 64, id 24559, offset 0, flags [DF], proto TCP (6), length 72)
    192.168.56.100.80 > 192.168.56.1.62438: Flags [.], cksum 0xf447 (correct), seq 12:32, ack 1, win 4117, options [nop,nop,TS val 387824164 ecr 387824164], length 20
	0x0000:  4500 0048 5fef 4000 4006 e90a c0a8 3864
	0x0010:  c0a8 3801 0050 f3e6 aaaa bbc7 0f36 ec4b
	0x0020:  8010 1015 f447 0000 0101 080a 171d ba24
	0x0030:  171d ba24 4772 6561 7420 746f 206d 6565
	0x0040:  7420 796f 7521 0a00

// ...both are ACK-ed, cumulatively (NOTE: ack 32)
//    (This cumulative ACK rather than two separate ACKs are due to the delayed ACK.)
//    (Remember: every second segment is still ACK-ed immediately when the delayed ACK)
//    (  is in force.)

01:35:59.850520 IP (tos 0x0, ttl 64, id 61262, offset 0, flags [DF], proto TCP (6), length 52)
    192.168.56.1.62438 > 192.168.56.100.80: Flags [.], cksum 0x7c30 (correct), ack 32, win 4116, options [nop,nop,TS val 387824164 ecr 387824164], length 0
	0x0000:  4500 0034 ef4e 4000 4006 59bf c0a8 3801
	0x0010:  c0a8 3864 f3e6 0050 0f36 ec4b aaaa bbdb
	0x0020:  8010 1014 7c30 0000 0101 080a 171d ba24
	0x0030:  171d ba24

// ...and there is my third segment (NOTE: seq 32:98):

01:35:59.850593 IP (tos 0x0, ttl 64, id 24559, offset 0, flags [DF], proto TCP (6), length 118)
    192.168.56.100.80 > 192.168.56.1.62438: Flags [.], cksum 0x2375 (correct), seq 32:98, ack 1, win 4117, options [nop,nop,TS val 387824164 ecr 387824164], length 66
	0x0000:  4500 0076 5fef 4000 4006 e8dc c0a8 3864
	0x0010:  c0a8 3801 0050 f3e6 aaaa bbdb 0f36 ec4b
	0x0020:  8010 1015 2375 0000 0101 080a 171d ba24
	0x0030:  171d ba24 4e69 6365 2077 6561 7468 6572
	0x0040:  2077 6520 6172 6520 6861 7669 6e67 2c20
	0x0050:  6275 7420 7468 6579 2073 6179 2069 7420
	0x0060:  7769 6c6c 2072 6169 6e20 6f6e 204d 6f6e
	0x0070:  6461 792e 0a00

// ...and an ACK for it: (NOTE: ack 98)

01:35:59.951239 IP (tos 0x0, ttl 64, id 22892, offset 0, flags [DF], proto TCP (6), length 52)
    192.168.56.1.62438 > 192.168.56.100.80: Flags [.], cksum 0x7b8b (correct), ack 98, win 4114, options [nop,nop,TS val 387824265 ecr 387824164], length 0
	0x0000:  4500 0034 596c 4000 4006 efa1 c0a8 3801
	0x0010:  c0a8 3864 f3e6 0050 0f36 ec4b aaaa bc1d
	0x0020:  8010 1012 7b8b 0000 0101 080a 171d ba89
	0x0030:  171d ba24
^C
8 packets captured
12 packets received by filter
0 packets dropped by kernel


Note that this will break in interesting ways if 192.168.56.1 attempts
sending any data. That data will not be ACK-ed, because my naive code
does not do it (except for the FIN+ACK); it will, however, be echoed
back, because my code blindly copies the incoming packet and only
swaps (srcIP, dstIP, srcPort, dstPort) around, and adds the
payload. This lazy way works for the initial handshake, but not for
the actual data transmission!

There are so many things wrong with this "implementation", but it
fools netcat into receiving the payload strings.

Closing this connection cleanly is not hard. First, you'd need to send
a FIN packet indicating there will be no more payloads; then you'll
want to ACK the FIN from the host side. See 
http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm