Pagtulad sa mga problema sa network sa Linux

Kumusta sa lahat, ang pangalan ko ay Sasha, nangunguna ako sa backend testing sa FunCorp. Kami, tulad ng marami pang iba, ay nagpatupad ng isang arkitektura na nakatuon sa serbisyo. Sa isang banda, pinapasimple nito ang gawain, dahil... Mas madaling subukan ang bawat serbisyo nang hiwalay, ngunit sa kabilang banda, kailangang subukan ang pakikipag-ugnayan ng mga serbisyo sa isa't isa, na kadalasang nangyayari sa network.

Sa artikulong ito, magsasalita ako tungkol sa dalawang utility na maaaring magamit upang suriin ang mga pangunahing sitwasyon na naglalarawan sa pagpapatakbo ng isang application sa pagkakaroon ng mga problema sa network.

Pagtulad sa mga problema sa network sa Linux

Pagtulad sa mga problema sa network

Kadalasan, sinusubok ang software sa mga server ng pagsubok na may magandang koneksyon sa Internet. Sa malupit na mga kapaligiran sa produksyon, maaaring hindi masyadong maayos ang mga bagay, kaya minsan kailangan mong subukan ang mga programa sa hindi magandang kundisyon ng koneksyon. Sa Linux, ang utility ay makakatulong sa gawain ng pagtulad sa mga naturang kundisyon tc.

tc(abbr. mula sa Traffic Control) ay nagbibigay-daan sa iyo na i-configure ang pagpapadala ng mga network packet sa system. Ang utility na ito ay may mahusay na mga kakayahan, maaari mong basahin ang higit pa tungkol sa mga ito dito. Dito ay isasaalang-alang ko lamang ang ilan sa mga ito: interesado kami sa pag-iiskedyul ng trapiko, kung saan ginagamit namin qdisc, at dahil kailangan nating tularan ang isang hindi matatag na network, gagamit tayo ng walang klase na qdisc netem.

Maglunsad tayo ng isang echo server sa server (ginamit ko nmap-ncat):

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

Upang maipakita nang detalyado ang lahat ng mga timestamp sa bawat hakbang ng pakikipag-ugnayan sa pagitan ng kliyente at ng server, sumulat ako ng isang simpleng script ng Python na nagpapadala ng isang kahilingan Pagsubok sa aming echo server.

source code ng kliyente

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

Ilunsad natin ito at tingnan ang trapiko sa interface lo at 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

tambakan ng trapiko

