Linux жүйесінде желілік мәселелерді имитациялау

Барлығына сәлем, менің атым Саша, мен FunCorp-те серверлік тестілеуді жүргіземін. Біз, басқалар сияқты, қызмет көрсетуге бағытталған архитектураны енгіздік. Бұл бір жағынан жұмысты жеңілдетеді, өйткені... Әрбір қызметті бөлек тексеру оңайырақ, бірақ екінші жағынан, желі арқылы жиі болатын қызметтердің бір-бірімен әрекеттесуін тексеру қажеттілігі туындайды.

Бұл мақалада желі ақаулары болған кезде қолданбаның жұмысын сипаттайтын негізгі сценарийлерді тексеру үшін пайдалануға болатын екі утилита туралы сөйлесемін.

Linux жүйесінде желілік мәселелерді имитациялау

Желі проблемаларын имитациялау

Әдетте, бағдарламалық қамтамасыз ету жақсы интернет байланысы бар сынақ серверлерінде тексеріледі. Қатаң өндірістік орталарда бәрі біркелкі болмауы мүмкін, сондықтан кейде нашар қосылым жағдайында бағдарламаларды сынау қажет. Linux жүйесінде утилита осындай жағдайларды имитациялау тапсырмасын орындауға көмектеседі tc.

tc(аббр. Traffic Control бөлімінен) жүйеде желілік пакеттерді жіберуді конфигурациялауға мүмкіндік береді. Бұл утилитаның керемет мүмкіндіктері бар, олар туралы көбірек оқуға болады осында. Мұнда мен олардың кейбіреулерін ғана қарастырамын: біз трафикті жоспарлауға қызығушылық танытамыз, ол үшін біз пайдаланамыз qdisc, және бізге тұрақсыз желіні эмуляциялау қажет болғандықтан, біз класссыз qdisc қолданамыз нетем.

Серверде жаңғырық серверін іске қосайық (мен қолдандым nmap-ncat):

ncat -l 127.0.0.1 12345 -k -c 'xargs -n1 -i echo "Response: {}"'

Клиент пен сервер арасындағы өзара әрекеттесудің әрбір қадамында барлық уақыт белгілерін егжей-тегжейлі көрсету үшін мен сұраныс жіберетін қарапайым Python сценарийін жаздым. сынақ біздің echo серверіне.

Клиенттің бастапқы коды

#!/bin/python

import socket
import time

HOST = '127.0.0.1'
PORT = 12345
BUFFER_SIZE = 1024
MESSAGE = "Testn"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
t1 = time.time()
print "[time before connection: %.5f]" % t1
s.connect((HOST, PORT))
print "[time after connection, before sending: %.5f]" % time.time()
s.send(MESSAGE)
print "[time after sending, before receiving: %.5f]" % time.time()
data = s.recv(BUFFER_SIZE)
print "[time after receiving, before closing: %.5f]" % time.time()
s.close()
t2 = time.time()
print "[time after closing: %.5f]" % t2
print "[total duration: %.5f]" % (t2 - t1)

print data

Оны іске қосып, интерфейстегі трафикті қарастырайық lo және порт 12345:

[user@host ~]# python client.py
[time before connection: 1578652979.44837]
[time after connection, before sending: 1578652979.44889]
[time after sending, before receiving: 1578652979.44894]
[time after receiving, before closing: 1578652979.45922]
[time after closing: 1578652979.45928]
[total duration: 0.01091]
Response: Test

Көлік қоқысы

