TCP Header etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
TCP Header etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

18 Aralık 2020 Cuma

TCP Header - SACK Permitted Alanı

Giriş
Bu yazıdaki içeriği uzun zaman önce not almıştım. Anladığım şekliyle tekrar kaleme almaya çalıştım. Konunu uzmanı değilim, böyle bir iddiam yok, yazıda eksikler olabilir.
 
Bu yazıda kavramlar var, her TCP gerçekleştirimi buradaki olmak zorunda değil. 

Acknowledgment Nedir?
Acknowledgment, ARQ (Automatic Repeat Request) kavramı ile ilgili. ARQ güvenilir (reliable) iletişim için vardır. ACK gelmeyen paketleri tekrar gönderir.

Not : ARQ TCP seviyesinde zaten var, ancak daha alta seviyelerde de uygulanabiliyor. Örneğin Mobile Ad hoc Network (Manet) sistemlerinde TCP'nin getirdiği maliyet fazla olduğu için Layer 2 (MAC) seviyesinde de uygulanabiliyor.

TCP Hangi Acknowledgement Yöntemini Kullanır
TCP "Cumulative Positive Acknowledgements" yöntemini kullanır. Açıklaması şöyle
Each TCP segment contains the sequence number of the next byte that the sender of the acknowledgement expects to receive from the remote host. 
Bu yöntemde alan taraf bir sonraki beklediği mesaj numarasını gönderir. Eğer bir sonraki beklenen mesaj gelmezse sürekli aynı numarayı göndererek "go-back-n" denilen davranışı istediğini belirtir. Şeklen şöyle. Burada 123 numaralı paket kaybolduğu için alan taraf 3 tane Cumulative Positive ACK gönderiyor. 123'ten sonra gelen 127,129,131 numaralı paketler için Cumulative Positive ACK gönderilemiyor, dolayısıyla gönderen taraf ta bu paketleri kendi Windows'undan çıkartamıyor

Ancak bu yöntem verimli değil. Açıklaması şöyle. Bu yüzden ilave olarak Selective Acknowledgement (SACK) yöntemi de geliştirilmiş.
The default go-back-n retransmission strategy used by TCP has the advantage of being simple to implement, in particular on the receiver side, but when there are losses, a go-back-n strategy provides a lower performance than a selective repeat strategy. 
SACK mesajların geldiğini bloklar/aralıklar şeklinde karşı tarafa bildirir. Ancak SACK kullanımının olup olmayacağına dair her iki tarafın da evet demesi gerekir.

SACK'e geçmeden önce bir küçük iyileştirme daha yapılmış. Buna "TCP fast retransmit heuristic" deniliyor. Şeklen şöyle Burada yine 3 tane ACK = 123 gönderiliyor ancak 127,129,131 numaralı mesajlar da alındığı için en sonunda ACK = 133 gönderiliyor.
Açıklaması şöyle. Yani dizideki bir mesaj kaybolur ancak dizinin gerisi düzgün gelirse (isolated loss), sorun yok fakat durum bu değilse yine problem var.
The fast retransmit heuristic improves the TCP performance provided that isolated segments are lost and the current window is large enough to allow the sender to send three duplicate acknowledgements.
When losses are not isolated or when the windows are small, the performance of the fast retransmit heuristic decreases. In such environments, it is necessary to allow a TCP sender to use a selective repeat strategy instead of the default go-back-n strategy.
Selective Acknowledgement (SACK) Kullanma Kararı Ne Zaman Verilir
SACK kullanılmasına izin verilip verilmediği yani TCP zarfındaki "SACK Permitted" değeri SYN aşamasında gönderilir. Her iki taraf SACK kullanıp kullanılmayacağını söyler. Açıklaması şöyle.
The SACK option is negotiated between the TCP endpoints, and is only used if support is advertised by both sides of a connection.
Daha detaylı açıklama şöyle.
Selective Acknowledgment (SACK) TCP was another TCP proposal in 1996, in RFC 2018. The earlier variants 8f TCP, even back to Tahoe, implement a cumulative acknowledgment scheme where a lost packet results in duplicate ACKs for each subsequently received packet. Relying purely on the cumulative acknowledgment scheme can lead to inefficiencies when packets are lost. An example of this is a case where 10,000 bytes are sent in 10 different TCP packets, and the first packet is lost during transmission. Using cumulative acknowledgment scheme, the receiver cannot say that it received the bytes 1,000 to 9,999 successfully, and only failed to receive the first packet, containing bytes 0 to 999. Thus the sender may then have to resend all 10,000 bytes.
Selective Acknowledgement (SACK) Yapısı Nasıldır
Yapısı şöyledir.
                     +--------+--------+
                     | Kind=5 | Length |
   +--------+--------+--------+--------+
   |      Left Edge of 1st Block       |
   +--------+--------+--------+--------+
   |      Right Edge of 1st Block      |
   +--------+--------+--------+--------+
   |                                   |
   /            . . .                  /
   |                                   |
   +--------+--------+--------+--------+
   |      Left Edge of nth Block       |
   +--------+--------+--------+--------+
   |      Right Edge of nth Block      |
   +--------+--------+--------+--------+
