Sie sind auf Seite 1von 38

internetworking part 2 - the transport layer

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[ copyright (c) 2003 by rattle ]


[ http://www.awarenetwork.org/ ]

__________
[ 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.

i will try to express everything as simply as possible and as detailed as


necessary,
and i just hope you will enjoy it. perhaps it helps you understand the things
that i
did not understand when reading the first tutorials about networking protocols
at ease.
as always, the appendixes are important. i would definitely recommend to read
them if
you are not sure that you know everything about ports and sockets. almost no
knowledge
is required to read [a], some coding background could be useful for [b] but is
not
necessary. however, both provide an important background knowledge for many
parts of
this paper. have a look at least.

_ ___________________________________
[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 ...)

furthermore, tcp is "connection-oriented". while ip sends raw packets from one


router to
the next one, tcp wants to exchange data a bit more organized and in this very
order:

1.) establish a connection


2.) send and exchange data
3.) close connection

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.

sure, i am exaggerating here, but it is obvious that finding a suitable way to


provide
connection-oriented and safe data exchange is not easy if all you can rely on is
ip.

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:

1518-18-20-20 = 1460 byte

_____________________________________________________________________________
______
|
|
| 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:

1.) host a connects, sends his mss


2.) host b accepts the request, sends his mss
3.) both of them compare their own mss to the one of the remote side
and use the smaller mss for their segments.

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.

after a segment has been sent to its destination, a retransmission timer is


started
at the sender's end. if the timer exceeds before an acknowledgement for the
segment
reaches the sender, the segment is sent again. on the other hand, delivery
might
be successful and an acknowledgement reaches the sender before the timer
exceeds
- in this case, the timer stops and the transmission of the segment was
successful.

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

calculation of the retransmission timer's timeout value is task of tcp


implementations
and you don't necessarily need to know about it for an understanding of what
will
follow.

_____ ______________________
{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.

whenever an acknowledgement for a segment reaches the sender before the


appropriate timer exceeds, tcp measures the time that has passed instead of
the calculated timeout. this so-called sample round trip time (srtt) is used
to recalculate the rtt:

rtt = (alpha * rtt) + ((1 - alpha) * srtt)

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:

rto = rtt + (4 * mdev)

mdev represents the average absolute error - we allow the acknowledgement to

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:

mdev = (betha * mdev) + ((1 - betha) * |rtt - srtt|)

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":

<---------------------------- segments ------------------------------->


_________________________________________________
| |
| |
|_________________________________________________|____________________
| | | | | | | | | | |����|����|����|
| 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 |�11�|�12�|�13�| ...
| | | | | | | | | | |����|����|����|
|�������������������������������������������������|��������������������
| initial window |
|_________________________________________________|

(figure 1.3.1: the initial tcp 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:

<---------------------------- segments ------------------------------->


..........._________________________________________________
: | |
: | |
:_________|_________________________________________________|__________
|####|####| | | | | | | | | | |����|
|#01#|#02#| 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |�13�| ...
|####|####| | | | | | | | | | |����|
:���������|�������������������������������������������������|����������
: | window slides ----> |
:.........|_________________________________________________|

(figure 1.3.2: the sliding tcp window)


this sliding window in our example has a length of 10 segments - but in fact,
the
window size is variable. this has numerous advantages:

- 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.

______ ______ _____________


{1.4.01} � {16 bit} � { source port }
������ ������ �������������
the source port is the port that the sender of the respective segment uses
for this
tcp connection. please refer to [a] for an explanation of all the different
ports
and of all kinds of ports.

______ ______ __________________


{1.4.02} � {16 bit} � { destination port }
������ ������ ������������������
the destination port. obviously, this port is the port used by the remote
host
for this particular tcp connection. again, refer to [a] for more info about
ports.

______ ______ _________________


{1.4.03} � {32 bit} � { sequence number }
������ ������ �����������������
tcp segments will not reach their destination in the same order that they
were sent in,
some segments might take longer to be delivered and some of them will find a
faster way,
that depends on ip again. therefore, the sender uses a sequence number to
identify every
segment - the sequence number specifies the position of the data sent with
the respective
segment relative to the complete stream of data. during the data exchange,
the sequence
number is always increased by the number of bytes that have been sent
already. once again,
remember that the sequence number refers to the number of bytes and not to
the number of
segments that have already been sent.

in fact, the sequence number is used for identifcation purposes - the


sequence number is
always a unique value, and the receiver will only accept and interpret
segments that use
the sequence number he expects to receive. for example, the sequence number
is also used
and continuously increased when a connection is established (and when it is
canceled),
although no data is being sent at that point of time.

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 sender will receiver an acknowledgement segment by the receiver which


contains a
complete tcp header as well, but he ignores the sequence number as it is not
of any
interest for him. instead, the sender only uses the acknowledgement number
in this
acknowledgement segment to determine what segments have already been
delivered
successfully: refer to {1.4.4}.

______ ______ ________________________


{1.4.04} � {32 bit} � { acknowledgement number }
������ ������ ������������������������
the acknowledgement number is used to send the acknowledgement for a
received segment,
refer to (1.2). this number always represents the next segment that is
expected to be
received - therefore, it is the next sequence used by the sender. if the
receiver receives
a segment with the sequence number x, it sends an acknowledgement with an
acknowledgement
number of (x+1) to tell the sender what segment is expected to be received
now.

1.) receive data segment from sender with sequence number x


2.) send acknowledgement segment to sender with acknowledgement number
(x+1)
3.) receive data segment from sender with sequence number (x+1)
4.) ...