[user@host ~]# tcpdump -i lo -nn port 12345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
10:42:59.448601 IP 127.0.0.1.54054 > 127.0.0.1.12345: Flags [S], seq 3383332866, win 43690, options [mss 65495,sackOK,TS val 606325685 ecr 0,nop,wscale 7], length 0
10:42:59.448612 IP 127.0.0.1.12345 > 127.0.0.1.54054: Flags [S.], seq 2584700178, ack 3383332867, win 43690, options [mss 65495,sackOK,TS val 606325685 ecr 606325685,nop,wscale 7], length 0
10:42:59.448622 IP 127.0.0.1.54054 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 606325685 ecr 606325685], length 0
10:42:59.448923 IP 127.0.0.1.54054 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 606325685 ecr 606325685], length 5
10:42:59.448930 IP 127.0.0.1.12345 > 127.0.0.1.54054: Flags [.], ack 6, win 342, options [nop,nop,TS val 606325685 ecr 606325685], length 0
10:42:59.459118 IP 127.0.0.1.12345 > 127.0.0.1.54054: Flags [P.], seq 1:15, ack 6, win 342, options [nop,nop,TS val 606325696 ecr 606325685], length 14
10:42:59.459213 IP 127.0.0.1.54054 > 127.0.0.1.12345: Flags [.], ack 15, win 342, options [nop,nop,TS val 606325696 ecr 606325696], length 0
10:42:59.459268 IP 127.0.0.1.54054 > 127.0.0.1.12345: Flags [F.], seq 6, ack 15, win 342, options [nop,nop,TS val 606325696 ecr 606325696], length 0
10:42:59.460184 IP 127.0.0.1.12345 > 127.0.0.1.54054: Flags [F.], seq 15, ack 7, win 342, options [nop,nop,TS val 606325697 ecr 606325696], length 0
10:42:59.460196 IP 127.0.0.1.54054 > 127.0.0.1.12345: Flags [.], ack 16, win 342, options [nop,nop,TS val 606325697 ecr 606325697], length 0

Барлығы стандартты: үш жақты қол алысу, екі рет жауап ретінде PSH/ACK және ACK – бұл клиент пен сервер арасындағы сұраныс пен жауап алмасу, ал FIN/ACK және ACK екі рет – қосылымды аяқтау.

Пакет кідірісі

Енді кешіктіруді 500 миллисекундқа орнатайық:

tc qdisc add dev lo root netem delay 500ms

Біз клиентті іске қосамыз және сценарий енді 2 секундта жұмыс істейтінін көреміз:

[user@host ~]# ./client.py
[time before connection: 1578662612.71044]
[time after connection, before sending: 1578662613.71059]
[time after sending, before receiving: 1578662613.71065]
[time after receiving, before closing: 1578662614.72011]
[time after closing: 1578662614.72019]
[total duration: 2.00974]
Response: Test

Көлікте не бар? Қарап көрейік:

Көлік қоқысы

13:23:33.210520 IP 127.0.0.1.58694 > 127.0.0.1.12345: Flags [S], seq 1720950927, win 43690, options [mss 65495,sackOK,TS val 615958947 ecr 0,nop,wscale 7], length 0
13:23:33.710554 IP 127.0.0.1.12345 > 127.0.0.1.58694: Flags [S.], seq 1801168125, ack 1720950928, win 43690, options [mss 65495,sackOK,TS val 615959447 ecr 615958947,nop,wscale 7], length 0
13:23:34.210590 IP 127.0.0.1.58694 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 615959947 ecr 615959447], length 0
13:23:34.210657 IP 127.0.0.1.58694 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 615959947 ecr 615959447], length 5
13:23:34.710680 IP 127.0.0.1.12345 > 127.0.0.1.58694: Flags [.], ack 6, win 342, options [nop,nop,TS val 615960447 ecr 615959947], length 0
13:23:34.719371 IP 127.0.0.1.12345 > 127.0.0.1.58694: Flags [P.], seq 1:15, ack 6, win 342, options [nop,nop,TS val 615960456 ecr 615959947], length 14
13:23:35.220106 IP 127.0.0.1.58694 > 127.0.0.1.12345: Flags [.], ack 15, win 342, options [nop,nop,TS val 615960957 ecr 615960456], length 0
13:23:35.220188 IP 127.0.0.1.58694 > 127.0.0.1.12345: Flags [F.], seq 6, ack 15, win 342, options [nop,nop,TS val 615960957 ecr 615960456], length 0
13:23:35.720994 IP 127.0.0.1.12345 > 127.0.0.1.58694: Flags [F.], seq 15, ack 7, win 342, options [nop,nop,TS val 615961457 ecr 615960957], length 0
13:23:36.221025 IP 127.0.0.1.58694 > 127.0.0.1.12345: Flags [.], ack 16, win 342, options [nop,nop,TS val 615961957 ecr 615961457], length 0

