Simulering af netværksproblemer i Linux

Hej alle sammen, mit navn er Sasha, jeg leder backend-test hos FunCorp. Vi har som mange andre implementeret en serviceorienteret arkitektur. På den ene side letter dette arbejdet, fordi... Det er nemmere at teste hver tjeneste for sig, men på den anden side er der behov for at teste tjenesternes interaktion med hinanden, hvilket ofte sker over netværket.

I denne artikel vil jeg tale om to værktøjer, der kan bruges til at kontrollere grundlæggende scenarier, der beskriver driften af ​​en applikation i nærvær af netværksproblemer.

Simulering af netværksproblemer i Linux

Simulering af netværksproblemer

Typisk testes software på testservere med en god internetforbindelse. I barske produktionsmiljøer er tingene måske ikke så glatte, så nogle gange er du nødt til at teste programmer under dårlige forbindelsesforhold. På Linux vil hjælpeprogrammet hjælpe med opgaven med at simulere sådanne forhold tc.

tc(abbr. fra Trafikkontrol) giver dig mulighed for at konfigurere transmissionen af ​​netværkspakker i systemet. Dette værktøj har store muligheder, du kan læse mere om dem her. Her vil jeg kun overveje nogle få af dem: vi er interesserede i trafikplanlægning, som vi bruger til qdisc, og da vi skal efterligne et ustabilt netværk, vil vi bruge klasseløs qdisc netem.

Lad os starte en ekkoserver på serveren (jeg brugte nmap-ncat):

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

For at få vist alle tidsstempler i detaljer ved hvert trin af interaktion mellem klienten og serveren, skrev jeg et simpelt Python-script, der sender en anmodning Test til vores ekkoserver.

Klientens kildekode

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

Lad os starte det og se på trafikken på grænsefladen lo og 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

Trafikplads