Örnek
İletişim esnasında şu paketler gelmiş olsun.
0 - 500, 900 - 1100 ve 1300 - 2000 ?
Paketlerin sırasının bozuk olması SACK gönderilmesine sebep olur. Gönderilen SACK şöyledir.
TCP ACK - 501 (in TCP header, not in SACK Option)
TCP SACK - 1st block Left Edge  - 900
TCP SACK - 1st block Right Edge - 1100
TCP SACK - 2nd block Left Edge  - 1300
TCP SACK - 2nd block Right Edge - 2000
(all in the same Segment)
Örnek
Şeklen şöyle. Burada 123 numaralı paket kaybolduğu için alan taraf 3 tane Cumulative Positive ACK gönderiyor. 123'ten sonra gelen 127,129,131 numaralı paketler içinse Selective ACK gönderiliyor. 




13 Mart 2019 Çarşamba

TCP Header - RST (Reset) Flag

Giriş
RST (Reset) Flag -  1 bit büyüklüğündedir. Açıklaması şöyle
Connection reset.
Açıklaması şöyle.
"Connection reset by peer" is the TCP/IP equivalent of slamming the phone back on the hook. It's more polite than merely not replying, leaving one hanging. But it's not the FIN-ACK expected of the truly polite TCP/IP converseur.
Bağlantıyı hemen kapatmak için gönderilirTCP Handshake yazısına da bakabilirsiniz.

Kod İle Göndermek
Kod ile bu bayrağın atandığı bir paket göndermek mümkün. Açıklaması şöyle. SO_LINGER değerine 0 verilir ve socket için close() çağrısı yapılır.
Again, according to "UNIX Network Programming" third edition page 202-203, setting SO_LINGER with timeout 0 prior to calling close() will cause the normal termination sequence not to be initiated.

Instead, the peer setting this option and calling close() will send a RST (connection reset) which indicates an error condition and this is how it will be perceived at the other end. You will typically see errors like "Connection reset by peer".

Therefore, in the normal situation it is a really bad idea to set SO_LINGER with timeout 0 prior to calling  close() – from now on called abortive close – in a server application.

However, certain situation warrants doing so anyway:

- If the a client of your server application misbehaves (times out, returns invalid data, etc.) an abortive close makes sense to avoid being stuck in CLOSE_WAIT or ending up in the TIME_WAIT state.

- If you must restart your server application which currently has thousands of client connections you might consider setting this socket option to avoid thousands of server sockets in TIME_WAIT (when calling close() from the server end) as this might prevent the server from getting available ports for new client connections after being restarted.

- On page 202 in the aforementioned book it specifically says: "There are certain circumstances which warrant using this feature to send an abortive close. One example is an RS-232 terminal server, which might hang forever in CLOSE_WAIT trying to deliver data to a stuck terminal port, but would properly reset the stuck port if it got an RST to discard the pending data."

2 Ocak 2019 Çarşamba

TCP Header - Sequence Number Alanı

Giriş
32 bit uzunluğundadır. Açıklaması şöyle.
Represents either (if the SYN bit is set)  the initial sequence number or (if the SYN bit is not set) the sequence number of the current packet. 
Bu alanla ilgili açıklama şöyle. Yani ilk başlangıç değeri tam random olmasa bile tahmin etmesi zor bir değerdir.
The first standard specifying modern TCP is RFC793 from 1981 (with predecessors dating back to 1974), which says about initial sequence number selection
...
So they recognized that the sequence number has to be relatively unique, to avoid accidental collision between separate sessions. It didn't, however, consider deliberate attack.

Possible attacks against TCP sequence numbers were first described in 1985, and there were various vendor-specific fixes for it. Finally in 1996, RFC1948 standardized one fix, which uses a cryptographic hash of ports, addresses and secret key to decide the initial sequence number.

