在Linux中模擬網路問題

大家好,我叫 Sasha,我在 FunCorp 負責後端測試。 與許多其他人一樣,我們已經實現了以服務為導向的架構。 一方面,這簡化了工作,因為...... 單獨測試每個服務更容易,但另一方面,需要測試服務之間的交互,這通常發生在網路上。

在本文中,我將討論兩個實用程序,可用於檢查描述存在網路問題時應用程式操作的基本場景。

在Linux中模擬網路問題

模擬網路問題

通常,軟體在具有良好互聯網連接的測試伺服器上進行測試。 在惡劣的生產環境中,事情可能不會那麼順利,所以有時你需要在連接條件較差的情況下測試程序。 在 Linux 上,該實用程式將協助完成模擬此類條件的任務 tc.

TC(縮寫。 來自交通管制)可讓您設定係統中網路封包的傳輸。 該實用程式具有強大的功能,您可以閱讀有關它們的更多信息 這裡。 在這裡我只考慮其中的幾個:我們對流量調度感興趣,為此我們使用 隊列磁碟,並且由於我們需要模擬不穩定的網絡,因此我們將使用無類 qdisc 內特姆.

讓我們在伺服器上啟動一個 echo 伺服器(我用過 nmap-ncat):

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

為了詳細顯示客戶端和伺服器互動的每一步的所有時間戳,我編寫了一個簡單的Python腳本來發送請求 測試 到我們的回顯伺服器。

客戶端源碼

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

讓我們啟動它並查看介面上的流量 lo 和連接埠 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

交通轉儲

