Linux-da şəbəkə problemlərinin simulyasiyası

Hər kəsə salam, mənim adım Sasha, mən FunCorp-da backend testinə cavabdehəm. Biz, bir çoxları kimi, xidmət yönümlü arxitektura tətbiq etmişik. Bu, bir tərəfdən işi asanlaşdırır, çünki hər bir xidməti ayrıca yoxlamaq daha asandır, lakin digər tərəfdən, şəbəkə üzərindən tez-tez baş verən xidmətlərin bir-biri ilə qarşılıqlı əlaqəsini yoxlamaq zərurəti yaranır.

Bu yazıda, şəbəkə problemlərinin mövcudluğunda tətbiqin davranışını təsvir edən əsas ssenariləri sınaqdan keçirmək üçün istifadə edilə bilən iki yardım proqramı haqqında danışacağam.

Linux-da şəbəkə problemlərinin simulyasiyası

Şəbəkə problemlərinin simulyasiyası

Adətən proqram təminatı yaxşı İnternet kanalı olan test serverlərində sınaqdan keçirilir. Sərt istehsal mühitlərində işlər o qədər də rəvan gedə bilməz, buna görə bəzən zəif əlaqə şəraitində proqramları yoxlamaq lazımdır. Linux-da yardım proqramı bu cür şərtləri simulyasiya etmək tapşırığına kömək edəcəkdir. tc.

tc(abbr. Traffic Control tərəfindən) sistemdə şəbəkə paketlərinin ötürülməsini konfiqurasiya etməyə imkan verir. Bu yardım proqramı əla xüsusiyyətlərə malikdir, onlar haqqında daha çox oxuya bilərsiniz burada. Burada onlardan yalnız bir neçəsini nəzərdən keçirəcəyəm: biz istifadə etdiyimiz trafik cədvəli ilə maraqlanırıq qdisk, və qeyri-sabit şəbəkəni təqlid etməmiz lazım olduğundan, biz sinifsiz qdisc-dən istifadə edəcəyik netem.

Serverdə əks-səda serverinə başlayaq (mən istifadə etdim nmap-ncat):

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

Müştərinin serverlə qarşılıqlı əlaqəsinin hər addımında bütün vaxt ştamplarını ətraflı şəkildə göstərmək üçün sorğu göndərən sadə Python skripti yazdım. Sınaq echo serverimizə.

Müştəri mənbə kodu

#!/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

Gəlin onu işə salaq və interfeysdəki trafikə baxaq lo və port 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

Trafik zibilxanası

