Beruflich Dokumente
Kultur Dokumente
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__________
[ contents ]
����������
::[0] introduction
::[1] the transmission control protocol
:..
: ::(1.1) tcp segments
: ::(1.2) safe delivery and tcp timers
: :..
: : ::{1.2.1} retransmission timer
: :
: ::(1.3) sliding windows
: ::(1.4) the tcp header
: :..
: : ::{1.4.01} source port
: : ::{1.4.02} destination port
: : ::{1.4.03} sequence number
: : ::{1.4.04} acknowledgement number
: : ::{1.4.05} offset
: : ::{1.4.06} reserved
: : ::{1.4.07} flags
: : ::{1.4.08} window advertisement
: : ::{1.4.09} checksum
: : ::{1.4.10} urgent pointer
: : ::{1.4.11} options and padding
: :
: ::(1.5) establishing a connection
: :..
: : ::{1.5.1} step one - request
: : ::{1.5.2} step two - reply
: : ::{1.5.3} step three - connection
: :
: ::(1.6) closing a connection
:
::[2] advanced portscanning
:..
: ::(2.1) what is portscanning?
: ::(2.2) nmap stealth scanning
: :..
: ::{2.2.1} syn stealth
: ::{2.2.2} fin stealth
:
::[3] the user datagram protocol
:..
: ::(3.1) the udp header
: :..
: : ::{3.1.01} source port
: : ::{3.1.02} destination port
: : ::{3.1.03} length
: : ::{3.1.04} checksum
: :
: ::(3.2) udp spoofing
:
::[a] ports
:..
: ::(a-1) well-known ports
: ::(a-2) registered ports
: ::(a-3) dynamic ports
:
::[b] sockets
:
::[4] last words
_ ______________
[0] :: [ introduction ]
� ��������������
hello boys and girls. this is actually the second part of a set of tutorials i
am writing
about networking protocols, techniques and algorithms. i would definitely
recommend to
read the first part before you read on here for a complete understanding of what
i am trying
to convey. you can find it here:
http://rs.box.sk/papers/ip.txt
so now about this tutorial: why should you know anything about the transport
layer?
because it is essential for understanding how data is being transferred within
the large
networks of today - like, for instance, the internet. you will mainly learn
about tcp
(transmission control protocol) here since i consider it the most popular
protocol as
far as transport layer protocols are concerned. it is widely used and a bit
complex
as well - and we don't just want to scrap the surface this time, you won't get
away with
a schematic summary of the three way handshake. besides an indepth explanation
of tcp,
you will also learn about udp (user datagram protocol), which is rather easy to
understand and which also offers less goodies than tcp.
if you did not understand the words "protocol", "network", or "layer" - please
read my
first tutorial or refer to some more basic stuff. also, if you are an expert and
if you
feel to elite for this, go read something else. this tutorial is not for
complete newbies,
neither was it written for networking gurus. you need to be familiar with high
level
application-layer networking and some average knowledge about programming in c.
_ ___________________________________
[1] :: [ the transmission control protocol ]
� �����������������������������������
so, if you already know ip, you should also know that tcp as a transport layer
protocol
is responsible for safe exchange of data. "safe" in this context means that no
data is lost,
altered after transmission or violated in any way. while ip merely offers a
channel to route
packets through from one host to the other, tcp needs to make sure that one
chunk of data
is still the same chunk of data when it has been sent and received by the remote
host.
(no idea what i am talking about? read the first tutorial ...)
this probably seems quite simple to you since tcp is usually implemented by the
operating
system and not even programmers have to care about what it does. however,
remember ip and
its chaotic treatment of packets: packets get lost, packets are blindly routed
to their
destination until their ttl exceeds and if it does not work, they are discarded.
this time and for tcp only, i will not start with explaining the tcp header -
because too
much would have to be left open and everything would get too complicated. i will
explain
some basic theory behind the way tcp works at first, then the header explanation
will
follow. i won't explain how a connection is established and closed either yet,
you will
read about this in the last part.
___ ______________
(1.1) : ( tcp segments )
��� ��������������
tcp uses so-called segments to split up one chunk of data that has to be sent.
think
of this procedure as of the way ip splits up data into packets, since it is
fairly
the same procedure.
the size of one segment mainly depends on the mtu (maximum transfer unit) of
the
respective network. let's assume we are using a normal ethernet line. in this
case, the network layer gives us an ethernet frame size of 1518 byte. the
network
layer itself needs 18 byte for its header, ip needs 20 bytes and the tcp
header
itself has a size of 20 bytes as well. therefore, the mss in a normal ethernet
would
be:
_____________________________________________________________________________
______
|
|
| note, in case you are wondering:
|
|
|
| tcp does not have to care about whether the networks between the originating
and |
| the remote host might have smaller mtu's than itself, because it can rely on
ip |
| in this case - ip will once again split the segment up into packets if the
|
| segment is too large for a certain network.
|
|
__________________________________________________________________________________
_|
now as one host connects to another one, a certain problem might occur: one
host has
a larger mss than the other one. so it would not be very effective if one host
merely
uses his own mss to define the segment size, upon connection establishment
both hosts
need to find an agreement. in fact, this is quite simple:
the mss of both hosts is sent as a part of the tcp header, and will be
explained
in detail later - refer to (1.5). from now on, i will refer to a tcp packet
as a segment. a packet would not be correct as the segment that is being sent
can be
split up into packets by ip and therefore is not a real packet.
___ ______________________________
(1.2) : ( safe delivery and tcp timers )
��� ������������������������������
as i already mentioned, tcp wants to deliver all the segments safely, it wants
to
ensure that all segments reach their destination. there is only one way to
make sure
that a segment has been sent successfully - the sender needs to receive an
acknowledgement for each single segment that has been sent. once again, don't
worry
how this looks in detail.
that works pretty good as we know, but we still don't know how tcp calculates
the
timeout value for the timer that is started. the speed of our networks is not
always
the same, the internet and especially the route used for our segment can be
very
slow or pretty fast as well - tcp simply does not know. therefore, a constant
value
for the timer would not be a good idea. the timer has to be calculated
dynamically
while data is being exchanged.
if you are not interested in how this works, leave out the following part. the
_____ ______________________
{1.2.1} � { retransmission timer }
����� ����������������������
as tcp has to work in an unstable environment like the internet, the timeout
for
the retransmission timer has to be calculated dynamically. the algorithm
that is
mainly being used to achieve this was invented by van jacobson and works as
follows:
for every connection, tcp uses a variable called rtt (round trip time) to
represent the currently best guess at how long it takes for a segment to
reach the destination and for the acknowledgement to be sent. the rtt
basically
represents the time that is assumed to pass until the acknowledgement
reaches
the sender.
now what about alpha? it is a constant value that expresses how important
the
new measured srtt is for the new rtt. alpha is usually a value between 0.8
and
0.9, 0.875 is a popular value.
besides the rtt, tcp also uses two further variables. obviously, it uses a
variable for the actual time out value which is referred to as rto. the
third
variable called mdev is used to calculate the rto from the rtt:
take 4 times the mdev longer than expected (as the rtt is the time we would
expect). as you might have guessed, the mdev is a variable as well and is
calculated as follows:
betha is once again a constant value which should be smaller than alpha,
jacobson himself suggested a value of 0.75 for this constant.
this is a pretty nice and smooth algorithm now and it works pretty good.
there
have been several different algorithms to calculate the rto in the past, but
i consider this technique the most modern and most accurate way to do so.
one more thing about the retransmission timer though: what about segments
that
have to be sent again when their timer exceeds? if an acknowledgement for
such
a segment reaches the sender before its timer exceeds, we do not know
whether
this acknowledgement refers to the segment we sent first or to the segment
we
sent again after the first segment's timer exceeded. therefore, segments
that
are sent twice or more often are never used to calculate the rtt or the
mdev.
instead, the rto is doubled for every segment that has to be sent again.
this
technique is used by most tcp-implementations.
___ ________________
(1.3) : ( sliding window )
��� ����������������
we live in a multithreaded world, and this has seriously affected tcp as well.
tcp does not send segment by segment one after the other, it sends multiple
segments at the same time. in theory, you think of these segments as part of
a "window":
figure 1.2.1 shows an initial tcp window that would allow tcp to send 10
segments
at once. the segments displayed with points (�) are not being sent yet. after
the
acknowledgement for segment 1 has reached the originating host (the sender),
the
window "slides" to the right side by one and segment 11 is being sent. this
goes on
like this untill all data is sent - every time the acknowledgement for the
first
segment in the window reaches the sender, the window slides on. figure 1.3.2
shows
our tcp window after two segments have been sent successfully:
- tcp can react when there is a problem or a very slow network between the
sender and the receiver. this is known as congestion avoidance.
- imagine two differently strong hosts that are exchanging data via tcp,
for instance a big server and a small client. the server can send much
more data than the client can handle in its small buffer, therefore the
ammount of data that is send at once has to be adjusted as well. this
is known as flow control.
now as you know why we need flow control, let's see how it's done. once again,
the
theory is fairly simple. the receiver sends a window advertisement with every
acknowledgement it sends - this window advertisement tells the sender how big
his
window for sending data should be. the sender, of course, does as he is told
and
adjusts his window size according to the window advertisement he received. a
window
advertisement can also set the window size to 0 which stops the entire
transfer,
until a window advertisement > 0 is sent.
___ ________________
(1.4) : ( the tcp header )
��� ����������������
now you have learned enough about the basic tcp theory, let's have a look at
the
tcp header. as always, the header is sent before the data, and the tcp header
directly
follows the ip header.
<-------------------------------------------- bits
-------------------------------------------->
______________________________________________________________________________
_________________
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|
27|28|29|30|31|32|
|�����������������������������������������������|
�����������������������������������������������|
| source port | destination port
|
|_______________________________________________|
_______________________________________________|
|
����������������������������������������������������������������������������������
�������������|
| squence number
|
|
__________________________________________________________________________________
_____________|
|
����������������������������������������������������������������������������������
�������������|
| acknowledgement number
|
|
__________________________________________________________________________________
_____________|
|�����������|�����������������|�����������������|
�����������������������������������������������|
| offset | reserved | flags | window advertisement
|
|___________|_________________|_________________|
_______________________________________________|
|�����������������������������������������������|
�����������������������������������������������|
| checksum | urgent pointer
|
|_______________________________________________|
_______________________________________________|
|
����������������������������������������������������������������������������������
�������������|
| options and padding
|
|
__________________________________________________________________________________
_____________|
|
##################################################################################
#############|
|###########################################[ data ]
############################################|
|
##################################################################################
#############|
������������������������������������������������������������������������������
�����������������
(figure 1.4.1: the tcp header format as explained in rfc 793, part 3.1:
http://www.rfc-editor.org/rfc/rfc793.txt)
ok, i will now explain the respective parts of the header in detail, and also
explain
their function related to each other.
although both the receiver and the sender as well use the complete tcp
header for their
segments (which is quite logical), the sequence number is only interpreted
by the host
that is currently receiving data.
the 6 bits of the flags field can be set to set the appropriate flag. the
meaning of the
flags when they are set (or not set) will be explained in detail later, but
here is a
quick overview:
+------
+-------------------------------------------------------------------------+
| flag | description
|
+------
+-------------------------------------------------------------------------+
| urg | if urg is set, the urgent pointer field of the tcp header is
evaluated. |
+------
+-------------------------------------------------------------------------+
| ack | if ack is set, the acknowledgement number field is evaluated:
this |
| | means, that an acknowledgement is being sent. also, the window
|
| | advertisement is evaluated only when ack is set.
|
+------
+-------------------------------------------------------------------------+
| psh | if psh is set, the data that the segment contains is not buffered
but |
| | the respective application listening on the destination port is
fed |
| | with the data immediately.
|
+------
+-------------------------------------------------------------------------+
| rst | the rst bit is set when the connection has to be terminated
immediately |
| | in case of an error or when a connection is refused.
|
+------
+-------------------------------------------------------------------------+
| syn | the syn bit is set on connection establishment. refer to (1.5)
|
+------
+-------------------------------------------------------------------------+
| fin | the fin bit is set when the connection is closed refer to (1.6)
|
+------
+-------------------------------------------------------------------------+
to use the field like a bitmask, you might define these constants in a
normal c program
and use the bitwise or to combine them as you wish:
___________________________________________________________________________
________
|
|
| note, in case you are wondering:
|
|
|
| when you use the bitwise or to combine, let's say the ack and the syn
flag, this |
| is what exactly happens:
|
|
|
| position: 1 2 3 4 5 6
|
|
|
| syn = 0x02 = 0 0 0 0 1 0
|
| ack = 0x10 = 0 1 0 0 0 0
|
|
|
| now each bit of the syn flag is compared to the bit of the ack flag at the
same |
| position:
|
|
|
| position 1: 0 or 0 is 0: 0.....
|
| position 2: 0 or 1 is 1: 01....
|
| position 3: 0 or 0 is 0: 010...
|
| position 4: 0 or 0 is 0: 0100..
|
| position 5: 1 or 0 is 1: 01001.
|
| position 6: 0 or 0 is 0: 010010
|
|
|
| the result is a bitmask that contains a bit set at position 2 and 5, which
means |
| that, relative to the tcp header, the 12th and 15th bit are set. there you
are, |
| the ack and syn flag are set.
|
|
__________________________________________________________________________________
_|
[ a pseudo header ]
[ the tcp header ]
[ the data ]
this pseudo header is never sent, it is never received and it is only used
once to calculate
the tcp checksum. it contains information from the ip header and the tcp
header, which is in
fact a violation of the protocol hierarchy. however, it helps tcp to find
packets that have
not been delivered correctly by ip. the pseudo header contains the following
fields:
____________________________________________________________________________
___________________
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|
26|27|28|29|30|31|32|
|
����������������������������������������������������������������������������������
�������������|
| source ip address
|
|
__________________________________________________________________________________
_____________|
|
����������������������������������������������������������������������������������
�������������|
| destination ip address
|
|
__________________________________________________________________________________
_____________|
|�����������������������|�����������������������|
�����������������������������������������������|
| 0 | 6 | tcp segment length
|
|_______________________|_______________________|
_______________________________________________|
the field of the pseudo header that is set to 6 actually represents the
protocol, but as
the tcp pseudo header is used for calculating the tcp checksum, it will
always be 6 as this
is the number that represents the tcp protocol.
when calculating the checksum, the checksum field of the tcp header is
always set to 0 (the
tcp header itself is part of the buffer that is used to calculate the
checksum, so this has
to be clearly defined).
once the receiver calculates the checksum for the segment he receives
(without the pseudo
header, of course), the result will be zero if the checksum was correct.
"tcp does not attempt to define what the user specifically does upon being
notified of pending
urgent data, but the general notion is that the receiving process will take
action to process
the urgent data quickly."
well in real life, urgent data is also referred to as out of band data. to
receive out of band
data through the socket interface (refer to [b] for more information about
sockets), you can
use the msg_oob flag on a recv call:
#ifdef _win32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#endif
/* ... */
return 0;
}
<---------------------------------- bits
------------------------------------->
___________________________________________________________________________
___
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20| ... | length *
8 |
|�����������������������|�����������������������|
������������������������������|
| type | length | data
|
|_______________________|_______________________|
______________________________|
the option is identified by its type (one byte), and the data field as well
as its length depend
completely on the option. the length field specifies the length of the
complete option in bytes.
two special options do not have a length or a data field:
no operation
+------+--------+-------------------------------------
+-------------------------------------------+
| kind | length | description | references
|
+------+--------+-------------------------------------
+-------------------------------------------+
| 0 | 1 | end of option list. | http://www.rfc-
editor.org/rfc/rfc793.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 1 | 1 | no operation. | http://www.rfc-
editor.org/rfc/rfc793.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 2 | 4 | maximum segment size. | http://www.rfc-
editor.org/rfc/rfc793.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 3 | 3 | window scale factor. | http://www.rfc-
editor.org/rfc/rfc1072.txt |
| | | | http://www.rfc-
editor.org/rfc/rfc1323.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 4 | 2 | sack permitted. | http://www.rfc-
editor.org/rfc/rfc2018.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 5 | - | sack. | http://www.rfc-
editor.org/rfc/rfc2018.txt |
| | | | http://www.rfc-
editor.org/rfc/rfc2883.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 6 | 6 | echo. | http://www.rfc-
editor.org/rfc/rfc1072.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 7 | 6 | echo reply. | http://www.rfc-
editor.org/rfc/rfc1072.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 8 | 10 | timestamp. | http://www.rfc-
editor.org/rfc/rfc1323.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 9 | 2 | partial order connection permitted. | http://www.rfc-
editor.org/rfc/rfc1693.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 10 | 3 | partial order service profile. | http://www.rfc-
editor.org/rfc/rfc1693.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 11 | 6 | cc, connection count. | http://www.rfc-
editor.org/rfc/rfc1644.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 12 | 6 | cc.new | http://www.rfc-
editor.org/rfc/rfc1644.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 13 | 6 | cc.echo | http://www.rfc-
editor.org/rfc/rfc1644.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 14 | 3 | tcp alternate checksum request. | http://www.rfc-
editor.org/rfc/rfc1146.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 15 | - | tcp alternate checksum data. | http://www.rfc-
editor.org/rfc/rfc1146.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 16 | - | skeeter. |
|
+------+--------+-------------------------------------
+-------------------------------------------+
| 17 | - | bubba. |
|
+------+--------+-------------------------------------
+-------------------------------------------+
| 18 | 3 | trailer checksum option. |
|
+------+--------+-------------------------------------
+-------------------------------------------+
| 19 | 18 | md5 signature. | http://www.rfc-
editor.org/rfc/rfc2385.txt |
+------+--------+-------------------------------------
+-------------------------------------------+
| 20 | - | scps capabilities. |
|
+------+--------+-------------------------------------
+-------------------------------------------+
| 21 | - | selective negative acknowledgements |
|
+------+--------+-------------------------------------
+-------------------------------------------+
| 22 | - | record boundaries. |
|
+------+--------+-------------------------------------
+-------------------------------------------+
| 23 | - | corruption experienced. |
|
+------+--------+-------------------------------------
+-------------------------------------------+
| 24 | - | snap. |
|
+------+--------+-------------------------------------
+-------------------------------------------+
| 26 | - | tcp compression filter. |
|
+------+--------+-------------------------------------
+-------------------------------------------+
___ ___________________________
(1.5) : ( establishing a connection )
��� ���������������������������
when two hosts want to establish a connection using tcp, they perform three
essential steps before
both of them think "well, now i am connected". this procedure is known as the
"three-way-handshake",
the most famous tcp buzzword ever. you might have already heard about it, read
about how
it works and you might already be about to leave out this part of the tutorial
because you have
read about the three way handshake a million times. however, i would really
recommend you to read
this part carefully to understand the concept completely.
you should definitely read [a] before continuing with this chapter.
_____ ____________________
{1.5.1} � { step one - request }
����� ��������������������
now we can have a closer look at the actual connection. the host that wants
to connect
(the client) sends a tcp segment to the server. this tcp segment contains a
valid source
and destination port number, a syn flag, no data and the isn.
what is the isn? it is an initial sequence number - a random number that is
chosen when the
connection is established. correct, the sequence number does not start with
0, it starts with
a random value. this random isn has to be subtracted from the sequence
number that is sent
with all the following segments to get the real byte position.
why is a random value chosen? this has basically just security purposes.
attacks like
spoofing or faking packets are close to impossible when you cannot calculate
a valid
sequence number - segments with invalid sequence numbers will be ignored by
the server.
____________________________________________________________________________
___________________
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|
26|27|28|29|30|31|32|
|�����������������������������������������������|
�����������������������������������������������|
| 49155 | 80
|
|_______________________________________________|
_______________________________________________|
|
����������������������������������������������������������������������������������
�������������|
| 1431655765 (random)
|
|
__________________________________________________________________________________
_____________|
|
����������������������������������������������������������������������������������
�������������|
| 0 (ignored, no ack flag set)
|
|
__________________________________________________________________________________
_____________|
|�����������|�����������������|�����������������|
�����������������������������������������������|
| 28 | 0 | 000010 (syn)* | 0 (ignored, no ack flag
set) |
|___________|_________________|_________________|
_______________________________________________|
|�����������������������������������������������|
�����������������������������������������������|
| checksum (too lazy to calculate) | 0 (ignored, no urg flag
set) |
|_______________________________________________|
_______________________________________________|
|�����������������������|�����������������������|
�����������������������������������������������|
| 2 (mss) | 4 | 1460 (standard mss)
|
|_______________________|_______________________|
_______________________________________________|
|�����������������������|
�����������������������������������������������������������������������|
| 0 (end of options) | 0 (padding 3 bytes)
|
|_______________________|
_______________________________________________________________________|
so what is happening? the client himself has registered the dynamic port
49155 and connects
to port 80 on the server - this is the beginning of a normal http request.
and what are the last two lines (the last two double words)? this is the mss
option sent with
the tcp header. as i told you in (1.1), the mss is exchanged upon connection
establishment.
the mss option is sent within segments that have the syn (synchronization,
sounds logical)
flag set.
the option itself is pretty simple. the type byte is 2, the length is 4
bytes and the word
that specifies the actual mss of the client is the last field of the option.
after the mss
option follows a complete double word full of zeros - one byte to specify
the end of the
option list and the remaining zeros are used for padding the tcp header
length up to a
multiple of 32 bit.
the offset field is set to 28 instead of the 20 bytes that the "usual" tcp
header contains
- because of the options.
_____ __________________
{1.5.2} � { step two - reply }
����� ������������������
when the server receives this segment, he has two options - tell the client
that he can connect
or tell him that he can't. the client cannot connect to a port that is not
registered on the
remote operating system - perhaps there is no http server running on the
box. in both cases, the
header would look similar, only the tcp flags would change. if the server is
willing to
establish a connection, he will send a segment with both a syn and an ack
flag - syn to signalize
that he is sending his own isn to be synchronized with the client and ack to
acknowledge the
isn that the client has sent. therefore, the acknowledgement number will
contain the isn of the
client plus 1. if, however, the server refuses a connection, he sets only
the rst flag and
sends a segment with any sequence number he wants. i think you can imagine
how the rst segment
looks like, so i will only show you how the reply would look like if a
connection will actually
be established. i will stick to the example in {1.5.1}, you can check back
with the numbers there
to see what happens:
____________________________________________________________________________
___________________
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|
26|27|28|29|30|31|32|
|�����������������������������������������������|
�����������������������������������������������|
| 80 | 49155
|
|_______________________________________________|
_______________________________________________|
|
����������������������������������������������������������������������������������
�������������|
| 1717986918 (random)
|
|
__________________________________________________________________________________
_____________|
|
����������������������������������������������������������������������������������
�������������|
| 1431655766 (ack: 1431655765 + 1)
|
|
__________________________________________________________________________________
_____________|
|�����������|�����������������|�����������������|
�����������������������������������������������|
| 28 | 0 | 010010 (a,s)* | 7300 (5 segments per
window.) |
|___________|_________________|_________________|
_______________________________________________|
|�����������������������������������������������|
�����������������������������������������������|
| checksum (too lazy to calculate) | 0 (ignored, no urg flag
set) |
|_______________________________________________|
_______________________________________________|
|�����������������������|�����������������������|
�����������������������������������������������|
| 2 (mss) | 4 | 1460 (standard mss)
|
|_______________________|_______________________|
_______________________________________________|
|�����������������������|
�����������������������������������������������������������������������|
| 0 (end of options) | 0 (padding 3 bytes)
|
|_______________________|
_______________________________________________________________________|
as the ack flag is set, the server also sends his window size. 5 * 1460 is
7300 which seemed
like a good window count for me. i have no idea if this is a realistic
number, but this is
just an example after all. due to the ack flag, as well, the server send the
appropriate
acknowledgement number that contains the client's isn (1431655765) plus one
(1431655766).
additionally, the server sends his own isn (1717986918).
of course, the destination port is now the port that was registered by the
client and the
server specifies his own port (80) as the source port. simple, right? i bet
you're still
with me.
_____ _________________________
{1.5.2} � { step three - connection }
����� �������������������������
it's almost done - the client sent a request to connect to the server and
the server sent a
valid reply, with a nice and correct sequence number, the correct
acknowledgement number and
both of them calculated the checksum correctly (not abig surprise, they got
algorithms which
perform these tasks for them.)
____________________________________________________________________________
___________________
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|
26|27|28|29|30|31|32|
|�����������������������������������������������|
�����������������������������������������������|
| 49155 | 80
|
|_______________________________________________|
_______________________________________________|
|
����������������������������������������������������������������������������������
�������������|
| 1431655766 (using the server's last acknowledgement number)
|
|
__________________________________________________________________________________
_____________|
|
����������������������������������������������������������������������������������
�������������|
| 1717986919 (ack: 1717986918 + 1)
|
|
__________________________________________________________________________________
_____________|
|�����������|�����������������|�����������������|
�����������������������������������������������|
| 20 | 0 | 010000 (ack)* | 7300 (5 segments per
window.) |
|___________|_________________|_________________|
_______________________________________________|
|�����������������������������������������������|
�����������������������������������������������|
| checksum (too lazy to calculate) | 0 (ignored, no urg flag
set) |
|_______________________________________________|
_______________________________________________|
this time we don't send any options: the offset field of the tcp header is
set to 20. you
might have noticed that the client uses the same window size as the server -
this is just
an example. when a connection is established, the smaller one of both window
advertisements
is used by both ends of the connection, similar to how the mss is handled.
those who are chronically pessimistic and those who use nmap might have
thought about how
the client can cancel the connection even at this point. yes indeed, the
client does not
have to send the final acknowledgement to establish the connection - he can
also send an
rst segment. sounds a bit strange, huh? one would think that the client
would not want to
cancel the connection he just tried to establish.
however, there are numerous reasons to cancel the connection at this point
of time:
now let's assume the server sent a wrong acknolwedgement number - what
sequence
number would be used for the rst segment? the sequence number that would
usually
follow or the wrong one that the server expects to receive? the wrong one.
we
have to use the sequence number that the server expects to receive because
he
would ignore the segment if the sequence number was not his previous ack
number.
furthermore, the client does not send an acknowledgement as no ack flag is
set.
as always, i am referring to the sample we used all the time - this is how
such
an rst segment sent by the client might look like:
____________________________________________________________________________
___________________
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|
26|27|28|29|30|31|32|
|�����������������������������������������������|
�����������������������������������������������|
| 49155 | 80
|
|_______________________________________________|
_______________________________________________|
|
����������������������������������������������������������������������������������
�������������|
| 1431655766 (using the server's last acknowledgement number, even if it was
wrong!) |
|
__________________________________________________________________________________
_____________|
|
����������������������������������������������������������������������������������
�������������|
| 0 (ignored, no ack flag set.)
|
|
__________________________________________________________________________________
_____________|
|�����������|�����������������|�����������������|
�����������������������������������������������|
| 20 | 0 | 000100 (rst)** | 0 (ignored, no ack flag
set) |
|___________|_________________|_________________|
_______________________________________________|
|�����������������������������������������������|
�����������������������������������������������|
| checksum (too lazy to calculate) | 0 (ignored, no urg flag
set) |
|_______________________________________________|
_______________________________________________|
so, i hope you're still with me, let's move on to the next chapter.
___ ______________________
(1.6) : ( closing a connection )
��� ����������������������
whereas establishing a connection takes 3 steps, closing a connection requires
4 steps. why does
it have to be so complicated? well, both sides can send and receive data at
the same time - this
means that both sides might be sending data when one side wants to close the
connection. thus,
both sides of the connection have to announce a closing of the connection
independantly as well.
in this chapter i will refer to the sample in (1.5), here are the sequence
numbers again so
you don't have to scroll up every time you need to check back. and believe me,
you should
check back and really understand what number is used or inreased when and how.
let's assume the client wants to disconnect - in this very case, he sends a
tcp segment that
contains the fin and the ack flag. this segment uses the client's isn as the
sequence number
and the server's isn as the acknowledgement number - pretty simple actually.
______________________________________________________________________________
_________________
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|
27|28|29|30|31|32|
|�����������������������������������������������|
�����������������������������������������������|
| 49155 | 80
|
|_______________________________________________|
_______________________________________________|
|
����������������������������������������������������������������������������������
�������������|
| 1431655765 (client isn)
|
|
__________________________________________________________________________________
_____________|
|
����������������������������������������������������������������������������������
�������������|
| 1717986918 (server isn)
|
|
__________________________________________________________________________________
_____________|
|�����������|�����������������|�����������������|
�����������������������������������������������|
| 20 | 0 | 010001 (a,f)* | 7300 (still receiving data)
|
|___________|_________________|_________________|
_______________________________________________|
|�����������������������������������������������|
�����������������������������������������������|
| checksum (too lazy to calculate) | 0 (ignored, no urg flag set)
|
|_______________________________________________|
_______________________________________________|
this is not too complicated. after the client has sent this segment, he does
not send any
more data and waits for the server to acknowledge the fin segment. if the
server does not
reply until the timer for this fin segment times out, the client sends it
again, though.
now the server will acknowledge this fin segment like any other segment.
the server uses his own isn as the sequence number, since this was the last
acknowledgement
number used by the client - he used it in his fin segment. tcp is very strict
here, a host
always has to use the sequence number that was "requested" by the previous
acknowledgement
number in a segment from the other side of the connection. furthermore, as we
send an
acknowledgement, the ack flag is set and he acknowledgement numer field
contains the client
isn plus one.
______________________________________________________________________________
_________________
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|
27|28|29|30|31|32|
|�����������������������������������������������|
�����������������������������������������������|
| 80 | 49155
|
|_______________________________________________|
_______________________________________________|
|
����������������������������������������������������������������������������������
�������������|
| 1717986918 (server isn - the value of the clients previous acknowledgement
number.) |
|
__________________________________________________________________________________
_____________|
|
����������������������������������������������������������������������������������
�������������|
| 1431655766 (client isn + 1)
|
|
__________________________________________________________________________________
_____________|
|�����������|�����������������|�����������������|
�����������������������������������������������|
| 20 | 0 | 010000 (ack)** | 0 (won't receive any more
data) |
|___________|_________________|_________________|
_______________________________________________|
|�����������������������������������������������|
�����������������������������������������������|
| checksum (too lazy to calculate) | 0 (ignored, no urg flag set)
|
|_______________________________________________|
_______________________________________________|
it is not a strict tcp rule that the window advertisement has to be zero in
this kind of
acknowledgement, but it seems logical to set it to zero as no more data is
expected to be
received.
now the server finishes sending his data to the client and then he performs
the same
procedure - but of course, the sequence number he uses for his fin segment is
his own
isn and so on. i don't think i have to explain this in detail.
now after each the client and the server (both sides of the connection) have
announced that
they want to close the connection, the connection is, well, closed. no more
data will
be sent and both sides forget about the synchronized data they had stored,
like the isn's,
the mss and any other stuff used during the data exchange.
_ _______________________
[2] :: [ advanced portscanning ]
� �����������������������
note - this chapter is not required for any part of this tutorial or any
tutorial that belongs
to my internetworking series. it is just for fun, if you know nmap and if you
want to know how
it works.
now as you have learned about tcp and pretty much all the important facts about
how it works,
it is nice to see that this knowledge is actually good for something. knowledge
about how
tcp initiates a connection is useful to understand the syn stealth scan that
nmap uses to
determine the open ports on a computer. make sure that you have read [a] as well
as [b]
and (1.5) before you read on, because i will refer to many things i explained in
these chapters.
___ _______________________
(2.1) : ( what is portscanning? )
��� �����������������������
portscanning is the process of determining what ports on a certain machine are
open and
which are closed, basically. some people will tell you that every attempt to
break into
a server starts with a portscan - because the portscan can tell you which
services are
running on the computer you are scanning. a service is basically just another
name for a
server application, like an ftp server listening on tcp port 21 or anything
else. these
server application provide services to the client and sometimes the client is
able to
abuse the services offered to him. more details about this would lead much too
far, so
let's concentrate on the portscan itself.
i will explain here what would probably called the "classic" portscan. this
method is
also known as a connect-portscan. this merely refers to the connect() call i
told you
about in [b]. a portscanner is basically a program that uses the connect()
call, trying
to connect to the computer that is being scanned on a wide range of possible
ports.
once the program can establish a connection on a certain port, the one who
uses the
scanner knows that the port is "open", meaning that the server accepts
connections on
this port. if it accepts connections on this port, there is a service running
and listening
on that port - and this service might be abused, giving a potential attacker
the oportunity
to gain access to the system. however - it is not as simple as that,
fortunately.
false = none;
true = 1;
if __name__ == '__main__':
sserv = sys.argv[1]
if (len(sys.argv)>3):
i1port = int(sys.argv[2]);
i2port = int(sys.argv[3]);
what is the problem with connect-portscanning? every time an open port is open
on the remote
machine, the application connects completely and disconnects again. of course,
it is not
only possible to log these scans on the server easiely, it is done by default
usually. since
a malicious hacker was really planning to compromise the server, he would not
want to get
logged and caught while he is just begging to prepare for an attack by
scanning the server ...
from his point of view, a much more stealthy method had to be invented ...
___ _______________________
(2.2) : ( nmap stealth scanning )
��� �����������������������
nmap is a portscanner with many more nice and interesting features. it was
made by the
good guys at http://www.insecure.org/ and was the first portscanner (as far as
i know)
that used the so-called syn stealth scan. syn sounds pretty familiar and with
the
background knowledge about tcp that you should have by now, you might have
already figured
how it works. anyhow, other methods have been developed by the nmap coders as
well to
perform stealthy scans and i will discuss the two of them that i consider
directly related
to the topic of this paper.
_____ _____________
{2.2.1} � { syn stealth }
����� �������������
pretty much the most famous stealth port scan. check back with (1.5), as
this scan
is based on the way in which a connection is established. you know, the
client sends
a syn packet to request that a connection is established and then the server
replies
with his own syn|ack segment to establish the connection or with an rst
segment to
reject the request.
the syn stealth scan is pretty simple - the portscanner sends the syn packet
and
waits for a reply. if an rst packet is returned, the port that is currently
being
probed is closed. now if a syn|ack packet is returned however, the client
already
knows that the port he is currently probing is open on the server. now
instead of
really establishing the connection like a connect-portscanner would do, nmap
immediately
sends an rst segment to tell the server that some critical error has occured
on the client side and that the connection will not be established.
this "failed" connection attempt is (or rather, was) not logged by most
servers.
this has changed most probably when you read this, as the syn stealth scan
has
become a pretty famous technique and is also used by other portscanners like
_____ _____________
{2.2.2} � { fin stealth }
����� �������������
the fin stealth scan is even more stealthy than syn scanning - the
portscanner never
attempts to conenct to the server at all. a fin scan uses a sheer fin
segment to
probe ports. what happens if a fin packet is sent to a closed port? i am
quoting
rfc 793 on page 64, as referred to in the nmap manual:
"[...] if the state is closed (i.e., tcb does not exist) then all data in
the incoming segment is discarded. an incoming segment containing a rst
is discarded. an incoming segment not containing a rst causes a rst to
be sent in response. [...]"
(http://www.rfc-editor.org/rfc/rfc793.txt)
so, an rst packet will be sent to the portscanner if the port is closed.
however, if
the port is open (in listen state) and a segment with only the fin flag set
is sent,
the packet will be ignored as stated on page 67 of the rfc 793:
"[...] fifth, if neither of the syn or rst bits is set then drop the
segment and return. [...]"
that's about it - send the raw fin segment. if an rst is returned, the port
is closed,
and if no reply is sent the port is probably open. how to find out if no
reply is
being sent? thats a bit tricky, but nmap certainly uses some decent timer.
there are two other related scanning methods used by nmap - the xmas tree
and the null
scan. those work like the fin stealth scan, but the xmas tree scan turns on
fin, urg
and psh while the null scan does not turn on any flag for this type of scan.
_ ____________________________
[3] :: [ the user datagram protocol ]
� ����������������������������
relax, udp is completely different. udp was invented in rfc 768 and is a non-
connection
oriented transport protocol. neither does it offer any mechanisms to ensure that
the
data arrives at the remote end or any other smart algorithms. udp has often been
called
an unreliable protocol and sometimes it is referred to as an insecure protocol.
in fact, udp is still a useful protocol for applications that do not have to
transfer
huge ammounts of data. a simple client - server application usually wants to
avoid the
complex mechanism to establish a connection and to acknowledge every packet when
only
2 or 3 packets have to be sent - udp is perfect for this kind of simple data
exchange.
an example: back when icq was still a simple instant messenger, it used udp to
communicate
with the icq server.
___ ________________
(3.1) : ( the udp header )
��� ����������������
this time we will start directly with the header as an udp implementation does
not
utilize any further algorithms or techniques. udp packets are just being sent,
there
is nothing else to do.
<-------------------------------------------- bits
-------------------------------------------->
______________________________________________________________________________
_________________
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|
27|28|29|30|31|32|
|�����������������������������������������������|
�����������������������������������������������|
| source port | destination port
|
|_______________________________________________|
_______________________________________________|
|�����������������������������������������������|
�����������������������������������������������|
| length | checksum
|
|_______________________________________________|
_______________________________________________|
|
##################################################################################
#############|
|###########################################[ data ]
############################################|
|
##################################################################################
#############|
������������������������������������������������������������������������������
�����������������
(figure 3.1.1: the tcp header format as explained in rfc 793, part 3.1:
http://www.rfc-editor.org/rfc/rfc768.txt)
as always, i will explain all the fields of the udp header in detail now.
[ a pseudo header ]
[ the udp header ]
[ the data ]
this pseudo header is never sent with the datagram, i have to stress this
again and again.
it is never being received and it is only used once by the sender to
calculate the checksum.
it contains information from the ip header as well, and for udp it looks
like this:
____________________________________________________________________________
___________________
|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|
26|27|28|29|30|31|32|
|
����������������������������������������������������������������������������������
�������������|
| source ip address
|
|
__________________________________________________________________________________
_____________|
|
����������������������������������������������������������������������������������
�������������|
| destination ip address
|
|
__________________________________________________________________________________
_____________|
|�����������������������|�����������������������|
�����������������������������������������������|
| 0 | 17 | udp datagram length
|
|_______________________|_______________________|
_______________________________________________|
if you compare figure 3.1.04.1 with figure 1.4.09.1, you certainly notice
that they look
quite similar. indeed, transport layer pseudo headers always work the same
way: they contain
the source and the destination ip address, then a zero-byte followed by one
byte that
contains the protocol number for the transport layer protocol that is being
used. the word
that follows is always the length of the complete packet that is supposed to
be sent.
so, obviously, the field which is set to 17 actually represents the udp
protocol number.
___ ______________
(3.2) : ( udp spoofing )
��� ��������������
tcp - flashback: you might not have thought about it yet, but the sequence and
acknowledgement numbers in tcp were added on purpose and not just to annoy
people who are creating a tcp implementation. the sequence number is chosen
randomly once a connection is established and tcp segments that contain an
invalid sequence number are ignored. this is actually a quite secure
mechanism,
and additional to that, tcp is connection-oriented. the three-way-handshake
requires both partners of the connection to identify themselves by
acknowledging
a segment they received from the other side. it is almost impossible to
spoof such a connection - at least tcp is quite secure.
however, spoofing udp packets is usually not that simple - as the applications
that use udp usually implement several security measures within the
application
layer which makes it much more complicated to attack a specific service.
udp might be insecure, but ip itself is insecure as well - that does not count
until you see the whole picture, aka all layers combined.
i won't present a tacky udp spoofing example here, that should be left for the
tutorial about raw sockets that should follow soon.
_ _______
[a] :: [ ports ]
� �������
ports are an essential concept of transport layer protocols. each side of the
connection registers
a port number with the operating system. this port is used as the virtual
interface for a computer
program to receive data from the network.
the port number is actually just a number - when registering a port, nothing
extraordinary happens.
the application that registers a port basically tells your os that it wants to
register this
specific port and the os assigns this port number to the process that
represents the running
application. when the port is assigned, nothing more happens - the os only
remembers that the
process id of this application belongs to a certain port number. thus, the port
number is just
an identifier.
when the operating system receives data from the physical network layer, it
parses the transport
layer protocol header and looks for a field that contains the target port. now
the os knows which
application had registered this port and forwards all incomming data that is
sent to this port to the
appropriate application. this functionality is implemented by the socket
interface which will be
explained in [b].
now, as you know what a port actually is and represents, let's get into detail.
a port number is
a 16 bit word, the biggest possible port number therefor is 0xffff = 65535.
however, port numbers
are not used randomly, they have been devided into 3 groups with different
meanings and tasks:
___ __________________
(a-1) : ( well-known ports )
��� ������������������
the well-known ports range from 0 to 1023. these ports are used for well known
services such
as http and ftp. the internet assigned numbers authority (iana) administrates
this range of
ports and is responsible for new services to be registered and any other
changes to the
public standard of the well knonw ports.
___ __________________
(a-2) : ( registered ports )
��� ������������������
registered ports are used for services that normally use the respective
service. for instance,
the port 8080 is officially an alternative http port and is usually used by
proxies and also
by some unofficial or private http servers that want to get around port
restrictions set by
their isp. the registered ports range from 1024 to 49151.
___ _______________
(a-3) : ( dynamic ports )
��� ���������������
the dynamic or private ports are actually used randomly. these ports can be
used by any
application for any purpose - dynamic ports can be used for ipc (inter-process
comunication)
as well as for a client application that connects to a well known service.
however, no
well known service has registered a dynamic port - actually, no dynamic port
may be registered
to any service as they are, by definition, dynamic. obviously, the dynamic
ports range from
49152 to 65535.
_ _________
[b] :: [ sockets ]
� ���������
the word "socket" is often used like a buzzword, even by programmers and people
who should know
what they are talking about - ask them what a socket is, and many of them will
not be able to
give you a correct answer. the first thing to keep in mind is that a socket is
merely an abstract
idea, just like a port. the socket is not some sort of object or device.
the socket can be described as the abstract idea of one side of a connection.
the virtual socket
interface has to provide mechanisms to register a port number with the os, to
send and receive
data, and so forth. please read [a] before you go on in order to understand the
concept of
registering and using a port number.
the core socket interface is a set of functions that are provided by every
operating system
to allow programmers to develop platform independant networking code.
the function that has to be called in order to create a socket is the socket()
function, which
is usually linked to an api routine implemented by the operating system. as i
already said,
a socket is an abstract interface. therefore, the function does not return any
object or
structure but simply an integer number. this integer number is the socket
identifier.
this identifier is actually derived from the ip address of the computer that
the socket is
created on and the port number that belongs to it. as both the ip address of a
certain host
and the port number of a service are always unique, the socket identifier
itself is unique
for each socket object. thus, it provides an easy and yet clean way to wrap the
complex
mechanisms behind tcp/ip.
as this is not a socket tutorial for c coders, i will leave out code samples
and explanations
of the socket interface api. perhaps this will be part of a socket tutorial
that might follow
in this series.
_ ____________
[4] :: [ last words ]
� ������������
well, this is the second part of my series, looks like i will really write more
of these.
i am definitely planning to publish one about raw sockets (especially in
windows 2000
environments) and about ipv6. this tutorial probably contains the basic
knowledge required
to understand most of the other topics that might follow and therefore i need
feedback.
i had the impression that part 1 was quite ok, and i hope that this one helped
some people
as well. anyway, just tell me what you think and also give me advice if you
think i could
formulate this or that part in a better way.
for in time, you know what counts: always the real thing.
yours, rattlesnake@box.sk