Клиент пен сервердің өзара әрекеттесуінде күтілетін жарты секундтық кешігу пайда болғанын көруге болады. Кешігу үлкенірек болса, жүйе өзін әлдеқайда қызықты етеді: ядро ​​кейбір TCP пакеттерін қайта жібере бастайды. Кешігуді 1 секундқа өзгертіп, трафикті қарастырайық (клиенттің нәтижесін көрсетпеймін, жалпы ұзақтығында күтілетін 4 секунд бар):

tc qdisc change dev lo root netem delay 1s

Көлік қоқысы

13:29:07.709981 IP 127.0.0.1.39306 > 127.0.0.1.12345: Flags [S], seq 283338334, win 43690, options [mss 65495,sackOK,TS val 616292946 ecr 0,nop,wscale 7], length 0
13:29:08.710018 IP 127.0.0.1.12345 > 127.0.0.1.39306: Flags [S.], seq 3514208179, ack 283338335, win 43690, options [mss 65495,sackOK,TS val 616293946 ecr 616292946,nop,wscale 7], length 0
13:29:08.711094 IP 127.0.0.1.39306 > 127.0.0.1.12345: Flags [S], seq 283338334, win 43690, options [mss 65495,sackOK,TS val 616293948 ecr 0,nop,wscale 7], length 0
13:29:09.710048 IP 127.0.0.1.39306 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 616294946 ecr 616293946], length 0
13:29:09.710152 IP 127.0.0.1.39306 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 616294947 ecr 616293946], length 5
13:29:09.711120 IP 127.0.0.1.12345 > 127.0.0.1.39306: Flags [S.], seq 3514208179, ack 283338335, win 43690, options [mss 65495,sackOK,TS val 616294948 ecr 616292946,nop,wscale 7], length 0
13:29:10.710173 IP 127.0.0.1.12345 > 127.0.0.1.39306: Flags [.], ack 6, win 342, options [nop,nop,TS val 616295947 ecr 616294947], length 0
13:29:10.711140 IP 127.0.0.1.39306 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 616295948 ecr 616293946], length 0
13:29:10.714782 IP 127.0.0.1.12345 > 127.0.0.1.39306: Flags [P.], seq 1:15, ack 6, win 342, options [nop,nop,TS val 616295951 ecr 616294947], length 14
13:29:11.714819 IP 127.0.0.1.39306 > 127.0.0.1.12345: Flags [.], ack 15, win 342, options [nop,nop,TS val 616296951 ecr 616295951], length 0
13:29:11.714893 IP 127.0.0.1.39306 > 127.0.0.1.12345: Flags [F.], seq 6, ack 15, win 342, options [nop,nop,TS val 616296951 ecr 616295951], length 0
13:29:12.715562 IP 127.0.0.1.12345 > 127.0.0.1.39306: Flags [F.], seq 15, ack 7, win 342, options [nop,nop,TS val 616297952 ecr 616296951], length 0
13:29:13.715596 IP 127.0.0.1.39306 > 127.0.0.1.12345: Flags [.], ack 16, win 342, options [nop,nop,TS val 616298952 ecr 616297952], length 0

Клиент SYN пакетін екі рет, ал сервер SYN/ACK екі рет жібергенін көруге болады.

Тұрақты мәннен басқа, кідіріс ауытқуға, тарату функциясына және корреляцияға (алдыңғы пакеттің мәнімен) орнатылуы мүмкін. Бұл келесідей орындалады:

tc qdisc change dev lo root netem delay 500ms 400ms 50 distribution normal

Мұнда біз кешіктіруді 100-ден 900 миллисекундқа дейін орнаттық, мәндер қалыпты үлестірімге сәйкес таңдалады және алдыңғы пакет үшін кідіріс мәнімен 50% корреляция болады.

Сіз бірінші қолданған пәрменді байқаған боларсыз қосу, сосын өзгеріс. Бұл пәрмендердің мағынасы түсінікті, сондықтан мен одан да көп екенін қосамын дель, ол конфигурацияны жою үшін пайдаланылуы мүмкін.

