Simulante retajn problemojn en Linukso

Saluton al ĉiuj, mia nomo estas Sasha, mi gvidas backend-testadon ĉe FunCorp. Ni, kiel multaj aliaj, efektivigis servo-orientitan arkitekturon. Unuflanke tio simpligas la laboron, ĉar... Estas pli facile testi ĉiun servon aparte, sed aliflanke, necesas testi la interagadon de servoj unu kun la alia, kiu ofte okazas tra la reto.

En ĉi tiu artikolo, mi parolos pri du utilecoj, kiuj povas esti uzataj por kontroli bazajn scenarojn, kiuj priskribas la funkciadon de aplikaĵo en ĉeesto de retaj problemoj.

Simulante retajn problemojn en Linukso

Simulante retajn problemojn

Tipe, programaro estas provita sur testaj serviloj kun bona interreta konekto. En severaj produktadmedioj, aferoj eble ne estas tiel glataj, do foje vi devas testi programojn en malbonaj konektkondiĉoj. En Linukso, la utileco helpos kun la tasko simuli tiajn kondiĉojn tc.

tc(abr. de Trafika Kontrolo) permesas al vi agordi la transdonon de retaj pakoj en la sistemo. Ĉi tiu utileco havas grandajn kapablojn, vi povas legi pli pri ili tie. Ĉi tie mi konsideros nur kelkajn el ili: ni interesiĝas pri trafika planado, por kiu ni uzas qdisko, kaj ĉar ni bezonas kopii malstabilan reton, ni uzos senklasan qdisc netem.

Ni lanĉu eĥservilon sur la servilo (mi uzis nmap-ncat):

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

Por montri detale ĉiujn tempomarkojn ĉe ĉiu paŝo de interago inter la kliento kaj la servilo, mi skribis simplan Python-skripton, kiu sendas peton. testo al nia eĥservilo.

Klienta fontkodo

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

Ni lanĉu ĝin kaj rigardu la trafikon sur la interfaco lo kaj haveno 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

Trafika rubejo