This is still the method that is used in e.g. Linux kernel secure_tcp_seq. So it is not really random (which would risk random collisions), but just difficult to predict without knowing the secret key (net_secret in Linux kernel).
Birçok kaynakta aşağıdaki alıntı gibi bu alanın rastgele seçildiği söyleniyor. Ancak rastgele değildir.
The initial sequence number is randomly selected to avoid connection hijacking. Without randomly selecting the initial sequence number, this number would be easily guessable, allowing an attacker to blindly send a sequences of packets that the receiver would believe to come from a different IP address.
Wireshark
Wireshark gösterim için TCP Sequence Number değeri yerine kendisinin ürettiği bir sayı kullanıyor. Bu özellik "Edit > Preferences > Protocols > TCP" penceresindeki "Relative sequence numbers" seçeneği ile açılıp kapatılabilir.

Gerçek TCP
Gerçek TCP'de şöyle çalışıyor.
Paket 1 için Seq # 1 olsun. Payload 25 olsun
Paket 2 için Seq # 26 olur. Payload 10 olsun
Paket 3 için Seq # 36 olur.
Yani bir sonraki sequence sayısı paketteki sayı + byte cinsinden payload büyüklüğü olarak hesaplanır.





5 Aralık 2017 Salı

TCP Header

Session ve Flow Farkı
Açıklaması şöyle.
Flow kavramsal olarak IP + port gibi düşünülebilir.

Session ise TCP'nin çalışması için gereken handshake, acknowledge vs. gibi mekanizmaların tamamı gibi düşünülebilir.

TCP Handshake yazısına bakabilirsiniz. TCP sıralamayı korumak zorunda olduğu için, gecikme (latency) açısından UDP'ye göre her zaman daha yavaş kalacaktır.


TCP Header
Şöyledir
0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Sequence Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Acknowledgment Number                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Data |           |U|A|P|R|S|F|                               |
| Offset| Reserved  |R|C|S|S|Y|I|            Window             |
|       |           |G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Checksum            |         Urgent Pointer        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options                    |    Padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             data                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Kod ile şöyledir
/* TCP Header */
struct tcpheader {
  u_short tcp_sport;               /* source port */
  u_short tcp_dport;               /* destination port */
  u_int   tcp_seq;                 /* sequence number */
  u_int   tcp_ack;                 /* acknowledgement number */
  u_char  tcp_offx2;               /* data offset, rsvd */
#define TH_OFF(th)      (((th)->tcp_offx2 & 0xf0) >> 4)
  u_char  tcp_flags;
#define TH_FIN  0x01
#define TH_SYN  0x02
#define TH_RST  0x04
#define TH_PUSH 0x08
#define TH_ACK  0x10
#define TH_URG  0x20
#define TH_ECE  0x40
#define TH_CWR  0x80
#define TH_FLAGS        (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
  u_short tcp_win;                 /* window */
  u_short tcp_sum;                 /* checksum */
  u_short tcp_urp;                 /* urgent pointer */
};
TCP zarfında IP numaraları ve TCP paketinin büyüklüğü bilgisi yok. Bu bilgi IP zarfı içindedir.
IP Stack yazılımı IP Numarası + TCP Paketinin büyüklüğü bilgilerini TCP yazılımına verir.
It is clearly nessacery to pass some metadata (size, addresses etc) between the "transport" and "internet" layers but how exactly this is done is an implementation detail.
1. TCP Port Numaraları
Açıklaması şöyle
A port number is a 16-bit unsigned integer, thus ranging from 0 to 65535
1.1 Source Port (16 bits) : Sender's port.
1.2 Destination Port (16 bits) : Receiver's port.
Port numarası 16 bit olduğu için 65535'e kadar gider.

Well-Known Port Numaraları
Bazı port numaraları (0-1024 arası) ayrılmıştır veya atanmış durumda. Well-known port listesi şöyle.

0 Numaralı Port Kullanılamaz
0 numaralı port Well-Know Port numarası içinde ve ayrılmış (reserved) durumda. Yani kullanılamaz. 
Açıklaması şöyle
IANA has reserved both TCP and UDP port 0.
Açıklaması şöyle
Port 0 is reserved by networking libraries (either socket or streams API) to return a random unused port number. All popular OSes do this. If you use port 0 the socket library will give you port 63812 or 23712 or 11328 or 9035 etc. Because of this it is generally impossible for port 0 to appear on the wire (unless you write your own implementation of TCP/IP stack)