[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

一切都是標準的:三次握手,兩次 PSH/ACK 和 ACK 回應——這是客戶端和伺服器之間請求和回應的交換,兩次 FIN/ACK 和 ACK——完成連線。

資料包延遲

現在讓我們將延遲設定為 500 毫秒:

tc qdisc add dev lo root netem delay 500ms

我們啟動客戶端並看到腳本現在運行了 2 秒:

[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

交通中有什麼? 我們看看吧:

交通轉儲

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

可以看到客戶端和服務端的互動出現了預期的半秒延遲。 如果滯後更大,系統的行為會更加有趣:核心開始重新發送一些 TCP 封包。 讓我們將延遲更改為 1 秒並查看流量(我不會顯示客戶端的輸出,預計總持續時間為 4 秒):

tc qdisc change dev lo root netem delay 1s

交通轉儲

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

可以看到客戶端發送了兩次SYN包,伺服器發送了兩次SYN/ACK。

除了常數值之外,延遲還可以設定為偏差、分佈函數和相關性(與前一個資料包的值)。 這是如下完成的:

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

這裡我們將延遲設定在 100 到 900 毫秒之間,這些值將根據常態分佈進行選擇,並且與前一個資料包的延遲值有 50% 的相關性。

您可能已經注意到,在我使用的第一個命令中 添加然後 改變。 這些命令的含義很明顯,所以我只是補充一下還有更多 德爾,可用於刪除配置。

Котеря пакетов

現在讓我們試著處理丟包問題。 從文件中可以看出,這可以透過三種方式完成:以一定機率隨機丟包,使用 2、3 或 4 個狀態的馬可夫鏈來計算丟包,或使用 Elliott-Gilbert 模型。 在本文中,我將考慮第一種(最簡單且最明顯的)方法,您可以閱讀其他方法 這裡.

讓我們假設遺失 50% 的資料包,相關性為 25%:

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

不幸的是, 轉儲 將無法清楚地向我們顯示資料包遺失情況,我們只能假設它確實有效。 而腳本運行時間的增加和不穩定將幫助我們驗證這一點。 客戶端.py (可以立即完成,也可能在 20 秒內完成),以及增加重傳資料包的數量:

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

在資料包中添加噪音

除了資料包遺失之外,您還可以模擬資料包損壞:隨機資料包位置會出現雜訊。 讓我們以 50% 的機率進行資料包損壞,並且沒有相關性:

tc qdisc change dev lo root netem corrupt 50%

我們運行客戶端腳本(沒有什麼有趣的,但花了 2 秒完成),查看流量:

交通轉儲

[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

可以看到,有些資料包被重複發送,並且有一個資料包元資料損壞: 選項 [nop,未知-65 0x0a3dcf62eb3d,[錯誤選擇]>。 但最重要的是,最終一切正常 - TCP 完成了它的任務。

資料包重複

你還能做什麼 內特姆? 例如,模擬丟包的逆向情況-資料包重複。 該指令還採用 2 個參數:機率和相關性。

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

更改包的順序

您可以透過兩種方式混合袋子。

第一種情況下,有些資料包會立即發送,其餘資料包會延遲指定的時間。 文件中的範例:

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

資料包有 25% 的機率(相關性為 50%)立即發送,其餘資料包將延遲 10 毫秒發送。

第二種方法是每第 N 個資料包以給定的機率(和相關性)立即發送,其餘資料包以給定的延遲發送。 文件中的範例:

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

每五個包裹中有 25% 的機會立即發送。

改變頻寬

通常他們所指的任何地方 TBF,但在幫助下 內特姆 您也可以變更介面頻寬:

tc qdisc change dev lo root netem rate 56kbit

這支隊伍將長途跋涉 本地 就像透過撥接數據機上網一樣痛苦。 除了設定位元率之外,您還可以模擬連結層協定模型:設定封包的開銷、單元大小和單元的開銷。 例如可以這樣模擬 ATM 標準大氣壓 位元率 56 kbit/秒:

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

類比連接逾時

接受軟體時測試計劃中的另一個重要點是超時。 這很重要,因為在分散式系統中,當其中一個服務被停用時,其他服務必須及時回退到其他服務或向客戶端傳回錯誤,並且在任何情況下都不應該簡單地掛起,等待回應或連結待成立。

有幾種方法可以做到這一點:例如,使用不響應的模擬,或者使用偵錯器連接到進程,在正確的位置放置斷點並停止進程(這可能是最變態的方法)。 但最明顯的之一是防火牆連接埠或主機。 它將幫助我們解決這個問題 iptables的.

為了進行演示,我們將防火牆連接埠 12345 並執行我們的客戶端腳本。 您可以在傳送者對傳出此連接埠的封包進行防火牆,或在接收者對傳入封包進行防火牆。 在我的範例中,傳入資料包將受到防火牆保護(我們使用鏈 INPUT 和選項 --d連接埠)。 此類資料包可以被 DROP、REJECT 或帶有 TCP 標誌 RST 的 REJECT,或 ICMP 主機不可達(事實上,預設行為是 icmp 連接埠不可達,還有機會發送回复 icmp 網路不可達, icmp 協議不可達, icmp 網路禁止 и icmp 主機禁止).

下降

如果有 DROP 規則,封包就會「消失」。

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

我們啟動客戶端,發現它在連接到伺服器的階段凍結了。 我們來看看流量:
交通轉儲

[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

可以看到,客戶端發送SYN包的超時時間呈指數增長。 所以我們發現客戶端有一個小bug:需要使用方法 設定超時()限制客戶端嘗試連接伺服器的時間。

我們立即刪除該規則:

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

您可以一次刪除所有規則:

iptables -F

如果您使用 Docker 並且需要對進入容器的所有流量進行防火牆,那麼您可以如下執行操作:

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

拒絕

現在讓我們新增一個類似的規則,但使用 REJECT:

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

客戶端一秒鐘後退出並出現錯誤 [Errno 111] 連線被拒絕。 讓我們來看看 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

可以看到客戶端收到了兩次 連接埠不可達 然後以錯誤結束。

使用 tcp-reset 拒絕

讓我們嘗試新增該選項 --reject-with tcp-reset:

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

在這種情況下,客戶端立即錯誤退出,因為第一個請求收到了 RST 資料包:

[user@host ~]# tcpdump -i lo -nn port 12345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
09:02:52.766175 IP 127.0.0.1.60658 > 127.0.0.1.12345: Flags [S], seq 1889460883, win 43690, options [mss 65495,sackOK,TS val 1205119003 ecr 0,nop,wscale 7], length 0
09:02:52.766184 IP 127.0.0.1.12345 > 127.0.0.1.60658: Flags [R.], seq 0, ack 1889460884, win 0, length 0

使用 icmp-host-unreachable 拒絕

讓我們嘗試使用 REJECT 的另一個選項:

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

客戶端一秒鐘後退出並出現錯誤 [Errno 113] 沒有到主機的路由,我們在 ICMP 流量中看到 ICMP 主機 127.0.0.1 無法存取.

您也可以嘗試其他 REJECT 參數,我將重點介紹這些:)

模擬請求逾時

另一種情況是客戶端能夠連接到伺服器,但無法向伺服器發送請求。 如何過濾資料包以使過濾不會立即開始? 如果您查看客戶端和伺服器之間的任何通訊流量,您會注意到,在建立連線時,僅使用 SYN 和 ACK 標誌,但在交換資料時,最後一個請求資料包將包含 PSH 標誌。 它會自動安裝以避免緩衝。 您可以使用此資訊建立過濾器:它將允許除包含 PSH 標誌的資料包之外的所有資料包。 因此,連線將建立,但客戶端將無法向伺服器發送資料。

下降

對於 DROP,命令如下所示:

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

啟動客戶端並觀察流量:

交通轉儲

[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

我們看到連線已建立,客戶端無法向伺服器發送資料。

拒絕

在這種情況下,行為將是相同的:客戶端將無法發送請求,但會接收 ICMP 127.0.0.1 tcp 連接埠 12345 無法存取 並以指數方式增加請求重新提交之間的時間。 該指令如下圖所示:

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

使用 tcp-reset 拒絕

該指令如下圖所示:

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

我們已經知道,當使用 --reject-with tcp-reset 客戶端將收到一個 RST 封包作為回應,因此可以預測行為:在建立連線時收到 RST 封包意味著另一端的套接字意外關閉,這意味著客戶端應該接收 連接被對等方重置。 讓我們運行我們的腳本並確保這一點。 流量如下圖所示:

交通轉儲

[user@host ~]# tcpdump -i lo -nn port 12345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
10:22:14.186269 IP 127.0.0.1.52536 > 127.0.0.1.12345: Flags [S], seq 2615137531, win 43690, options [mss 65495,sackOK,TS val 1209880423 ecr 0,nop,wscale 7], length 0
10:22:14.186284 IP 127.0.0.1.12345 > 127.0.0.1.52536: Flags [S.], seq 3999904809, ack 2615137532, win 43690, options [mss 65495,sackOK,TS val 1209880423 ecr 1209880423,nop,wscale 7], length 0
10:22:14.186293 IP 127.0.0.1.52536 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 1209880423 ecr 1209880423], length 0
10:22:14.186338 IP 127.0.0.1.52536 > 127.0.0.1.12345: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 1209880423 ecr 1209880423], length 5
10:22:14.186344 IP 127.0.0.1.12345 > 127.0.0.1.52536: Flags [R], seq 3999904810, win 0, length 0

使用 icmp-host-unreachable 拒絕

我認為每個人都已經很清楚該命令的樣子了:) 在這種情況下,客戶端的行為將與簡單 REJECT 的行為略有不同:客戶端不會增加嘗試重新發送資料包之間的逾時。

[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

產量

沒有必要編寫模擬來測試服務與掛起的客戶端或伺服器的交互;有時使用 Linux 中的標準實用程式就足夠了。

本文中討論的實用程式具有比所描述的更多的功能,因此您可以提出一些自己的使用它們的選項。 就我個人而言,我寫的內容總是足夠的(事實上,甚至更少)。 如果您在公司中使用這些或類似的實用程式進行測試,請具體說明如何使用。 如果沒有,那麼如果您決定使用建議的方法在網路問題的情況下測試它,我希望您的軟體會變得更好。

來源: www.habr.com

添加評論