Simulerar nätverksproblem i Linux

Hej alla, jag heter Sasha, jag leder backend-testning på FunCorp. Vi har, liksom många andra, implementerat en tjänsteorienterad arkitektur. Å ena sidan förenklar detta arbetet, eftersom... Det är lättare att testa varje tjänst separat, men å andra sidan finns det ett behov av att testa interaktionen av tjänster med varandra, vilket ofta sker över nätverket.

I den här artikeln kommer jag att prata om två verktyg som kan användas för att kontrollera grundläggande scenarier som beskriver driften av en applikation i närvaro av nätverksproblem.

Simulerar nätverksproblem i Linux

Simulerar nätverksproblem

Vanligtvis testas programvara på testservrar med en bra internetanslutning. I hårda produktionsmiljöer är det kanske inte så smidigt, så ibland behöver du testa program under dåliga anslutningsförhållanden. På Linux kommer verktyget att hjälpa till med uppgiften att simulera sådana förhållanden tc.

tc(förkortning. från Trafikverket) låter dig konfigurera överföringen av nätverkspaket i systemet. Det här verktyget har fantastiska möjligheter, du kan läsa mer om dem här. Här kommer jag bara att överväga ett fåtal av dem: vi är intresserade av trafikschemaläggning, som vi använder qdisc, och eftersom vi behöver emulera ett instabilt nätverk kommer vi att använda klasslös qdisc netem.

Låt oss starta en ekoserver på servern (jag använde nmap-ncat):

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

För att i detalj visa alla tidsstämplar vid varje steg av interaktion mellan klienten och servern skrev jag ett enkelt Python-skript som skickar en begäran Testa till vår ekoserver.

Klientens källkod

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

Låt oss starta det och titta på trafiken på gränssnittet lo och 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

Trafikdump