the acknowledgement number is closely linked to the sequence number as you


might already
have figured. the acknowledgement number always contains the sequence number
that the
receiver expects to receive next and therefore, the acknowledgement number,
as well, is
part of the tcp identification mechanism.

______ ______ ________


{1.4.05} � { 4 bit} � { offset }
������ ������ ��������
the offset is merely the length of the tcp header, which is not always the
same due to the
options field. the name offset was chosen because the data begins at this
offset, relative
to the position of the header.

______ ______ __________


{1.4.06} � { 6 bit} � { reserved }
������ ������ ����������
oh how i hate reserved fields. reserved fields are never used and they will
never be used
for future implementations. it has never ever happened! oh well anyway, the
reserved field
within the tcp header contains, well, nothing. it is currently being ignored
and has no
sense at all.

______ ______ _______


{1.4.07} � { 6 bit} � { flags }
������ ������ �������
the tcp flags are used to represent the purpose of a particular segment.

<----------------------- bits ---------------------->


_____________________________________________________
... | 11 | 12 | 13 | 14 | 15 | 16 | ...
�����|������|������|������|������|������|������|�����
... | urg | ack | psh | rst | syn | fin | ...
_____|______|______|______|______|______|______|_____

(figure 1.4.07.1: tcp flags)

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:

#define urg 0x20


#define ack 0x10
#define psh 0x08
#define rst 0x04
#define syn 0x02
#define fin 0x01

___________________________________________________________________________
________
|
|
| 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.
|
|
__________________________________________________________________________________
_|

______ ______ ______________________


{1.4.08} � {16 bit} � { window advertisement }
������ ������ ����������������������
make sure you have read (1.3) to understand this. this field of the tcp
header contains the
number of bytes that the receiver is willing to receive. it is not the
number of segments
within the window, it is actually the number of bytes. therefore, if the
receiver advertises
a window size of 2400 and the mss that the two hosts use is 380 (one segment
has a size of
400, mss plus the header length of 20) then the window has a size of 6
segments that are
sent simultaneously. if the receiver's window advertisement was only 2300,
the sender's window
would have a size of 6 segments as well, though - the last segment, however,
would not contain
380 but 280 bytes.

the window advertisement field is only evaluated by the sender when he


receives an
acknowledgement (a segment with the ack flag set).

______ ______ __________


{1.4.09} � {16 bit} � { checksum }
������ ������ ����������
calculating checksums, always the same pain in the ass. the tcp checksum,
like probably all
checksums, is computed as the 16-bit one's complement of the one's
complement sum of something.
however, tcp is not like ip or icmp in this case, because it does not
calculate the checksum
of its own header or its data, but it calculates the checksum of a buffer
that contains:

[ 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
|
|_______________________|_______________________|
_______________________________________________|

(figure 1.4.09.1: the tcp pseudo header)

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.

the field that is set to 0 is not declared as a reserved field, it just


contains zeros
to make the pseudo header length a multiple of two bytes.

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.

______ ______ ________________


{1.4.10} � {16 bit} � { urgent pointer }
������ ������ ����������������
if the urg flag is set, this field points to the sequence number of the last
byte in a sequence
of "urgent" data. although the urgent mechanism may be used for any
application, it is normally
used to send 'interrupt'- type commands to a telnet program. here's what
[rfc793] says about the
urgent pointer:

"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

int main(int argc, char** argv)


{
sockaddr_in remote = {0};
int sock = socket(af_inet,sock_stream,ipproto_tcp);

/* ... */

char surgent[42] = {0}; // buffer for urgent data


recv(sock,surgent,42,msg_oob); // receive out of band, aka urgent data

if (*surgent) printf("very urgent: %s", surgent);

return 0;
}

______ ___________ _____________________


{1.4.11} � {0-44 bytes } � { options and padding }
������ ����������� ���������������������
options are a very famous concept to allow improvement, enhancement or an
extension of an existing
protocol. i like them much more than "reserved" fields, they are more
flexible and dynamic. think
of an option as of a little, additional header that is added to the tcp
header at the end - it
includes additional information of any kind. an option has always the same
format:

<---------------------------------- 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
|
|_______________________|_______________________|
______________________________|

(figure 1.4.11.1: a general tcp option)

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:

end of option list:


___________
____________
the end of option list "option" is actually just one byte |01|02|03|
04|05|06|07|08|
byte that is set to 0. think of it as of a terminating |
�����������������������|
null character. it does nothing but specifying the end | type = 0
|
of all options, it is always the last option when options |
_______________________|
are sent.

no operation

this option, similar to the end of option list option does


_______________________
not have a length or a data field. it is one single byte |01|02|03|
04|05|06|07|08|
that is set to 1. usually, this option is used for padding |
�����������������������|
the next option up to the next word boundary, but as a | type = 1
|
sender does not have to use this option, receivers must be |
_______________________|
prepared to process options even if they do not begin on a
word boundary.

here is a complete list of all options:

+------+--------+-------------------------------------
+-------------------------------------------+
| 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.

so, this is a sample of what the client might send:

____________________________________________________________________________
___________________
|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)
|
|_______________________|
_______________________________________________________________________|

* the flags field is set to 2. this is 000010


in binary, which means the syn flag is set.

(figure 1.5.1.1: tcp connection request; client)

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)
|
|_______________________|
_______________________________________________________________________|

* s stands for syn and a stands for ack:


the flags field is set to 18. this is 010010
in binary, which means the syn and the ack
flags are set.

(figure 1.5.2.1: tcp connection reply; server)

i think it is pretty obvious what's going on - as this is a segment with a


syn flag set, the
mss option is sent again and to keep this as simple as even possible, the
server uses the
same mss as the client :-).

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.)

now it is called a three-way-handshake and the client has to send a final


segment that
actually establishes the connection. since everything has been synchronized,
the syn flag
will not be set in this segment. however, as the server sent his isn, the
client needs to
acknowledge it now. so, you guessed it, only the ack flag is set.

the acknowledgement number is not difficult to guess, it is the server's isn


plus one.
the server also sent the correct acknowledgement for the client's isn and
this way he told
the client what sequence number has to be sent next. well, as the ack flag
is set, the
client will also send his own window advertisement this time, but there is
not much to
wonder about this time. this is how the last segment, referring to our
example, would 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)
|
|
__________________________________________________________________________________
_____________|
|
����������������������������������������������������������������������������������
�������������|
| 1717986919 (ack: 1717986918 + 1)
|
|
__________________________________________________________________________________
_____________|
|�����������|�����������������|�����������������|
�����������������������������������������������|
| 20 | 0 | 010000 (ack)* | 7300 (5 segments per
window.) |
|___________|_________________|_________________|
_______________________________________________|
|�����������������������������������������������|
�����������������������������������������������|
| checksum (too lazy to calculate) | 0 (ignored, no urg flag
set) |
|_______________________________________________|
_______________________________________________|

* the flags field is set to 16. this is 010000


in binary, which means the ack flag is set.

(figure 1.5.3.1: tcp connection established: final segment of three-way-


handshake)

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:

- the client application might have crashed


- the server's reply can be invalid
- the server's reply might contain specifications that
don't appeal to the client.

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) |
|_______________________________________________|
_______________________________________________|

