06.05. ICMP nesasniedzamā porta kļūda

Last modified by Valdis Vītoliņš on 2018/01/15 21:44

06.05. ICMP nesasniedzamā porta kļūda

Iepriekšējās divas nodaļas aplūkoja ICMP pieprasījumu ziņojumus - adreses maskas un laikspiedoga pieprasījumus un atbildes. Tagad aplūkosim, kādu papildu informāciju atgriež nesasniedzamā porta ziņojumu ICMP kļūdas ziņojums, kas ir ICMP nesasniedzamā galamērķa ziņojuma apakškods. Mēs šo skatīsimies, izmantojot UDP (11.nodaļa). 

Viens no UDP likumiem ir, ka, saņemot UDP datagrammu, ja adresāta ports neatbilst kāda procesa lietotam porta numuram, tad UDP slānis atbild ar ICMP nesasniedzamā porta kļūdu. Varam izraisīt nesasniedzamā porta kļūdu, izmantojot TFTP klientu (TFTP aprakstīsim 15.nodaļā). 

Labi zināmais UDP porta numurs TFTP serverim ir 69. Bet vairums TFTP klientu programmas ļauj mums norādīt citu portu, izmantojot 'connect' komandu. Mēs to izmantojam, lai norādītu portu 8888: 

bsdi % tftp
tftp> connect svr4 8888     (norāda mītni un porta numuru)
tftp> get temp.foo          (mēģina savākt failu)
Transfer timed out.         (pēc apm. 15 sekundēm)
tftp> quit
Komanda 'connect' noglabā mītnes vārdu, ar ko sazināties un porta numuru uz šīs mītnes vēlākai 'get' komandas ievadei. Pēc 'get' komandas ievades UDP datagrammu nosūta servera

Pirms UDP datagrammu var nosūtīt uz

#pic("f_6_8.gif", "500") 6.8.attēls: ICMP nesasniedzama porta ziņojums, ko ģenerē TFTP pieprasījums

Tūlīt tiek atgriezta ICMP nesasniedzamā porta kļūda (4.rindiņa). Bet TFTP klients, šķiet, ignorē šo ICMP ziņojumu, nosūtot vēl vienu UDP datagrammu apmēram pēc 5 sekundēm (5.rindiņa). Tas turpinās vēl 3 reizes, pirms klients liekas mierā.

Ievērojiet, ka ICMP ziņojumus apmaina pašas mītnes (īpaši nenorādot portu numurus), turpretī ikviena 20-baitu UDP datagramma ir no konkrēta porta (2924) uz konkrētu portu (8888).

Skaitlis 20 katras UDP rindiņas beigās ir datu garums konkrētajā UDP datagrammā. Šajā piemērā 20 ir summa TFTP 2-baitu operācijas kodam (opcode), 9-baitu nosaukumam

Ja darbināsim šo pašu piemēru, izmantojot

#pic("f_6_9.gif", "500") 6.9.attēls: ICMP ziņojums, ko atgriež mūsu "UDP port unreachable" piemērā