[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

Alt er standard: et tre-vejs håndtryk, PSH/ACK og ACK som svar to gange - dette er udvekslingen af ​​anmodning og svar mellem klienten og serveren, og FIN/ACK og ACK to gange - fuldfører forbindelsen.

Pakkeforsinkelse

Lad os nu indstille forsinkelsen til 500 millisekunder:

tc qdisc add dev lo root netem delay 500ms

Vi starter klienten og ser, at scriptet nu kører 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

Hvad er der i trafikken? Lad os se:

Trafikplads

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, at den forventede forsinkelse på et halvt sekund er dukket op i interaktionen mellem klienten og serveren. Systemet opfører sig meget mere interessant, hvis forsinkelsen er større: kernen begynder at sende nogle TCP-pakker igen. Lad os ændre forsinkelsen til 1 sekund og se på trafikken (jeg vil ikke vise klientens output, der er de forventede 4 sekunder i samlet varighed):

tc qdisc change dev lo root netem delay 1s

Trafikplads

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, at klienten sendte en SYN-pakke to gange, og serveren sendte en SYN/ACK to gange.

Ud over en konstant værdi kan forsinkelsen indstilles til en afvigelse, en fordelingsfunktion og en korrelation (med værdien for den forrige pakke). Dette gøres som følger:

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

Her har vi sat forsinkelsen mellem 100 og 900 millisekunder, værdierne vil blive valgt efter en normalfordeling og der vil være en 50% korrelation med forsinkelsesværdien for den forrige pakke.

Du har måske bemærket det i den første kommando, jeg brugte tilføjeog derefter lave om. Betydningen af ​​disse kommandoer er indlysende, så jeg vil bare tilføje, at der er mere den, som kan bruges til at fjerne konfigurationen.

Pakketab

Lad os nu prøve at gøre pakketab. Som det fremgår af dokumentationen, kan dette gøres på tre måder: at miste pakker tilfældigt med en vis sandsynlighed, ved at bruge en Markov-kæde på 2, 3 eller 4 tilstande til at beregne pakketab, eller ved at bruge Elliott-Gilbert-modellen. I artiklen vil jeg overveje den første (simpelste og mest oplagte) metode, og du kan læse om andre her.

Lad os tabe 50 % af pakker med en korrelation på 25 %:

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

Desværre tcpdump vil ikke være i stand til tydeligt at vise os tabet af pakker, vi vil kun antage, at det virkelig virker. Og den øgede og ustabile køretid for scriptet vil hjælpe os med at bekræfte dette. client.py (kan fuldføres øjeblikkeligt, eller måske på 20 sekunder), samt et øget antal gentransmitterede pakker:

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

Tilføjelse af støj til pakker

Ud over pakketab kan du simulere pakkeskade: støj vil optræde ved en tilfældig pakkeposition. Lad os lave pakkeskade med 50 % sandsynlighed og uden korrelation:

tc qdisc change dev lo root netem corrupt 50%

Vi kører klientscriptet (intet interessant der, men det tog 2 sekunder at fuldføre), se på trafikken:

Trafikplads

[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, at nogle pakker blev sendt gentagne gange, og der er en pakke med ødelagte metadata: muligheder [nop,ukendt-65 0x0a3dcf62eb3d,[dårlig opt]>. Men det vigtigste er, at alt i sidste ende fungerede korrekt - TCP klarede sin opgave.

Pakkeduplikering

Hvad kan du ellers gøre med netem? Simuler f.eks. den omvendte situation med pakketab - pakkeduplikering. Denne kommando tager også 2 argumenter: sandsynlighed og korrelation.

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

Ændring af rækkefølgen af ​​pakker

Du kan blande poserne på to måder.

I den første sendes nogle pakker med det samme, resten med en specificeret forsinkelse. Eksempel fra dokumentationen:

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

Med en sandsynlighed på 25% (og en korrelation på 50%) vil pakken blive sendt med det samme, resten sendes med en forsinkelse på 10 millisekunder.

Den anden metode er, når hver N'te pakke sendes øjeblikkeligt med en given sandsynlighed (og korrelation), og resten med en given forsinkelse. Eksempel fra dokumentationen:

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

Hver femte pakke har 25 % chance for at blive sendt uden forsinkelse.

Ændring af båndbredde

Normalt overalt, hvor de henviser til TBF, men med hjælp netem Du kan også ændre grænsefladebåndbredden:

tc qdisc change dev lo root netem rate 56kbit

Dette hold vil tage rundt localhost lige så smertefuldt som at surfe på internettet via et opkaldsmodem. Ud over at indstille bithastigheden kan du også emulere linklagsprotokolmodellen: Indstil overhead for pakken, cellestørrelse og overhead for cellen. Dette kan f.eks. simuleres Pengeautomat og bithastighed 56 kbit/sek.:

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

Simulering af forbindelsestimeout

Et andet vigtigt punkt i testplanen ved accept af software er timeouts. Dette er vigtigt, fordi i distribuerede systemer, når en af ​​tjenesterne er deaktiveret, skal de andre falde tilbage til de andre i tide eller returnere en fejl til klienten, og de må under ingen omstændigheder blot hænge og vente på svar eller en forbindelse skal etableres.

Der er flere måder at gøre dette på: Brug for eksempel en mock, der ikke reagerer, eller opret forbindelse til processen ved hjælp af en debugger, sæt et brudpunkt på det rigtige sted og stop processen (dette er nok den mest perverse måde). Men en af ​​de mest oplagte er firewall-porte eller værter. Det vil hjælpe os med dette iptables.

Til demonstration vil vi firewallport 12345 og køre vores klientscript. Du kan firewall udgående pakker til denne port hos afsenderen eller indgående pakker ved modtageren. I mine eksempler vil indgående pakker være firewalled (vi bruger kæde INPUT og optionen --dport). Sådanne pakker kan være DROP, REJECT eller REJECT med TCP-flaget RST, eller med ICMP-vært, der ikke kan nås (faktisk er standardadfærden icmp-port-unreachable, og der er også mulighed for at sende et svar icmp-net-uopnåelig, icmp-proto-unreachable, icmp-net-forbudt и icmp-host-forbudt).

DROP

Hvis der er en regel med DROP, vil pakker simpelthen "forsvinde".

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

Vi starter klienten og ser, at den fryser på tidspunktet for tilslutning til serveren. Lad os se på trafikken:
Trafikplads

[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, at klienten sender SYN-pakker med en eksponentielt stigende timeout. Så vi fandt en lille fejl i klienten: du skal bruge metoden settimeout()for at begrænse den tid, hvor klienten vil forsøge at oprette forbindelse til serveren.

Vi fjerner straks reglen:

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

Du kan slette alle regler på én gang:

iptables -F

Hvis du bruger Docker, og du har brug for at firewall al trafik, der går til containeren, kan du gøre det som følger:

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

AFVIS

Lad os nu tilføje en lignende regel, men med REJECT:

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

Klienten afslutter efter et sekund med en fejl [Errno 111] Forbindelse nægtet. Lad os se på ICMP-trafikken:

[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, at klienten modtog to gange havn uopnåelig og endte så med en fejl.

AFVIS med tcp-reset

Lad os prøve at tilføje muligheden --reject-with tcp-reset:

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

I dette tilfælde afsluttes klienten straks med en fejl, fordi den første anmodning modtog en RST-pakke:

[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

AFVIS med icmp-host-unreachable

Lad os prøve en anden mulighed for at bruge REJECT:

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

Klienten afslutter efter et sekund med en fejl [Errno 113] Ingen rute til værten, ser vi i ICMP-trafik ICMP-vært 127.0.0.1 kan ikke nås.

Du kan også prøve de andre REJECT-parametre, og jeg vil fokusere på disse :)

Simulering af anmodningstimeout

En anden situation er, når klienten var i stand til at oprette forbindelse til serveren, men ikke kan sende en anmodning til den. Hvordan filtrerer man pakker, så filtreringen ikke starter med det samme? Hvis du ser på trafikken af ​​enhver kommunikation mellem klienten og serveren, vil du bemærke, at når du etablerer en forbindelse, bruges kun SYN- og ACK-flag, men ved udveksling af data vil den sidste anmodningspakke indeholde PSH-flaget. Den installeres automatisk for at undgå buffering. Du kan bruge denne information til at oprette et filter: det vil tillade alle pakker undtagen dem, der indeholder PSH-flaget. Forbindelsen vil således blive etableret, men klienten vil ikke være i stand til at sende data til serveren.

DROP

For DROP ville kommandoen se sådan ud:

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

Start klienten og se trafikken:

Trafikplads

[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, at forbindelsen er etableret, og klienten kan ikke sende data til serveren.

AFVIS

I dette tilfælde vil adfærden være den samme: klienten vil ikke være i stand til at sende anmodningen, men vil modtage ICMP 127.0.0.1 tcp-port 12345 kan ikke nås og øge tiden mellem genindsendelse af anmodninger eksponentielt. Kommandoen ser sådan ud:

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

AFVIS med tcp-reset

Kommandoen ser sådan ud:

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

Det ved vi allerede, når vi bruger --reject-with tcp-reset klienten vil modtage en RST-pakke som svar, så adfærden kan forudsiges: modtagelse af en RST-pakke, mens forbindelsen er etableret, betyder, at stikket uventet lukkes på den anden side, hvilket betyder, at klienten skal modtage Forbindelsen er nulstillet af brugeren. Lad os køre vores script og sørge for dette. Og sådan vil trafikken se ud:

Trafikplads

[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

AFVIS med icmp-host-unreachable

Jeg tror, ​​at det allerede er indlysende for alle, hvordan kommandoen vil se ud :) Klientens adfærd i dette tilfælde vil være en smule anderledes end ved en simpel AFVISNING: Klienten vil ikke øge timeoutet mellem forsøg på at sende pakken igen.

[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

Output

Det er ikke nødvendigt at skrive en mock for at teste interaktionen af ​​en tjeneste med en hængt klient eller server; nogle gange er det nok at bruge standardværktøjer, der findes i Linux.

De hjælpeprogrammer, der diskuteres i artiklen, har endnu flere muligheder end beskrevet, så du kan komme med nogle af dine egne muligheder for at bruge dem. Personligt har jeg altid nok af det, jeg skrev om (faktisk endnu mindre). Hvis du bruger disse eller lignende hjælpeprogrammer til at teste i din virksomhed, så skriv venligst hvordan. Hvis ikke, så håber jeg, at din software bliver bedre, hvis du beslutter dig for at teste den under netværksproblemer ved hjælp af de foreslåede metoder.

Kilde: www.habr.com

Tilføj en kommentar