** the flags field is set to 4. this is 000100


in binary, which means the rst flag is set.

(figure 1.5.3.2: tcp connection reset: final segment of three-way-handshake)

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.

however, it is not as complicated as you might think. although 4 steps are


required to
completely close the connection, the complete procedure is not as tricky as
establishing a
connection - each host performs only 2 steps and both hosts basically do the
same.

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.

client isn: 1431655765 = 0x55555555


server isn: 1717986918 = 0x66666666

(i bet you didn't figure. bad coder humor i guess ...)


one of the two hosts has to initiate the process once he does not want to send
any more data.
this is important to understand the terminology used by tcp - closing means
that no more data
is sent. if the client closes the connection, he declares that he will not, by
no means, send
any more data to the server. the client still has to receive data sent from
the server - until
the server himself closes the connection. don't worry, here are the details:

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)
|
|_______________________________________________|
_______________________________________________|

* f stands for fin, a stands for ack.


the flags field is set to 17, this is 010001
in binary: the ack and the fin flag are set.

(figure 1.6.1: client closes the connection)

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)
|
|_______________________________________________|
_______________________________________________|

** the flags field is set to 16, this is 010000


in binary: the ack flag is set.

(figure 1.6.2: server acknowledges fin segment from client)

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.

this is a sample connect() portscanner in python - it is a simple and single-


threaded sample,
but i'm sure it would work. i would give you a sample in c, but that would be
much more work
as i have to do a lot of error checking and other stuff myself in c. check
http://www.pyton.org/ if you want to know more about this great language ...

from socket import *


import sys

false = none;
true = 1;

def scanport(sserver, iport):


breturn = true
s = socket(af_inet,sock_stream)
try: s.connect((str(sserver),int(iport)))
except: breturn = false
if (breturn): s.close();
del s; return breturn;

if __name__ == '__main__':

i1port = 1; # lowest valid port


i2port = 2**16; # highest valid port: 16 bits

sserv = sys.argv[1]

if (len(sys.argv)>3):
i1port = int(sys.argv[2]);
i2port = int(sys.argv[3]);

for i in range(i1port, i2port+1):


if (scanport(sserv,i)): print "open port:", i

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

retina from eeye (http://www.eeye.com/).

_____ _____________
{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.

______ ______ _____________


{3.1.01} � {16 bit} � { source port }
������ ������ �������������
the source port is the port that the sender of the respective segment uses
for this
tcp connection. please refer to [a] for an explanation of all the different
ports
and of all kinds of ports. (right, this is the same concept tcp uses.)

______ ______ __________________


{3.1.02} � {16 bit} � { destination port }
������ ������ ������������������
the destination port is the port used by the remote host for this data
exchange. again,
refer to [a] for more info about ports.

______ ______ ________


{3.1.03} � {16 bit} � { length }
������ ������ ��������
the length field contains the complete length of the udp datagram, including
the header
and the data, of course. this value will also be based on the mtu of the
respective
network, if larger datagrams are being sent at all.

______ ______ __________


{3.1.04} � {16 bit} � { checksum }
������ ������ ����������
i hope you still remember the tcp header, otherwise please check out (1.4)
before you read
this or at least have a look at {1.4.09} that explains how the tcp checksum
us calculated.
why am i referring to the tcp header or its checksum? because calculating
the udp checksum
is basically the same procedure. before the checksum is calculated, the
checksum field of
the udp header is set to zero. then a pseudo header is created and copied to
a buffer along
with the real udp header and the data. the buffer then looks like this:

[ 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
|
|_______________________|_______________________|
_______________________________________________|

(figure 3.1.04.1: the udp pseudo header)

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.

the field that is set to 0 is not declared as a reserved field, it just


contains zeros
to make the pseudo header length a multiple of two bytes.

anyhow, the checksum field is optional. if the sender of an udp datagram


sets the checksum
field of the udp header to zero, it will just be ignored by the receiver.
this is
actually a good argument to call udp an insecure protocol, in my opinion.

___ ______________
(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.

comparing udp to tcp: there is no sequence number. there is no


acknowledgement.
there is nothing in udp to check whether a packet is valid at all. this
allows spoofing and faking udp datagrams - one could think about a million
things that could be done.

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

Das könnte Ihnen auch gefallen