Viens no ICMP likumiem ir tāds, ka ICMP kļūdu ziņojumi (sk. pēdējo kolonnu #picref("f_6_3.gif", "6.3.attēlā")) vienmēr iekļauj IP kļūdu ģenerējošās datagrammas sākumposmu (ieskaitot opcijas) un pirmos 8 sākumposmam sekojošos datu baitus. Mūsu piemērā pirmie 8 baiti pēc IP sākumposma satur UDP sākumposmu (#picref("f_11_2.gif", "11.2.attēls")).

Svarīgi zināt, ka UDP sākumposmā ir ietverti avota un galamērķa portu numuri. Šoreiz galamērķa porta numurs (8888) izraisīja ICMP nesasniedzamā porta ģenerēšanu. Avota porta numuru (2924) var izmantot sistēma, kura saņems ICMP kļūdu, lai saistītu šo kļūdas ziņojumu ar konkrētu lietotāja procesu (konkrēti šajā gadījumā - TFTP klientu).

Viens no iemesliem, kādēļ sūta atpakaļ kļūdu izraisījušās IP datagrammas IP sākumposmu ir tas, ka šis IP sākumposms ir tas protokola lauks, kurš ļauj ICMP saprast, kā interpretēt nākamos 8 baitus (konkrēti šajā gadījumā UDP sākumposmu). Kad aplūkojam TCP sākumposmu (#picref("f_17_2.gif", "17.2.attēlu")), redzēsim, ka avota un galamērķa portu numuri ir ietverti pirmajos 8 bitos arī TCP sākumposmam. ICMP nesasniedzamības ziņojumu vispārīgais formāts ir parādīts 6.10.attēlā.

#pic("f_6_10.gif", "500") 6.10.attēls: ICMP nesasniedzamības ziņojums

#picref("f_6_3.gif", "6.3.attēlā") atzīmējām, ka ir 16 dažādi ICMP nesasniedzamības ziņojumi, kuru kodi ir no 0 līdz 15. ICMP nesasniedzamā porta kods ir 3. Arī, lai gan #picref("f_6_10.gif", "6.10.attēls") norāda, ka otrajam 32-bitu vārdam ICMP ziņojumā jābūt 0, Ceļa MTU Atrašanas mehānisms (2.9.nodaļa) atļauj maršrutētājam novietot izejošās saskarnes MTU jaunākajos 16 bitos šai 32-bitu vērtībai, kad kods vienāds ar 4 (ziņojums "nepieciešama fragmentācija, bet ir uzstādīts nefragmentēšanas bits"). Šīs kļūdas piemēru redzēsim 11.6.nodaļā.

Lai gan ICMP likumi ļauj sistēmai atgriezt vairāk nekā pirmos 8 baitus no kļūdu izraisījušās IP datagrammas datu sadaļas, vairums no Bērklija atvasināto implementāciju atgriež precīzi 8 baitus. Solaris 2.2 sistēmās opcija

Viscaur šajā grāmatā attēlosim

#pic("f_6_11.gif", "500") 6.11.attēls: Hronoloģija TFTP pieprasījumam uz nederīgu portu

Laiks pieaug, virzoties uz leju un iezīmes attēla kreisajā pusē ir tās pašas laika vērtības, kas mūsu

Kādēļ TFTP klients turpina atkalsūtīt pieprasījumu arī pēc ICMP ziņojumu atgriešanas? Te izpaužas tīklu programmēšanas efekts, kurā BSD sistēmas nepaziņo lietotāju procesiem, kuri izmanto UDP, par ICMP ziņojumiem, kas tiek saņemti par attiecīgo soketu, ja vien process nav izveidojis savienojumu uz šo soketu. Standartais BSD sistēmā esošais TFTP klients neveido savienojumu, tādēļ arī tas nesaņem ICMP kļūdas paziņojumu

Var ievērot arī slikto atkalsūtīšanas noildzes algoritmu, ko izmanto šis TFTP klients. Tas pieņem, ka 5 sekundes ir piemērots laiks un atkalsūta katras 5 sekundes, izmantojot kopumā 25 sekundes. Vēlāk redzēsim, ka TCP ir daudz labāks algoritms. 

Šis senlaicīgais noildzes un atkalsūtīšanas algoritms, ko lieto TFTP klients, ir aizliegts Mītņu Prasību RFC. Tomēr visas trīs sistēmas autora apakštīklā un Solaris 2.2 joprojām to lieto. AIX 3.2.2 pielieto eksponenciālu atkāpšanos noildzei, sūtot paketes pēc 0, 5, 15 un 35 sekundēm, kas ir ieteiktais veids. Mēs daudz vairāk runāsim par noildzēm 21.nodaļā

Visbeidzot, ievērojiet, ka ICMP ziņojumus atgriež apmēram 3.5 ms pēc UDP datagrammas nosūtīšanas - kā redzēsim 7.nodaļā, tas ir līdzīgs aprites laikiem Ping pieprasījumos.