Пакет жоғалуы

Енді пакетті жоғалтуға тырысайық. Құжаттамадан көрініп тұрғандай, мұны үш жолмен жасауға болады: пакеттерді белгілі бір ықтималдықпен кездейсоқ жоғалту, пакеттердің жоғалуын есептеу үшін 2, 3 немесе 4 күйден тұратын Марков тізбегін пайдалану немесе Эллиотт-Гилберт моделін қолдану. Мақалада мен бірінші (ең қарапайым және ең айқын) әдісті қарастырамын, сіз басқалары туралы оқи аласыз осында.

50% корреляциямен пакеттердің 25% жоғалтуын жасайық:

tc qdisc add dev lo root netem loss 50% 25%

Өкінішке орай, tcpdump бізге пакеттердің жоғалуын нақты көрсете алмайды, біз тек оның шынымен жұмыс істейтінін болжаймыз. Сценарийдің ұлғайған және тұрақсыз жұмыс уақыты бізге мұны тексеруге көмектеседі. client.py (бірден немесе 20 секундта аяқталуы мүмкін), сондай-ақ қайта жіберілетін пакеттер санының артуы:

[user@host ~]# netstat -s | grep retransmited; sleep 10; netstat -s | grep retransmited
    17147 segments retransmited
    17185 segments retransmited

Пакеттерге шу қосу

Пакеттің жоғалуынан басқа, пакеттің зақымдалуын имитациялауға болады: шуыл пакеттің кездейсоқ орнында пайда болады. 50% ықтималдықпен және корреляциясыз пакеттік зақымдану жасайық:

tc qdisc change dev lo root netem corrupt 50%

Біз клиенттік сценарийді іске қосамыз (бұл жерде қызықты ештеңе жоқ, бірақ оны аяқтау үшін 2 секунд қажет болды), трафикті қараңыз:

Көлік қоқысы