[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

Ĉio estas norma: tridirekta manpremo, PSH/ACK kaj ACK en respondo dufoje - tio estas la interŝanĝo de peto kaj respondo inter la kliento kaj servilo, kaj FIN/ACK kaj ACK dufoje - kompletigante la konekton.

Paka prokrasto

Nun ni agordu la prokraston al 500 milisekundoj:

tc qdisc add dev lo root netem delay 500ms

Ni lanĉas la klienton kaj vidas, ke la skripto nun funkcias dum 2 sekundoj:

[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

Kio estas en la trafiko? Ni rigardu:

Trafika rubejo

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

Vi povas vidi, ke la atendata malfruo de duona sekundo aperis en la interago inter la kliento kaj la servilo. La sistemo kondutas multe pli interese se la malfruo estas pli granda: la kerno komencas resendi kelkajn TCP-pakaĵojn. Ni ŝanĝu la prokraston al 1 sekundo kaj rigardu la trafikon (mi ne montros la eliron de la kliento, estas la atendataj 4 sekundoj en totala daŭro):

tc qdisc change dev lo root netem delay 1s

Trafika rubejo

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

Oni povas vidi, ke la kliento sendis SYN-pakaĵon dufoje, kaj la servilo sendis SYN/ACK dufoje.

Aldone al konstanta valoro, la prokrasto povas esti agordita al devio, distribua funkcio, kaj korelacio (kun la valoro por la antaŭa pakaĵeto). Ĉi tio estas farita jene:

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

Ĉi tie ni starigis la prokraston inter 100 kaj 900 milisekundoj, la valoroj estos elektitaj laŭ normala distribuo kaj estos 50% korelacio kun la prokrasta valoro por la antaŭa pako.

Vi eble rimarkis tion en la unua ordono, kiun mi uzis aldoni, kaj tiam ŝanĝo. La signifo de ĉi tiuj ordonoj estas evidenta, do mi nur aldonos, ke estas pli de la, kiu povas esti uzata por forigi la agordon.

Paka Perdo

Ni nun provu fari pakperdon. Kiel videblas el la dokumentaro, ĉi tio povas esti farita laŭ tri manieroj: perdi pakaĵetojn hazarde kun iu verŝajneco, uzante Markov-ĉenon de 2, 3 aŭ 4 ŝtatoj por kalkuli pakaĵetperdon, aŭ uzante la Elliott-Gilbert-modelon. En la artikolo mi konsideros la unuan (plej simplan kaj evidentan) metodon, kaj vi povas legi pri aliaj tie.

Ni faru la perdon de 50% de pakoj kun korelacio de 25%:

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

Bedaŭrinde, tcpdump ne povos klare montri al ni la perdon de pakaĵoj, ni nur supozos, ke ĝi vere funkcias. Kaj la pliigita kaj malstabila rultempo de la skripto helpos nin kontroli ĉi tion. kliento.py (povas esti kompletigita tuj, aŭ eble en 20 sekundoj), same kiel pliigita nombro da reelsenditaj pakaĵetoj:

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

Aldonante bruon al pakoj

Krom paka perdo, vi povas simuli pakaĵdamaĝon: bruo aperos ĉe hazarda paka pozicio. Ni faru pakaĵdamaĝon kun 50% probableco kaj sen korelacio:

tc qdisc change dev lo root netem corrupt 50%

Ni rulas la klientan skripton (nenion interesa tie, sed necesis 2 sekundoj por kompletigi), rigardu la trafikon:

Trafika rubejo

[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

Videblas, ke kelkaj pakaĵoj estis senditaj plurfoje kaj estas unu pako kun rompitaj metadatenoj: opcioj [nep,nekonata-65 0x0a3dcf62eb3d,[malbona elekto]>. Sed la ĉefa afero estas, ke finfine ĉio funkciis ĝuste - TCP traktis sian taskon.

Duobligo de paketoj

Kion alian vi povas fari netem? Ekzemple, simulu la inversan situacion de paka perdo—pakaĵduobligo. Ĉi tiu komando ankaŭ prenas 2 argumentojn: probablo kaj korelacio.

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

Ŝanĝi la ordon de pakoj

Vi povas miksi la sakojn en du manieroj.

En la unua, kelkaj pakaĵoj estas senditaj tuj, la ceteraj kun difinita prokrasto. Ekzemplo el la dokumentado:

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

Kun probableco de 25% (kaj korelacio de 50%) la pako estos sendita tuj, la resto estos sendita kun malfruo de 10 milisekundoj.

La dua metodo estas kiam ĉiu N-a pakaĵeto estas sendita tuj kun antaŭfiksita probableco (kaj korelacio), kaj la resto kun antaŭfiksita prokrasto. Ekzemplo el la dokumentado:

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

Ĉiu kvina pakaĵo havas 25% ŝancon esti sendita senprokraste.

Ŝanĝanta Bandwidth

Kutime ĉie ili referencas TBF, sed kun la helpo netem Vi ankaŭ povas ŝanĝi la interfacan bendolarĝon:

tc qdisc change dev lo root netem rate 56kbit

Ĉi tiu teamo faros vojaĝojn ĉirkaŭe localhost same dolora kiel navigado per interreto per telefona modemo. Krom agordi la bitratecon, vi ankaŭ povas kopii la ligtavolan protokolmodelon: agordu la supran koston por la pakaĵo, la ĉelan grandecon kaj la supran por la ĉelo. Ekzemple, ĉi tio povas esti simulita ATM kaj bitrapideco 56 kbit/sec:

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

Simulado de konektotempo

Alia grava punkto en la testa plano kiam oni akceptas softvaron, estas tempotempoj. Ĉi tio gravas ĉar en distribuitaj sistemoj, kiam unu el la servoj estas malfunkciigita, la aliaj devas ĝustatempe reveni al la aliaj aŭ redoni eraron al la kliento, kaj en neniu kazo ili simple pendigu, atendante respondon aŭ konekton. esti establita.

Estas pluraj manieroj fari tion: ekzemple, uzu mokon, kiu ne respondas, aŭ konekti al la procezo per erarseĉilo, meti rompopunkton en la ĝusta loko kaj ĉesigi la procezon (tio verŝajne estas la plej perversa maniero). Sed unu el la plej evidentaj estas al fajroŝirmilaj havenoj aŭ gastigantoj. Ĝi helpos nin kun ĉi tio iptables.

Por pruvo, ni fajroŝirmis havenon 12345 kaj rulos nian klientan skripton. Vi povas fajroŝirmigi elirantajn pakaĵojn al ĉi tiu haveno ĉe la sendinto aŭ envenantajn pakaĵojn ĉe la ricevilo. En miaj ekzemploj, alvenantaj pakaĵoj estos fajroŝirmitaj (ni uzas ĉenan INPUT kaj la opcion --dport). Tiaj pakaĵetoj povas esti DROP, REJECT aŭ REJECT kun la TCP-flago RST, aŭ kun ICMP-gastiganto neatingebla (fakte, la defaŭlta konduto estas icmp-port-neatingebla, kaj ankaŭ estas la ŝanco sendi respondon icmp-net-neatingebla, icmp-proto-neatingebla, icmp-net-malpermesita и icmp-gastiganto-malpermesita).

GUTI

Se ekzistas regulo kun DROP, pakoj simple "malaperos".

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

Ni lanĉas la klienton kaj vidas, ke ĝi frostas en la stadio de konekto al la servilo. Ni rigardu la trafikon:
Trafika rubejo

[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

Videblas, ke la kliento sendas SYN-pakaĵetojn kun eksponente pliiĝanta tempodaŭro. Do ni trovis malgrandan cimon en la kliento: vi devas uzi la metodon settimeout ()limigi la tempon dum kiu la kliento provos konekti al la servilo.

Ni tuj forigas la regulon:

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

Vi povas forigi ĉiujn regulojn samtempe:

iptables -F

Se vi uzas Docker kaj vi bezonas fajroŝirmigi la tutan trafikon irantan al la ujo, tiam vi povas fari ĝin jene:

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

REJEKTO

Nun ni aldonu similan regulon, sed kun REJECT:

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

La kliento eliras post sekundo kun eraro [Errno 111] Konekto rifuzita. Ni rigardu la ICMP-trafikon:

[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

Oni povas vidi, ke la kliento ricevis dufoje haveno neatingebla kaj poste finiĝis per eraro.

REJECT kun tcp-reset

Ni provu aldoni la opcion --reject-with tcp-reset:

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

En ĉi tiu kazo, la kliento tuj eliras kun eraro, ĉar la unua peto ricevis RST-pakaĵon:

[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

REJECT kun icmp-host-unatingable

Ni provu alian eblon por uzi REJECT:

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

La kliento eliras post sekundo kun eraro [Errno 113] Neniu vojo por gastigi, ni vidas en ICMP-trafiko ICMP-gastiganto 127.0.0.1 neatingebla.

Vi ankaŭ povas provi la aliajn REJECT-parametrojn, kaj mi koncentriĝos pri ĉi tiuj :)

Simulado de petotempo

Alia situacio estas kiam la kliento povis konektiĝi al la servilo, sed ne povas sendi peton al ĝi. Kiel filtri pakojn por ke filtrado ne komenciĝu tuj? Se vi rigardas la trafikon de iu ajn komunikado inter la kliento kaj la servilo, vi rimarkos, ke kiam oni establas konekton, nur la flagoj SYN kaj ACK estas uzataj, sed dum interŝanĝado de datumoj, la lasta peta pako enhavos la flagon PSH. Ĝi instaliĝas aŭtomate por eviti bufradon. Vi povas uzi ĉi tiun informon por krei filtrilon: ĝi permesos ĉiujn pakaĵojn krom tiuj enhavantaj la PSH-flagon. Tiel, la konekto estos establita, sed la kliento ne povos sendi datumojn al la servilo.

GUTI

Por DROP la komando aspektus jene:

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

Lanĉu la klienton kaj rigardu la trafikon:

Trafika rubejo

[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

Ni vidas, ke la konekto estas establita kaj la kliento ne povas sendi datumojn al la servilo.

REJEKTO

En ĉi tiu kazo la konduto estos la sama: la kliento ne povos sendi la peton, sed ricevos ICMP 127.0.0.1 tcp haveno 12345 neatingebla kaj pligrandigi la tempon inter peto-reprezentoj eksponente. La komando aspektas jene:

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

REJECT kun tcp-reset

La komando aspektas jene:

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

Ni jam scias tion kiam vi uzas --reject-with tcp-reset la kliento ricevos RST-pakaĵon en respondo, tiel ke la konduto povas esti antaŭdirita: ricevi RST-pakaĵon dum la ligo estas establita signifas ke la ingo estas neatendite fermita sur la alia flanko, kio signifas ke la kliento devus ricevi Konekto rekomencigita de samulo. Ni rulu nian skripton kaj certiĝu pri tio. Kaj jen kiel aspektos la trafiko:

Trafika rubejo

[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

REJECT kun icmp-host-unatingable

Mi pensas, ke jam estas evidente por ĉiuj, kia aspektos la komando :) La konduto de la kliento ĉi-kaze estos iomete malsama ol tiu per simpla RIĜO: la kliento ne pliigos la tempon inter provoj resendi la pakaĵon.

[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

konkludo

Ne necesas skribi mokon por testi la interagadon de servo kun pendigita kliento aŭ servilo; foje sufiĉas uzi normajn ilojn trovitajn en Linukso.

La utilecoj diskutitaj en la artikolo havas eĉ pli da kapabloj ol estis priskribitaj, do vi povas elpensi iujn viajn proprajn eblojn por uzi ilin. Persone, mi ĉiam havas sufiĉe da tio, pri kio mi skribis (fakte, eĉ malpli). Se vi uzas ĉi tiujn aŭ similajn ilojn en testado en via kompanio, bonvolu skribi kiel precize. Se ne, tiam mi esperas, ke via programaro pliboniĝos, se vi decidas testi ĝin en kondiĉoj de retaj problemoj uzante la proponitajn metodojn.

fonto: www.habr.com

Aldoni komenton