[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

Allt är standard: en trevägshandskakning, PSH/ACK och ACK som svar två gånger - detta är utbytet av begäran och svar mellan klienten och servern, och FIN/ACK och ACK två gånger - slutföra anslutningen.

Paketfördröjning

Låt oss nu ställa in fördröjningen till 500 millisekunder:

tc qdisc add dev lo root netem delay 500ms

Vi startar klienten och ser att skriptet nu körs i 2 sekunder:

[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

Vad är det i trafiken? Vi kollar:

Trafikdump

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

Du kan se att den förväntade fördröjningen på en halv sekund har dykt upp i interaktionen mellan klienten och servern. Systemet beter sig mycket mer intressant om fördröjningen är större: kärnan börjar skicka om några TCP-paket. Låt oss ändra fördröjningen till 1 sekund och titta på trafiken (jag kommer inte att visa klientens utdata, det finns de förväntade 4 sekunderna i total varaktighet):

tc qdisc change dev lo root netem delay 1s

Trafikdump

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

Det kan ses att klienten skickade ett SYN-paket två gånger och servern skickade ett SYN/ACK två gånger.

Förutom ett konstant värde kan fördröjningen ställas in på en avvikelse, en fördelningsfunktion och en korrelation (med värdet för föregående paket). Detta görs på följande sätt:

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

Här har vi ställt in fördröjningen mellan 100 och 900 millisekunder, värdena kommer att väljas enligt en normalfördelning och det kommer att finnas en 50% korrelation med fördröjningsvärdet för föregående paket.

Du kanske har märkt det i det första kommandot jag använde lägga tilloch då byta. Innebörden av dessa kommandon är uppenbar, så jag lägger bara till att det finns mer del, som kan användas för att ta bort konfigurationen.

Paketförlust

Låt oss nu försöka göra paketförlust. Som framgår av dokumentationen kan detta göras på tre sätt: att förlora paket slumpmässigt med viss sannolikhet, använda en Markov-kedja med 2, 3 eller 4 tillstånd för att beräkna paketförlust, eller använda Elliott-Gilbert-modellen. I artikeln kommer jag att överväga den första (enklaste och mest uppenbara) metoden, och du kan läsa om andra här.

Låt oss göra förlusten av 50 % av paketen med en korrelation på 25 %:

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

Olyckligtvis, tcpdump kommer inte att tydligt kunna visa oss förlusten av paket, vi kommer bara att anta att det verkligen fungerar. Och den ökade och instabila körtiden för skriptet kommer att hjälpa oss att verifiera detta. client.py (kan slutföras omedelbart, eller kanske på 20 sekunder), samt ett ökat antal återsända paket:

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

Lägger till brus till paket

Förutom paketförlust kan du simulera paketskador: brus kommer att uppstå vid en slumpmässig paketposition. Låt oss göra paketskador med 50 % sannolikhet och utan korrelation:

tc qdisc change dev lo root netem corrupt 50%

Vi kör klientskriptet (inget intressant där, men det tog 2 sekunder att slutföra), titta på trafiken:

Trafikdump

[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

Det kan ses att vissa paket skickades upprepade gånger och det finns ett paket med trasig metadata: alternativ [nop,unknown-65 0x0a3dcf62eb3d,[dålig opt]>. Men det viktigaste är att allt i slutändan fungerade korrekt - TCP klarade av sin uppgift.

Paketduplicering

Vad mer kan du göra med netem? Simulera till exempel den omvända situationen för paketförlust – paketduplicering. Detta kommando tar också två argument: sannolikhet och korrelation.

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

Ändra ordning på paket

Du kan blanda påsarna på två sätt.

I det första skickas vissa paket omedelbart, resten med en viss fördröjning. Exempel från dokumentationen:

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

Med en sannolikhet på 25% (och en korrelation på 50%) kommer paketet att skickas omedelbart, resten kommer att skickas med en fördröjning på 10 millisekunder.

Den andra metoden är när varje N:te paket skickas omedelbart med en given sannolikhet (och korrelation), och resten med en given fördröjning. Exempel från dokumentationen:

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

Vart femte paket har 25 % chans att skickas utan dröjsmål.

Ändra bandbredd

Vanligtvis överallt de refererar till TBF, men med hjälp netem Du kan också ändra gränssnittets bandbredd:

tc qdisc change dev lo root netem rate 56kbit

Det här laget kommer att göra vandringar runt lokalvärd lika smärtsamt som att surfa på Internet via ett uppringt modem. Förutom att ställa in bithastigheten kan du också emulera länklagerprotokollmodellen: ställ in overhead för paketet, cellstorlek och overhead för cellen. Detta kan till exempel simuleras bankomat och bithastighet 56 kbit/sek:

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

Simulering av timeout för anslutning

En annan viktig punkt i testplanen när man accepterar programvara är timeouts. Detta är viktigt eftersom i distribuerade system, när en av tjänsterna är inaktiverad, måste de andra falla tillbaka till de andra i tid eller returnera ett fel till klienten, och i inget fall bör de helt enkelt hänga, vänta på ett svar eller en anslutning att bli etablerad.

Det finns flera sätt att göra detta: använd till exempel en låtsas som inte svarar, eller anslut till processen med en debugger, sätt en brytpunkt på rätt plats och stoppa processen (detta är förmodligen det mest perversa sättet). Men en av de mest uppenbara är att brandväggsportar eller värdar. Det kommer att hjälpa oss med detta iptables.

För demonstration kommer vi brandväggsport 12345 och köra vårt klientskript. Du kan brandvägga utgående paket till denna port hos avsändaren eller inkommande paket vid mottagaren. I mina exempel kommer inkommande paket att vara brandväggiga (vi använder chain INPUT och alternativet --dport). Sådana paket kan vara DROP, REJECT eller REJECT med TCP-flaggan RST, eller med ICMP-värd som inte kan nås (i själva verket är standardbeteendet icmp-port-unreachable, och det finns även möjlighet att skicka ett svar icmp-net-unreachable, icmp-proto-unreachable, icmp-net-förbjudet и icmp-host-förbjudet).

FALLA

Om det finns en regel med DROP kommer paket helt enkelt att "försvinna".

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

Vi startar klienten och ser att den fryser vid anslutning till servern. Låt oss titta på trafiken:
Trafikdump

[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

Det kan ses att klienten skickar SYN-paket med en exponentiellt ökande timeout. Så vi hittade en liten bugg i klienten: du måste använda metoden settimeout()för att begränsa den tid under vilken klienten försöker ansluta till servern.

Vi tar omedelbart bort regeln:

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

Du kan ta bort alla regler på en gång:

iptables -F

Om du använder Docker och du behöver brandvägga all trafik som går till behållaren, kan du göra det på följande sätt:

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

AVVISA

Låt oss nu lägga till en liknande regel, men med REJECT:

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

Klienten avslutas efter en sekund med ett fel [Errnr 111] Anslutningen nekades. Låt oss titta på ICMP-trafiken:

[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

Det kan ses att klienten fått två gånger hamnen oåtkomlig och slutade sedan med ett fel.

AVVISA med tcp-reset

Låt oss försöka lägga till alternativet --reject-with tcp-reset:

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

I det här fallet avslutas klienten omedelbart med ett fel, eftersom den första begäran fick ett RST-paket:

[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

AVVISA med icmp-host-unreachable

Låt oss prova ett annat alternativ för att använda REJECT:

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

Klienten avslutas efter en sekund med ett fel [Errnr 113] Ingen väg till värd, ser vi i ICMP-trafik ICMP-värd 127.0.0.1 går inte att nå.

Du kan också prova de andra REJECT-parametrarna, så fokuserar jag på dessa :)

Simulerar timeout för begäran

En annan situation är när klienten kunde ansluta till servern, men inte kan skicka en begäran till den. Hur filtrerar man paket så att filtreringen inte startar direkt? Om du tittar på trafiken för all kommunikation mellan klienten och servern kommer du att märka att när du upprättar en anslutning, används endast SYN- och ACK-flaggor, men vid utbyte av data kommer det sista begäran-paketet att innehålla PSH-flaggan. Den installeras automatiskt för att undvika buffring. Du kan använda denna information för att skapa ett filter: det tillåter alla paket utom de som innehåller PSH-flaggan. Således kommer anslutningen att upprättas, men klienten kommer inte att kunna skicka data till servern.

FALLA

För DROP skulle kommandot se ut så här:

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

Starta klienten och titta på trafiken:

Trafikdump

[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

Vi ser att anslutningen är upprättad och klienten kan inte skicka data till servern.

AVVISA

I det här fallet kommer beteendet att vara detsamma: klienten kommer inte att kunna skicka förfrågan, men kommer att ta emot ICMP 127.0.0.1 tcp-port 12345 går inte att nå och öka tiden mellan återsändningar av begäran exponentiellt. Kommandot ser ut så här:

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

AVVISA med tcp-reset

Kommandot ser ut så här:

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

Det vet vi redan när vi använder det --reject-with tcp-reset klienten kommer att ta emot ett RST-paket som svar, så beteendet kan förutsägas: att ta emot ett RST-paket medan anslutningen är upprättad innebär att uttaget oväntat stängs på andra sidan, vilket betyder att klienten bör ta emot Anslutningen återställd av peer. Låt oss köra vårt manus och se till detta. Och så här kommer trafiken att se ut:

Trafikdump

[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

AVVISA med icmp-host-unreachable

Jag tror att det redan är uppenbart för alla hur kommandot kommer att se ut :) Klientens beteende i det här fallet kommer att skilja sig något från det med en enkel AVVISNING: klienten kommer inte att öka tidsgränsen mellan försöken att skicka om paketet.

[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

Utgång

Det är inte nödvändigt att skriva en låtsas för att testa interaktionen av en tjänst med en hängd klient eller server; ibland räcker det med att använda standardverktyg som finns i Linux.

De verktyg som diskuteras i artikeln har ännu fler funktioner än vad som beskrevs, så du kan komma på några av dina egna alternativ för att använda dem. Själv har jag alltid tillräckligt med det jag skrivit om (faktiskt ännu mindre). Om du använder dessa eller liknande verktyg för att testa i ditt företag, skriv exakt hur. Om inte, hoppas jag att din programvara kommer att bli bättre om du bestämmer dig för att testa den under nätverksproblem med hjälp av de föreslagna metoderna.

Källa: will.com

Lägg en kommentar