[user@host ~]# tcpdump -i lo -nn port 12345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
10:20:54.812434 IP 127.0.0.1.43666 > 127.0.0.1.12345: Flags [S], seq 2023663770, win 43690, options [mss 65495,sackOK,TS val 1037001049 ecr 0,nop,wscale 7], length 0
10:20:54.812449 IP 127.0.0.1.12345 > 127.0.0.1.43666: Flags [S.], seq 2104268044, ack 2023663771, win 43690, options [mss 65495,sackOK,TS val 1037001049 ecr 1037001049,nop,wscale 7], length 0
10:20:54.812458 IP 127.0.0.1.43666 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 1037001049 ecr 1037001049], length 0
10:20:54.812509 IP 127.0.0.1.43666 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 1037001049 ecr 1037001049], length 5
10:20:55.013093 IP 127.0.0.1.43666 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 1037001250 ecr 1037001049], length 5
10:20:55.013122 IP 127.0.0.1.12345 > 127.0.0.1.43666: Flags [.], ack 6, win 342, options [nop,nop,TS val 1037001250 ecr 1037001250], length 0
10:20:55.014681 IP 127.0.0.1.12345 > 127.0.0.1.43666: Flags [P.], seq 1:15, ack 6, win 342, options [nop,nop,TS val 1037001251 ecr 1037001250], length 14
10:20:55.014745 IP 127.0.0.1.43666 > 127.0.0.1.12345: Flags [.], ack 15, win 340, options [nop,nop,TS val 1037001251 ecr 1037001251], length 0
10:20:55.014823 IP 127.0.0.1.43666 > 127.0.0.5.12345: Flags [F.], seq 2023663776, ack 2104268059, win 342, options [nop,nop,TS val 1037001251 ecr 1037001251], length 0
10:20:55.214088 IP 127.0.0.1.12345 > 127.0.0.1.43666: Flags [P.], seq 1:15, ack 6, win 342, options [nop,unknown-65 0x0a3dcf62eb3d,[bad opt]>
10:20:55.416087 IP 127.0.0.1.43666 > 127.0.0.1.12345: Flags [F.], seq 6, ack 15, win 342, options [nop,nop,TS val 1037001653 ecr 1037001251], length 0
10:20:55.416804 IP 127.0.0.1.12345 > 127.0.0.1.43666: Flags [F.], seq 15, ack 7, win 342, options [nop,nop,TS val 1037001653 ecr 1037001653], length 0
10:20:55.416818 IP 127.0.0.1.43666 > 127.0.0.1.12345: Flags [.], ack 16, win 343, options [nop,nop,TS val 1037001653 ecr 1037001653], length 0
10:20:56.147086 IP 127.0.0.1.12345 > 127.0.0.1.43666: Flags [F.], seq 15, ack 7, win 342, options [nop,nop,TS val 1037002384 ecr 1037001653], length 0
10:20:56.147101 IP 127.0.0.1.43666 > 127.0.0.1.12345: Flags [.], ack 16, win 342, options [nop,nop,TS val 1037002384 ecr 1037001653], length 0

Кейбір пакеттердің бірнеше рет жіберілгенін және метадеректері бұзылған бір пакет бар екенін көруге болады: опциялар [жоқ, белгісіз-65 0x0a3dcf62eb3d, [жаман таңдау]>. Ең бастысы, соңында бәрі дұрыс жұмыс істеді - TCP өз міндетін орындады.

Пакеттердің қайталануы

Басқа немен айналысуға болады нетем? Мысалы, пакеттердің жоғалуының кері жағдайын имитациялаңыз - пакеттердің қайталануы. Бұл пәрмен сонымен қатар 2 аргументті қабылдайды: ықтималдық және корреляция.

tc qdisc change dev lo root netem duplicate 50% 25%

Пакеттердің ретін өзгерту

Сіз сөмкелерді екі жолмен араластыра аласыз.

Біріншісінде, кейбір пакеттер дереу жіберіледі, қалғандары белгіленген кідіріспен. Құжаттамадан мысал:

tc qdisc change dev lo root netem delay 10ms reorder 25% 50%

Ықтималдығы 25% (және 50% корреляция) пакет дереу жіберіледі, қалғаны 10 миллисекунд кешігумен жіберіледі.

Екінші әдіс - әрбір N-ші пакет берілген ықтималдықпен (және корреляциямен), ал қалғандары берілген кідіріспен бірден жіберіледі. Құжаттамадан мысал:

tc qdisc change dev lo root netem delay 10ms reorder 25% 50% gap 5

Әрбір бесінші пакеттің кідіріссіз жіберілу мүмкіндігі 25%.

Өткізу жолағын өзгерту

Әдетте олар барлық жерде сілтеме жасайды ТБФ, бірақ көмегімен нетем Сондай-ақ интерфейс өткізу қабілеттілігін өзгертуге болады:

tc qdisc change dev lo root netem rate 56kbit

Бұл команда айнала серуендейді жергілікті теру модемі арқылы интернетті шарлау сияқты азапты. Бит жылдамдығын орнатудан басқа, сілтеме деңгейінің протокол үлгісін де эмуляциялауға болады: пакет үшін үстеме шығынды, ұяшық өлшемін және ұяшық үшін үстеме шығынды орнатыңыз. Мысалы, бұл модельдеуге болады Банкомат және бит жылдамдығы 56 кбит/сек:

tc qdisc change dev lo root netem rate 56kbit 0 48 5

Қосылым күту уақытын имитациялау

Бағдарламаны қабылдау кезінде сынақ жоспарындағы тағы бір маңызды сәт - күту уақыты. Бұл маңызды, өйткені таратылған жүйелерде қызметтердің бірі өшірілгенде, басқалары уақытында басқаларына қайта оралуы немесе клиентке қатені қайтаруы керек және ешбір жағдайда жауап немесе қосылымды күтпей, жай ілулі тұрмауы керек. белгіленеді.

Мұны істеудің бірнеше жолы бар: мысалы, жауап бермейтін мысқылды пайдаланыңыз немесе отладчик арқылы процесске қосылыңыз, тоқтау нүктесін дұрыс жерге қойыңыз және процесті тоқтатыңыз (бұл ең бұрмаланған әдіс болуы мүмкін). Бірақ ең айқын бірі - брандмауэр порттары немесе хосттары. Бұл бізге көмектеседі iptables.

Көрсету үшін біз 12345 портын брандмауэрмен қамтамасыз етеміз және клиенттік сценарийді іске қосамыз. Жіберушіде осы портқа шығыс пакеттерді немесе қабылдағыштағы кіріс пакеттерін брандмауэрмен қорғай аласыз. Менің мысалдарымда кіріс пакеттер брандмауэрмен жабылады (біз INPUT тізбегін және опцияны қолданамыз. --dport). Мұндай пакеттер RST TCP жалауымен немесе ICMP хостына қол жетімсіз (шын мәнінде әдепкі әрекет icmp-порты-қолжетімсіз, сонымен қатар жауап жіберу мүмкіндігі бар icmp-желіге қол жетімсіз, icmp-proto-қолжетімсіз, icmp-net- тыйым салынған и icmp-хостқа тыйым салынған).

DROP

DROP ережесі бар болса, пакеттер жай ғана «жоғалады».

iptables -A INPUT -p tcp --dport 12345 -j DROP

Біз клиентті іске қосамыз және оның серверге қосылу кезеңінде қатып қалғанын көреміз. Жол қозғалысын қарастырайық:
Көлік қоқысы

[user@host ~]# tcpdump -i lo -nn port 12345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
08:28:20.213506 IP 127.0.0.1.32856 > 127.0.0.1.12345: Flags [S], seq 3019694933, win 43690, options [mss 65495,sackOK,TS val 1203046450 ecr 0,nop,wscale 7], length 0
08:28:21.215086 IP 127.0.0.1.32856 > 127.0.0.1.12345: Flags [S], seq 3019694933, win 43690, options [mss 65495,sackOK,TS val 1203047452 ecr 0,nop,wscale 7], length 0
08:28:23.219092 IP 127.0.0.1.32856 > 127.0.0.1.12345: Flags [S], seq 3019694933, win 43690, options [mss 65495,sackOK,TS val 1203049456 ecr 0,nop,wscale 7], length 0
08:28:27.227087 IP 127.0.0.1.32856 > 127.0.0.1.12345: Flags [S], seq 3019694933, win 43690, options [mss 65495,sackOK,TS val 1203053464 ecr 0,nop,wscale 7], length 0
08:28:35.235102 IP 127.0.0.1.32856 > 127.0.0.1.12345: Flags [S], seq 3019694933, win 43690, options [mss 65495,sackOK,TS val 1203061472 ecr 0,nop,wscale 7], length 0

Клиент SYN пакеттерін экспоненциалды түрде ұлғайған күту уақытымен жіберетінін көруге болады. Сонымен, біз клиентте кішкене қатені таптық: әдісті пайдалану керек settimeout()клиент серверге қосылуға тырысатын уақытты шектеу үшін.

Біз ережені дереу алып тастаймыз:

iptables -D INPUT -p tcp --dport 12345 -j DROP

Барлық ережелерді бірден жоюға болады:

iptables -F

Егер сіз Docker-ді қолданып жатсаңыз және контейнерге баратын барлық трафикті брандмауэрмен қорғау қажет болса, оны келесідей орындауға болады:

iptables -I DOCKER-USER -p tcp -d CONTAINER_IP -j DROP

ҚАБЫЛДАҢЫЗ

Енді ұқсас ережені қосайық, бірақ REJECT арқылы:

iptables -A INPUT -p tcp --dport 12345 -j REJECT

Клиент бір секундтан кейін қатемен шығады [Erno 111] Қосылудан бас тартылды. ICMP трафигін қарастырайық:

[user@host ~]# tcpdump -i lo -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
08:45:32.871414 IP 127.0.0.1 > 127.0.0.1: ICMP 127.0.0.1 tcp port 12345 unreachable, length 68
08:45:33.873097 IP 127.0.0.1 > 127.0.0.1: ICMP 127.0.0.1 tcp port 12345 unreachable, length 68

Клиент екі рет алғанын көруге болады портқа қол жеткізу мүмкін емес содан кейін қатемен аяқталды.

tcp-қайта орнату арқылы ҚАБЫЛДАУ

Опцияны қосуға тырысайық --reject-tcp-reset көмегімен:

iptables -A INPUT -p tcp --dport 12345 -j REJECT --reject-with tcp-reset

Бұл жағдайда клиент қатемен бірден шығады, себебі бірінші сұрау RST пакетін алды:

[user@host ~]# tcpdump -i lo -nn port 12345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
09:02:52.766175 IP 127.0.0.1.60658 > 127.0.0.1.12345: Flags [S], seq 1889460883, win 43690, options [mss 65495,sackOK,TS val 1205119003 ecr 0,nop,wscale 7], length 0
09:02:52.766184 IP 127.0.0.1.12345 > 127.0.0.1.60658: Flags [R.], seq 0, ack 1889460884, win 0, length 0

icmp-host-unreachable көмегімен ҚАБЫЛДАУ

REJECT пайдаланудың басқа опциясын қолданып көрейік:

iptables -A INPUT -p tcp --dport 12345 -j REJECT --reject-with icmp-host-unreachable

Клиент бір секундтан кейін қатемен шығады [Erno 113] Хостқа бағыт жоқ, біз ICMP трафигінде көреміз ICMP хост 127.0.0.1 қол жетімсіз.

Сіз сондай-ақ басқа REJECT параметрлерін қолданып көре аласыз, мен соларға назар аударамын :)

Сұраныс күту уақытын имитациялау

Тағы бір жағдай - клиент серверге қосыла алды, бірақ оған сұрау жібере алмайды. Сүзу бірден басталмауы үшін пакеттерді қалай сүзуге болады? Клиент пен сервер арасындағы кез келген байланыстың трафигін қарасаңыз, қосылымды орнату кезінде тек SYN және ACK жалаулары қолданылатынын байқайсыз, бірақ деректермен алмасу кезінде соңғы сұрау пакетінде PSH жалауы болады. Буферлеуді болдырмау үшін ол автоматты түрде орнатылады. Сіз бұл ақпаратты сүзгі жасау үшін пайдалана аласыз: ол PSH жалауы бар пакеттерден басқа барлық пакеттерге рұқсат береді. Осылайша, байланыс орнатылады, бірақ клиент серверге деректерді жібере алмайды.

DROP

DROP үшін пәрмен келесідей болады:

iptables -A INPUT -p tcp --tcp-flags PSH PSH --dport 12345 -j DROP

Клиентті іске қосыңыз және трафикті бақылаңыз:

Көлік қоқысы

[user@host ~]# tcpdump -i lo -nn port 12345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
10:02:47.549498 IP 127.0.0.1.49594 > 127.0.0.1.12345: Flags [S], seq 2166014137, win 43690, options [mss 65495,sackOK,TS val 1208713786 ecr 0,nop,wscale 7], length 0
10:02:47.549510 IP 127.0.0.1.12345 > 127.0.0.1.49594: Flags [S.], seq 2341799088, ack 2166014138, win 43690, options [mss 65495,sackOK,TS val 1208713786 ecr 1208713786,nop,wscale 7], length 0
10:02:47.549520 IP 127.0.0.1.49594 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 1208713786 ecr 1208713786], length 0
10:02:47.549568 IP 127.0.0.1.49594 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 1208713786 ecr 1208713786], length 5
10:02:47.750084 IP 127.0.0.1.49594 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 1208713987 ecr 1208713786], length 5
10:02:47.951088 IP 127.0.0.1.49594 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 1208714188 ecr 1208713786], length 5
10:02:48.354089 IP 127.0.0.1.49594 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 1208714591 ecr 1208713786], length 5