[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

Ang lahat ay pamantayan: isang three-way handshake, PSH/ACK at ACK bilang tugon nang dalawang beses - ito ang pagpapalitan ng kahilingan at tugon sa pagitan ng kliyente at server, at FIN/ACK at ACK nang dalawang beses - pagkumpleto ng koneksyon.

Pagkaantala ng pakete

Ngayon, itakda natin ang pagkaantala sa 500 millisecond:

tc qdisc add dev lo root netem delay 500ms

Inilunsad namin ang kliyente at nakita namin na tumatakbo na ngayon ang script sa loob ng 2 segundo:

[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

Ano ang nasa trapiko? Tingnan natin:

tambakan ng trapiko

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

Makikita mo na ang inaasahang lag ng kalahating segundo ay lumitaw sa pakikipag-ugnayan sa pagitan ng kliyente at ng server. Ang sistema ay kumikilos nang higit na kawili-wili kung ang lag ay mas malaki: ang kernel ay magsisimulang magpadala muli ng ilang TCP packet. Baguhin natin ang pagkaantala sa 1 segundo at tingnan ang trapiko (hindi ko ipapakita ang output ng kliyente, mayroong inaasahang 4 na segundo sa kabuuang tagal):

tc qdisc change dev lo root netem delay 1s

tambakan ng trapiko

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

Makikita na ang kliyente ay nagpadala ng SYN packet ng dalawang beses, at ang server ay nagpadala ng SYN/ACK ng dalawang beses.

Bilang karagdagan sa isang palaging halaga, ang pagkaantala ay maaaring itakda sa isang paglihis, isang function ng pamamahagi, at isang ugnayan (na may halaga para sa nakaraang packet). Ginagawa ito tulad ng sumusunod:

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

Dito namin itinakda ang pagkaantala sa pagitan ng 100 at 900 millisecond, ang mga halaga ay pipiliin ayon sa isang normal na pamamahagi at magkakaroon ng 50% na ugnayan sa halaga ng pagkaantala para sa nakaraang packet.

Maaaring napansin mo na sa unang utos na ginamit ko idagdagat pagkatapos baguhin. Ang kahulugan ng mga utos na ito ay halata, kaya idagdag ko na lamang na mayroon pa del, na maaaring gamitin upang alisin ang configuration.

Packet Loss

Subukan nating gawin ang packet loss. Tulad ng makikita mula sa dokumentasyon, ito ay maaaring gawin sa tatlong paraan: ang pagkawala ng mga packet nang random na may ilang posibilidad, gamit ang isang Markov chain na 2, 3 o 4 na estado upang kalkulahin ang pagkawala ng packet, o gamit ang Elliott-Gilbert na modelo. Sa artikulong isasaalang-alang ko ang una (pinakasimple at pinaka-halata) na paraan, at maaari mong basahin ang tungkol sa iba dito.

Gawin natin ang pagkawala ng 50% ng mga packet na may ugnayan na 25%:

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

Sa kasamaang palad, tcpdump ay hindi magagawang malinaw na ipakita sa amin ang pagkawala ng mga packet, ipagpalagay lamang namin na ito ay talagang gumagana. At ang tumaas at hindi matatag na oras ng pagpapatakbo ng script ay makakatulong sa amin na i-verify ito. client.py (maaaring makumpleto kaagad, o marahil sa loob ng 20 segundo), pati na rin ang isang tumaas na bilang ng mga muling ipinadalang packet:

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

Pagdaragdag ng ingay sa mga packet

Bilang karagdagan sa pagkawala ng packet, maaari mong gayahin ang pagkasira ng packet: lalabas ang ingay sa isang random na posisyon ng packet. Gumawa tayo ng packet damage na may 50% na posibilidad at walang ugnayan:

tc qdisc change dev lo root netem corrupt 50%

Pinapatakbo namin ang script ng kliyente (walang kawili-wili doon, ngunit tumagal ng 2 segundo upang makumpleto), tingnan ang trapiko:

tambakan ng trapiko

[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

Makikita na ang ilang mga packet ay paulit-ulit na ipinadala at mayroong isang packet na may sirang metadata: mga opsyon [nop,unknown-65 0x0a3dcf62eb3d,[bad opt]>. Ngunit ang pangunahing bagay ay sa huli ang lahat ay gumana nang tama - nakaya ng TCP ang gawain nito.

Pagdoble ng pakete

Ano pa ang magagawa mo netem? Halimbawa, gayahin ang reverse na sitwasyon ng packet lossβ€”packet duplication. Ang utos na ito ay tumatagal din ng 2 argumento: probabilidad at ugnayan.

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

Pagbabago ng pagkakasunud-sunod ng mga pakete

Maaari mong paghaluin ang mga bag sa dalawang paraan.

Sa una, ang ilang mga packet ay ipinadala kaagad, ang iba ay may tinukoy na pagkaantala. Halimbawa mula sa dokumentasyon:

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

Sa posibilidad na 25% (at isang ugnayan na 50%) ang packet ay ipapadala kaagad, ang iba ay ipapadala nang may pagkaantala ng 10 millisecond.

Ang pangalawang paraan ay kapag ang bawat Nth packet ay ipinadala kaagad na may ibinigay na probabilidad (at ugnayan), at ang iba ay may ibinigay na pagkaantala. Halimbawa mula sa dokumentasyon:

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

Ang bawat ikalimang pakete ay may 25% na pagkakataong maipadala nang walang pagkaantala.

Pagbabago ng Bandwidth

Kadalasan kahit saan sila tinutukoy TBF, ngunit sa tulong netem Maaari mo ring baguhin ang bandwidth ng interface:

tc qdisc change dev lo root netem rate 56kbit

Ang pangkat na ito ay gagawa ng mga paglalakbay sa paligid localhost kasing sakit ng pag-surf sa Internet sa pamamagitan ng dial-up modem. Bilang karagdagan sa pagtatakda ng bitrate, maaari mo ring tularan ang modelo ng protocol ng link layer: itakda ang overhead para sa packet, ang laki ng cell, at ang overhead para sa cell. Halimbawa, maaari itong gayahin ATM at bitrate 56 kbit/sec:

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

Simulating timeout ng koneksyon

Ang isa pang mahalagang punto sa plano ng pagsubok kapag tumatanggap ng software ay ang mga timeout. Mahalaga ito dahil sa mga distributed system, kapag ang isa sa mga serbisyo ay hindi pinagana, ang iba ay dapat na bumalik sa iba sa oras o magbalik ng isang error sa kliyente, at sa anumang kaso ay dapat silang mag-hang, naghihintay ng tugon o isang koneksyon upang maitatag.

Mayroong ilang mga paraan upang gawin ito: halimbawa, gumamit ng mock na hindi tumutugon, o kumonekta sa proseso gamit ang isang debugger, maglagay ng breakpoint sa tamang lugar at itigil ang proseso (ito ay marahil ang pinaka-pervert na paraan). Ngunit ang isa sa mga pinaka-halata ay ang mga firewall port o host. Makakatulong ito sa atin iptables.

Para sa pagpapakita, gagawin namin ang firewall port 12345 at patakbuhin ang script ng aming kliyente. Maaari mong i-firewall ang mga papalabas na packet sa port na ito sa nagpadala o mga papasok na packet sa receiver. Sa aking mga halimbawa, ang mga papasok na packet ay ma-firewall (ginagamit namin ang chain INPUT at ang opsyon --dport). Ang mga naturang packet ay maaaring DROP, REJECT o REJECT na may TCP flag na RST, o sa ICMP host na hindi maabot (sa katunayan, ang default na pag-uugali ay icmp-port-hindi maabot, at mayroon ding pagkakataong magpadala ng tugon icmp-net-unreachable, icmp-proto-unreachable, icmp-net-prohibited ΠΈ icmp-host-prohibited).

Ilaglag

Kung mayroong isang panuntunan sa DROP, ang mga packet ay "mawawala" lamang.

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

Inilunsad namin ang kliyente at nakita na nag-freeze ito sa yugto ng pagkonekta sa server. Tingnan natin ang trapiko:
tambakan ng trapiko

[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

Ito ay makikita na ang kliyente ay nagpapadala ng mga SYN packet na may isang exponentially pagtaas ng timeout. Kaya nakakita kami ng isang maliit na bug sa kliyente: kailangan mong gamitin ang pamamaraan settimeout()upang limitahan ang oras kung kailan susubukan ng kliyente na kumonekta sa server.

Agad naming inalis ang panuntunan:

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

Maaari mong tanggalin ang lahat ng mga panuntunan nang sabay-sabay:

iptables -F

Kung gumagamit ka ng Docker at kailangan mong i-firewall ang lahat ng trapikong papunta sa container, magagawa mo ito tulad ng sumusunod:

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

TANGGIHAN

Ngayon magdagdag tayo ng katulad na panuntunan, ngunit may REJECT:

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

Lalabas ang kliyente pagkatapos ng isang segundo nang may error [Errno 111] Tumanggi ang koneksyon. Tingnan natin ang trapiko ng ICMP:

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

Ito ay makikita na ang kliyente ay nakatanggap ng dalawang beses port na hindi maabot at pagkatapos ay natapos sa isang error.

TANGGILAN gamit ang tcp-reset

Subukan nating idagdag ang opsyon --reject-with tcp-reset:

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

Sa kasong ito, agad na lumabas ang kliyente nang may error, dahil ang unang kahilingan ay nakatanggap ng RST packet:

[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

TANGGILAN gamit ang icmp-host-unreachable

Subukan natin ang isa pang opsyon para sa paggamit ng REJECT:

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

Lalabas ang kliyente pagkatapos ng isang segundo nang may error [Errno 113] Walang ruta sa pagho-host, nakikita natin sa trapiko ng ICMP ICMP host 127.0.0.1 hindi maabot.

Maaari mo ring subukan ang iba pang mga parameter ng REJECT, at tututukan ko ang mga ito :)

Simulating timeout ng kahilingan

Ang isa pang sitwasyon ay kapag ang kliyente ay nakakonekta sa server, ngunit hindi makapagpadala ng kahilingan dito. Paano i-filter ang mga packet upang hindi agad magsimula ang pag-filter? Kung titingnan mo ang trapiko ng anumang komunikasyon sa pagitan ng kliyente at ng server, mapapansin mo na kapag nagtatag ng isang koneksyon, tanging ang mga flag ng SYN at ACK ang ginagamit, ngunit kapag nagpapalitan ng data, ang huling kahilingan na packet ay naglalaman ng bandila ng PSH. Awtomatikong nag-i-install ito upang maiwasan ang buffering. Magagamit mo ang impormasyong ito para gumawa ng filter: papayagan nito ang lahat ng packet maliban sa mga naglalaman ng flag ng PSH. Kaya, ang koneksyon ay maitatag, ngunit ang kliyente ay hindi makakapagpadala ng data sa server.

Ilaglag

Para sa DROP ang utos ay magiging ganito:

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

Ilunsad ang kliyente at panoorin ang trapiko:

tambakan ng trapiko

[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

Nakikita namin na ang koneksyon ay naitatag at ang kliyente ay hindi maaaring magpadala ng data sa server.

TANGGIHAN

Sa kasong ito ang pag-uugali ay magiging pareho: ang kliyente ay hindi maipadala ang kahilingan, ngunit makakatanggap ICMP 127.0.0.1 tcp port 12345 hindi maabot at dagdagan ang oras sa pagitan ng mga muling pagsusumite ng kahilingan nang exponentially. Ang utos ay ganito ang hitsura:

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

TANGGILAN gamit ang tcp-reset

Ang utos ay ganito ang hitsura:

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

Alam na natin yan kapag ginagamit --reject-with tcp-reset ang kliyente ay makakatanggap ng isang RST packet bilang tugon, kaya ang pag-uugali ay maaaring mahulaan: ang pagtanggap ng isang RST packet habang ang koneksyon ay itinatag ay nangangahulugan na ang socket ay hindi inaasahang sarado sa kabilang panig, na nangangahulugan na ang kliyente ay dapat tumanggap Pag-reset ng koneksyon ng peer. Patakbuhin natin ang ating script at siguraduhin ito. At ito ang magiging hitsura ng trapiko:

tambakan ng trapiko

[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

TANGGILAN gamit ang icmp-host-unreachable

Sa tingin ko ay halata na sa lahat kung ano ang magiging hitsura ng command :) Ang pag-uugali ng kliyente sa kasong ito ay bahagyang naiiba mula doon sa isang simpleng REJECT: hindi tataas ng kliyente ang timeout sa pagitan ng mga pagtatangka na muling ipadala ang packet.

[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

Pagbubuhos

Hindi kinakailangang magsulat ng isang mock upang subukan ang pakikipag-ugnayan ng isang serbisyo sa isang naka-hang na kliyente o server; kung minsan ay sapat na upang gumamit ng mga karaniwang kagamitan na matatagpuan sa Linux.

Ang mga utility na tinalakay sa artikulo ay may higit pang mga kakayahan kaysa sa inilarawan, kaya maaari kang makabuo ng ilan sa iyong sariling mga pagpipilian para sa paggamit ng mga ito. Sa personal, palagi akong may sapat na mga isinulat ko (sa katunayan, mas kaunti pa). Kung gagamitin mo ang mga ito o katulad na mga utility sa pagsubok sa iyong kumpanya, mangyaring isulat kung paano eksakto. Kung hindi, inaasahan kong magiging mas mahusay ang iyong software kung magpasya kang subukan ito sa mga kondisyon ng mga problema sa network gamit ang mga iminungkahing pamamaraan.

Pinagmulan: www.habr.com

Magdagdag ng komento