[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

Hər şey standartdır: üçtərəfli əl sıxma, iki dəfə cavab olaraq PSH / ACK və ACK - bu, müştəri ilə server arasında sorğu və cavab mübadiləsi və iki dəfə FIN / ACK və ACK - əlaqə tamamlandı.

Paket Gecikməsi

İndi gecikməni 500 millisaniyəyə təyin edək:

tc qdisc add dev lo root netem delay 500ms

Müştərini işə salırıq və görürük ki, indi skript 2 saniyə ərzində işləyir:

[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

Trafikdə nə var? Baxırıq:

Trafik zibilxanası

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

Müştəri və server arasındakı qarşılıqlı əlaqədə gözlənilən yarım saniyə gecikmənin meydana gəldiyini görə bilərsiniz. Gecikmə daha uzun olarsa, sistem özünü daha maraqlı aparır: nüvə bəzi TCP paketlərini yenidən göndərməyə başlayır. Gecikməni 1 saniyəyə dəyişək və trafikə baxaq (müştərinin çıxışını göstərməyəcəyəm, ümumi müddətdə gözlənilən 4 saniyə var):

tc qdisc change dev lo root netem delay 1s

Trafik zibilxanası

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

Görünür ki, müştəri iki dəfə SYN paketi, server isə iki dəfə SYN/ACK göndərib.

Sabit dəyərə əlavə olaraq, gecikmə dispersiyaya, paylama funksiyasına və korrelyasiyaya (əvvəlki partlayışın dəyəri ilə) təyin edilə bilər. Bu aşağıdakı kimi edilir:

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

Burada gecikməni 100 ilə 900 millisaniyə diapazonunda təyin etdik, dəyərlər normal paylanmaya görə seçiləcək və əvvəlki paket üçün gecikmə dəyəri ilə 50 faiz korrelyasiya olacaq.

Yəqin ki, istifadə etdiyim ilk əmrdə fərq etdiniz əlavə etməkvə sonra dəyişdirmək. Bu əmrlərin mənası göz qabağındadır, ona görə də mən yalnız orada olanları əlavə edəcəyəm. the, konfiqurasiyanı silə bilər.

Paket itkisi

İndi paket itkisi etməyə çalışaq. Sənədlərdən göründüyü kimi, bunu üç yolla etmək olar: müəyyən ehtimalla paketləri təsadüfi itirmək, paket itkisini hesablamaq üçün 2, 3 və ya 4 vəziyyətdən ibarət Markov zəncirindən istifadə etmək və ya Elliot-Gilbert modelindən istifadə etmək. Məqalədə mən birinci (ən sadə və aşkar) yolu nəzərdən keçirəcəyəm, ancaq başqaları haqqında oxuya bilərsiniz burada.

Gəlin 50% korrelyasiya ilə paketlərin 25% itkisi edək:

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

Təəssüf ki, tcpdump paketlərin itirilməsini bizə aydın şəkildə göstərə bilməyəcək, yalnız bunun həqiqətən işlədiyini güman edəcəyik. Buna əmin olmaq üçün artan və qeyri-sabit skript işləmə müddəti bizə kömək edəcəkdir. müştəri.py (dərhal və ya bəlkə də 20 saniyə ərzində icra oluna bilər), həmçinin təkrar ötürülən paketlərin sayı artır:

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

Paketlərə səs-küyün əlavə edilməsi

Paketlərin itirilməsi ilə yanaşı, onların zədələnməsini simulyasiya etmək mümkündür: səs-küy paketin təsadüfi mövqeyində görünəcək. Gəlin 50% ehtimalla və korrelyasiya olmayan paket korrupsiyasını edək:

tc qdisc change dev lo root netem corrupt 50%

Müştəri skriptini işə salırıq (maraqlı heç nə yoxdur, amma 2 saniyə çəkdi), trafikə baxırıq:

Trafik zibilxanası

[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

Görünür ki, bəzi paketlər yenidən göndərilib və metadata pozulmuş bir paket var: seçimlər [xeyr, naməlum-65 0x0a3dcf62eb3d, [pis seçim]>. Ancaq əsas odur ki, nəticədə hər şey düzgün getdi - TCP öz vəzifəsinin öhdəsindən gəldi.

Dublikat paketlər

Başqa nə edə bilərsən netem? Məsələn, paket itkisinin əksinə olan bir vəziyyəti simulyasiya etmək - paketlərin təkrarlanması. Bu əmr həm də 2 arqument götürür: ehtimal və korrelyasiya.

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

Paketlərin sırasının dəyişdirilməsi

Paketləri iki yolla qarışdıra bilərsiniz.

Paketlərin birinci hissəsində dərhal göndərilir, qalanları - müəyyən bir gecikmə ilə. Sənədlərdən nümunə:

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

25% ehtimalı (və 50% nisbəti ilə) paket dərhal göndəriləcək, qalanları 10 millisaniyəlik gecikmə ilə göndəriləcək.

İkinci yol, hər bir N-ci paketin dərhal müəyyən bir ehtimal (və korrelyasiya), qalanı isə müəyyən bir gecikmə ilə göndərilməsidir. Sənədlərdən nümunə:

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

Hər beşinci paketin gecikmədən göndərilmə şansı 25% olur.

Bant genişliyi dəyişikliyi

Adətən hər yerdə istinad edilir TBF, lakin köməyi ilə netem Siz həmçinin interfeysin bant genişliyini dəyişə bilərsiniz:

tc qdisc change dev lo root netem rate 56kbit

Bu komanda səfərlər edəcək localhost dial-up modem vasitəsilə internetdə gəzmək qədər ağrılı. Bit sürətini təyin etməklə yanaşı, siz həmçinin keçid qatının protokol modelini təqlid edə bilərsiniz: paket üçün yuxarı həddi, hüceyrə ölçüsünü və hüceyrə üçün yuxarı yükü təyin edin. Məsələn, simulyasiya edə bilərsiniz ATM və bit sürəti 56 kbps:

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

Bağlantı fasiləsini simulyasiya edin

Proqram təminatının qəbulu zamanı test planının digər vacib bəndi fasilələrdir. Bu vacibdir, çünki paylanmış sistemlərdə xidmətlərdən biri söndürüldükdə, qalanlar vaxtında başqalarına qayıtmalı və ya müştəriyə xəta qaytarmalı və heç bir halda cavab və ya əlaqə gözləməli deyillər.

Bunun bir neçə yolu var: məsələn, cavab verməyən istehzadan istifadə edin və ya sazlayıcıdan istifadə edərək prosesə qoşulun, kəsilmə nöqtəsini lazımi yerə qoyun və prosesin icrasını dayandırın (bu, yəqin ki, ən azğın yoldur) . Ancaq ən bariz olanlardan biri firewall portları və ya hostlarıdır. Bu bizə kömək edəcək iptables.

Nümayiş etmək üçün 12345 portunu firewall edəcəyik və müştəri skriptimizi işə salacağıq. Siz göndərəndə bu porta gedən paketləri və ya qəbuledicidə gələn paketləri qoruya bilərsiniz. Nümunələrimdə daxil olan paketlər təhlükəsizlik divarı ilə qorunacaq (biz zəncir INPUT və seçimdən istifadə edirik. -dport). Bu cür paketlər RST TCP bayrağı ilə DROP, REDD və ya REDD ola bilər və ya ICMP hostuna əlçatmaz ola bilər (əslində, standart davranış icmp-port-əlçatmaz, və hələ də cavab göndərmək imkanı var icmp-net-əlçatmaz, icmp-proto-əlçatmaz, icmp-net qadağandır и icmp-host qadağandır).

Burax

DROP ilə bir qayda varsa, paketlər sadəcə "yoxa çıxacaq".

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

Müştərini işə salırıq və onun serverə qoşulma mərhələsində asıldığını görürük. Gəlin trafikə baxaq:
Trafik zibilxanası

[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

Görünür ki, müştəri eksponent olaraq artan fasilə ilə SYN paketlərini göndərir. Beləliklə, müştəridə kiçik bir səhv tapdıq: metoddan istifadə etməlisiniz settimeout()müştərinin serverə qoşulmağa çalışacağı vaxtı məhdudlaşdırmaq üçün.

Dərhal qaydanı çıxarın:

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

Bütün qaydaları bir anda silə bilərsiniz:

iptables -F

Docker-dən istifadə edirsinizsə və konteynerə gedən bütün trafiki firewall etməlisinizsə, bunu belə edə bilərsiniz:

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

RAZILA

İndi oxşar qayda əlavə edək, lakin REJECT ilə:

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

Müştəri bir saniyədən sonra xəta ilə çıxış edir [Səhv 111] Bağlantı rədd edildi. ICMP trafikinə baxırıq:

[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

Müştərinin iki dəfə aldığını görmək olar port əlçatmazdır sonra xəta ilə bitdi.

tcp-reset ilə REDD EDİN

Bir seçim əlavə etməyə çalışaq --tcp-reset ilə rədd et:

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

Bu halda, müştəri dərhal xəta ilə çıxış edir, çünki ilk sorğu RST paketini alıb:

[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 ilə REDD EDİN

REJECT üçün başqa bir istifadə halına cəhd edək:

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

Müştəri bir saniyədən sonra xəta ilə çıxış edir [Səhv 113] Ev sahibi üçün marşrut yoxdur, ICMP trafikində görürük ICMP host 127.0.0.1 əlçatmazdır.

REDD ET parametrlərinin qalanını da sınaya bilərsiniz, lakin mən bunlara diqqət yetirəcəyəm :)

Sorğunun vaxt aşımını simulyasiya edin

Başqa bir vəziyyət, müştərinin serverə qoşula bildiyi, lakin ona sorğu göndərə bilməməsidir. Filtrləmə dərhal başlamaması üçün paketləri necə süzmək olar? Müştəri və server arasında hər hansı bir əlaqənin trafikinə baxsanız, əlaqə qurarkən yalnız SYN və ACK bayraqlarından istifadə edildiyini, lakin məlumat mübadiləsi zamanı PSH bayrağının sonuncu sorğu paketində olacağını görəcəksiniz. Buferləmənin qarşısını almaq üçün avtomatik olaraq təyin edilir. Siz bu məlumatdan PSH bayrağını ehtiva edən paketlərdən başqa bütün paketlərdən keçəcək filtr yaratmaq üçün istifadə edə bilərsiniz. Beləliklə, əlaqə qurulacaq, lakin müştəri serverə məlumat göndərə bilməyəcək.

Burax

DROP üçün əmr belə görünür:

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

Biz müştərini işə salırıq və trafikə baxırıq:

Trafik zibilxanası

[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

Bağlantının qurulduğunu və müştərinin serverə məlumat göndərə bilməyəcəyini görürük.

RAZILA

Bu vəziyyətdə davranış eyni olacaq: müştəri sorğu göndərə bilməyəcək, ancaq qəbul edəcək ICMP 127.0.0.1 tcp port 12345 əlçatmazdır və sorğunun eksponent olaraq təkrar göndərilməsi arasındakı vaxtı artırın. Komanda bu kimi görünür:

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

tcp-reset ilə REDD EDİN

Komanda bu kimi görünür:

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

İstifadə edərkən bunu artıq bilirik --tcp-reset ilə rədd et müştəri cavab olaraq RST paketi alacaq, buna görə də davranışı proqnozlaşdırmaq olar: qurulmuş əlaqədə RST paketinin alınması o deməkdir ki, rozetka digər tərəfdən gözlənilmədən bağlanıb, yəni müştəri qəbul etməlidir. Bağlantı həmyaşıd tərəfindən sıfırlandı. Skriptimizi işə salıb yoxlayaq. Və trafik belə görünəcək:

Trafik zibilxanası

[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 ilə REDD EDİN

Düşünürəm ki, komandanın necə görünəcəyi artıq hər kəsə aydındır 🙂 Bu halda müştərinin davranışı sadə RƏDƏT ilə olduğundan bir qədər fərqli olacaq: müştəri paketi yenidən göndərmək cəhdləri arasında fasiləni artırmayacaq.

[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

Buraxılış

Dondurulmuş müştəri və ya server ilə xidmətin qarşılıqlı əlaqəsini yoxlamaq üçün istehza yazmaq lazım deyil, bəzən Linux-da mövcud olan standart yardım proqramlarından istifadə etmək kifayətdir.

Məqalədə müzakirə olunan yardım proqramları təsvir ediləndən daha çox xüsusiyyətlərə malikdir, buna görə də onlardan istifadə etmək üçün öz seçimlərinizi tapa bilərsiniz. Şəxsən məndə həmişə yazdıqlarım kifayət qədərdir (əslində daha az). Əgər siz şirkətinizdə test zamanı bu və ya oxşar yardım proqramlarından istifadə edirsinizsə, zəhmət olmasa necə dəqiq yazın. Əgər yoxsa, ümid edirəm ki, təklif olunan üsullarla şəbəkə problemləri qarşısında onu yoxlamaq qərarına gəlsəniz, proqram təminatınız daha yaxşı olacaq.

Mənbə: www.habr.com

Добавить комментарий