Байланыс орнатылғанын және клиент деректерді серверге жібере алмайтынын көреміз.

ҚАБЫЛДАҢЫЗ

Бұл жағдайда мінез-құлық бірдей болады: клиент сұрауды жібере алмайды, бірақ қабылдайды ICMP 127.0.0.1 tcp порты 12345 қолжетімсіз және сұрауды қайта жіберу арасындағы уақытты экспоненциалды түрде арттырыңыз. Пәрмен келесідей көрінеді:

iptables -A INPUT -p tcp --tcp-flags PSH PSH --dport 12345 -j REJECT

tcp-қайта орнату арқылы ҚАБЫЛДАУ

Пәрмен келесідей көрінеді:

iptables -A INPUT -p tcp --tcp-flags PSH PSH --dport 12345 -j REJECT --reject-with tcp-reset

Біз оны пайдаланған кезде білеміз --reject-tcp-reset көмегімен клиент жауап ретінде RST пакетін алады, сондықтан мінез-құлықты болжауға болады: қосылым орнатылған кезде RST пакетін алу розетканың екінші жағынан күтпеген жерден жабылғанын білдіреді, яғни клиент қабылдауы керек Қосылым теңдесті арқылы қалпына келтірілді. Сценарийді іске қосып, осыған көз жеткізейік. Ал трафик келесідей болады:

Көлік қоқысы

[user@host ~]# tcpdump -i lo -nn port 12345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
10:22:14.186269 IP 127.0.0.1.52536 > 127.0.0.1.12345: Flags [S], seq 2615137531, win 43690, options [mss 65495,sackOK,TS val 1209880423 ecr 0,nop,wscale 7], length 0
10:22:14.186284 IP 127.0.0.1.12345 > 127.0.0.1.52536: Flags [S.], seq 3999904809, ack 2615137532, win 43690, options [mss 65495,sackOK,TS val 1209880423 ecr 1209880423,nop,wscale 7], length 0
10:22:14.186293 IP 127.0.0.1.52536 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 1209880423 ecr 1209880423], length 0
10:22:14.186338 IP 127.0.0.1.52536 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 1209880423 ecr 1209880423], length 5
10:22:14.186344 IP 127.0.0.1.12345 > 127.0.0.1.52536: Flags [R], seq 3999904810, win 0, length 0

icmp-host-unreachable көмегімен ҚАБЫЛДАУ

Менің ойымша, бұл команданың қандай болатыны барлығына түсінікті :) Бұл жағдайда клиенттің әрекеті қарапайым РЕТТЕУден сәл өзгеше болады: клиент пакетті қайта жіберу әрекеттері арасындағы күту уақытын көбейтпейді.