Bu portaları dinleyen sunucu çalıştırmak için yönetici (admin) olmak gerekir. Böylece çok kullanıcı işletim sistemlerinden tek bir kullanıcı herkes adına sunucu açamaz.

Registered Port Numaraları
1024 - 4951 arası numaralardır. Sunucular için kullanılır. Sunucu portları IANA'ya kaydettirilebiliyor. Registered port liste şöyle.

Dynamic Port Numaraları
49152 - 65535 arası numaralar dinamik olarak giden (outbound) bağlantılar için kullanılır.

2. Sequence Number (32 bits)
Sequence Number Alanı yazısına taşıdım.

3. Acknowledgement Number (32 bits)
Açıklaması şöyle.
Represents either (if the ACK bit is set) the sequence number of the next expected byte to be received from the sender (defined by the receiver), or (if the ACK bit is not set - only occurs at the beginning of the communication) the acknowledgment of the other end's initial sequence number itself.
4. Data Offset (4 bits)
Açıklaması şöyle.
Specifies the size of the TCP header in the number of 32 bit words, implicitly stating where in the TCP segment the data begins (the offset of data in theTCP segment)
Açıklaması şöyle.
"Data offset specifies the size of the TCP header in 32 bit words. The min. size header is 5 words and the max. is 15 words, thus giving the min. size of 20 bytes and max. of 60 bytes."
Açıklaması şöyle.
The purpose of the data offset is to tell the upper layers where the data starts.
1 word = 4 byte anlamına gelir. Header 20 byte - 60 byte arasında değişebilir. TCP zarfı değişken büyüklükte olduğu için data'nın nerede başladığını belirtmek için kullanılır.

5. Reserved (3 bits)
Açıklaması şöyle
For future use (set to zero)

6. TCP Bayrakları
Bazı TCP bayrakları şunlardır
  • Nonce
  • CWR
  • ECN-ECHO
  • URGENT
  • ACK
  • Push
  • RST
  • SYN
  • FIN
NS Flag - 1 bit
Açıklaması şöyle
Explicit Congestion Notification  (ECN)-nonce concealment protection.
Açıklaması şöyle
ECN is used by TCP to inform the hosts about network congestion.
CWR Flag - 1 bit
Açıklaması şöyle
If set, the Congestion Window Reduced (CWR) flag notifies the receiver that the sender has received an ECE flag and has reduced the congestion window as a result.

ECE - 1 bit
Açıklaması şöyle
When the SYN bit is set, ECN-Echo  (ECE) indicates whether TCP peer is ECN capable.  If the SYN bit is not set, a set ECE field indicates that a packet with the Congestion Experienced flag in the IP header set is received during normal transmission.

URG Flag - 1 bit
Açıklaması şöyle
Indicates that the Urgent pointer field is valid.
Bu bayrak artık pek kullanılmıyor.

ACK - 1 bit
Açıklaması şöyle
Indicates that the Acknowledgment field is valid. (Should be set in all packets after the initial SYN packet sent by the client. )
ACK biti atanmış ise Acknowledgment alanı bir sonraki beklenen paket numarasını belirtir. Açıklaması şöyle
If the ACK flag is set then the value of this field is the next sequence number that the sender is expecting.
ACK Ne Kadar Yük Getirir
Eğer veri iki yönlü ise ACK çok az yük getirir. Açıklaması şöyle
If data is flowing both ways, the ACKs are free since the ACK information rides in the same packets as the data.
Yani şu anlama gelir.
The receiver sends one message instead of two.
PSH (PUSH) Flag - 1 bit
Açıklaması şöyle
If set, requests the receiver to push the buffered data to the receiving application.
Paketin hemen gönderilmesi ve işlenmesi için kullanılır. Http Get isteğinde bu bayrak kullanılabilir.

RST (Reset) Flag -  1 bit
RST (Reset) Flag yazısına taşıdım.

SYN Flag - 1 bit
Açıklaması şöyle
If set means that the sender has finished sending data, and there will be no more data from the sender.

TCP Handshake yazısına bakabilirsiniz.

FIN Flag - 1 bit
Açıklaması şöyle
If set means that the sender has finished sending data,  and there will be no more data from the sender.
[FIN,ACK] bayrakları genelde sunucu socketlerde kullanılır. Socketin gönderme kısmının kapatıldığını belirtir. Socket okuma yapmaya devam edebilir. FIN mesajını alan tarafın yapabileceği bir şey yoktur. Aynı telefonun kapanması gibi karşı taraf kendi gönderme kısmını artık kapatmıştır.