[user@host ~]# tcpdump -i lo -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
10:29:56.149202 IP 127.0.0.1 > 127.0.0.1: ICMP host 127.0.0.1 unreachable, length 65
10:29:56.349107 IP 127.0.0.1 > 127.0.0.1: ICMP host 127.0.0.1 unreachable, length 65
10:29:56.549117 IP 127.0.0.1 > 127.0.0.1: ICMP host 127.0.0.1 unreachable, length 65
10:29:56.750125 IP 127.0.0.1 > 127.0.0.1: ICMP host 127.0.0.1 unreachable, length 65
10:29:56.951130 IP 127.0.0.1 > 127.0.0.1: ICMP host 127.0.0.1 unreachable, length 65
10:29:57.152107 IP 127.0.0.1 > 127.0.0.1: ICMP host 127.0.0.1 unreachable, length 65
10:29:57.353115 IP 127.0.0.1 > 127.0.0.1: ICMP host 127.0.0.1 unreachable, length 65

қорытынды

Қызметтің ілулі клиентпен немесе сервермен әрекеттесуін тексеру үшін мысқыл жазудың қажеті жоқ, кейде Linux-та табылған стандартты утилиталарды пайдалану жеткілікті.

Мақалада талқыланған утилиталар сипатталғанға қарағанда көбірек мүмкіндіктерге ие, сондықтан сіз оларды пайдаланудың кейбір жеке нұсқаларын таба аласыз. Жеке менің жазғандарым әрқашан жеткілікті (шын мәнінде, одан да аз). Егер сіз осы немесе ұқсас утилиталарды өз компанияңызда тестілеуде қолдансаңыз, дәл қалай екенін жазыңыз. Олай болмаса, ұсынылған әдістерді пайдаланып желі ақаулары жағдайында оны сынауды шешсеңіз, бағдарламалық жасақтама жақсарады деп үміттенемін.

Ақпарат көзі: www.habr.com

пікір қалдыру