7. Window Size - 16 bits
Açıklaması şöyle.
Set by the receiver. Announces the maximum number of bytes  (beyond the current ACK-ed sequence number) that the receiver is currently willing to receive.
8. Checksum - 16 bits
Açıklaması şöyle.
Used for controlling if header and data contain errors.
Hesaplanan checksum ile alınan checksum tutmuyorsa paket kabul edilmez. Açıklaması şöyle.
When TCP packet is received at the destination, the receiving TCP code also performs the TCP calculation and see if there’s a mismatch. If there is, it means there’s error in the packet and it will be discarded. The same validation logic used for IP header checksum validation can be used.
Eğer TCP bugün tasarlansaydı belki 32 veya 64 bit CRC kullanırdı. Açıklaması şöyle.
TCP has 16-bit whole data checksum protecting some parts of the IPv4 header, TCP header and all of the data. This is a true end-to-end checksum calculated using the same algorithm as IPv4 header checksum. Unfortunately, there is one in 65536 chance of accepting random corruption, meaning that 64 megabytes of randomly corrupted data sent will be once accepted given a kilobyte segment size.
Kod olarak şöyledir.
struct pseudo_tcp
{
  unsigned saddr, daddr;
  unsigned char mbz;
  unsigned char ptcl;
  unsigned short tcpl;
  struct tcpheader tcp;
  char payload[PACKET_LEN];
};
Şöyle yaparız.
/****************************************************************************
  TCP checksum is calculated on the pseudo header, which includes the 
  the TCP header and data, plus some part of the IP header. Therefore, 
  we need to construct the pseudo header first.
*****************************************************************************/
unsigned short calculate_tcp_checksum(struct ipheader *ip)
{
  struct tcpheader *tcp = (struct tcpheader *)((u_char *)ip + 
                             sizeof(struct ipheader)); 

  int tcp_len = ntohs(ip->iph_len) - sizeof(struct ipheader);

  /* pseudo tcp header for the checksum computation */
  struct pseudo_tcp p_tcp;
  memset(&p_tcp, 0x0, sizeof(struct pseudo_tcp));

  p_tcp.saddr  = ip->iph_sourceip.s_addr;
  p_tcp.daddr  = ip->iph_destip.s_addr;
  p_tcp.mbz    = 0;
  p_tcp.ptcl   = IPPROTO_TCP;
  p_tcp.tcpl   = htons(tcp_len);
  memcpy(&p_tcp.tcp, tcp, tcp_len);

  return  (unsigned short)in_cksum((unsigned short *)&p_tcp, tcp_len + 12); 
}
Daha sonra şöyle yaparız.
unsigned short in_cksum(unsigned short *buf,int length)
{
  unsigned short *w = buf;
  int nleft = length;
  int sum = 0;
  unsigned short temp=0;

  /*
  * The algorithm uses a 32 bit accumulator (sum), adds
  * sequential 16 bit words to it, and at the end, folds back all the
  * carry bits from the top 16 bits into the lower 16 bits.
  */
  while (nleft > 1)  {
    sum += *w++;
    nleft -= 2;
  }

  /* treat the odd byte at the end, if any */
  if (nleft == 1) {
    *(u_char *)(&temp) = *(u_char *)w ;
    sum += temp;
  }

  /* add back carry outs from top 16 bits to low 16 bits */
  sum = (sum >> 16) + (sum & 0xffff);     // add hi 16 to low 16 
  sum += (sum >> 16);                     // add carry 
  return (unsigned short)(~sum);
}
9. Options
9.1 No Op
Padding amaçlı kullanılabilir. Bir sonraki bayrağın 16 bit'lik word'den başlaması için boşluğu doldurur.
This option code may be used between options, for example, to align the beginning of a subsequent option on a word boundary. There is no guarantee that senders will use this option, so receivers must be prepared to process options even if they do not begin on a word boundary.
9.2 Maximum Segment Size - 32 bit
MSS alanı SYN aşamasında gönderilir. TCP Handshake yazısına bakabilirsiniz.

9.3 Window Scaling
Açıklama yaz.

9.4 SACK Permitted
SACK Permitted yazısına taşıdım

9.5 Timestamps
Açıklama yaz