[F5 Networks] 檔案莫名下載失敗/連線重設處理紀錄 (TCP RST)

前言

最近常收到教授抱怨科技部網站有些檔案能載,有些不能,但教授回到家裡用自家網路下載又正常。
我這邊嘗試在 F5 上對科技部網站固定走其中一條 HiNET 出去,在 Palo Alto 上對該網站都不做 IPS、防毒等等功能也沒用,折騰了很久決定跟科技部借一組帳號來做測試。

WireShark 抓包分析

使用 Analyze > Follow > TCP Stream 可以很快的篩選出資料流

當我下載時對伺服器發出 HTTP GET,後面跟著一長串回傳值

最後下載完成後,WEB Server 回覆 HTTP 200 OK

但可以看到回覆完 HTTP 200 OK 後就收到一連串的 TCP RST,這時 Chrome 下載的檔案會顯示 失敗 - 網路錯誤

在 F5 上使用 TCPDUMP 抓包分析

為了確認 TCP RST 是誰發出的,在 F5 上使用 tcpdump 抓包

1
~ # tcpdump -i any "((src host 61.60.96.9) or (dst host 61.60.96.9))" -c 500000 -w /shared/tmp/tcpdump_20180330.pacp

一樣用 WireShark 來看,發現 HTTP 200 OK 後 F5 對兩端都發了 TCP RST

接下來檢查 F5 發 TCP RST 的原因

在 F5 上設定 Log TCP RST Packet

K13223: Configuring the BIG-IP system to log TCP RST packets

輸入以下指令啟用 log (詳細請看文檔)

1
2
3
tmsh
modify /sys db tm.rstcause.log value enable
modify /sys db tm.rstcause.pkt value enable

篩選並顯示 log

1
2
3
4
5
6
7
8
9
~ # tail -f /var/log/ltm | grep 61.60.96.9

Mar 30 09:28:57 <my_username> err tmm[17913]: 011f0016:3: http_process_state_prepend - Invalid action:0x109010 Server sends too much data. serverside (61.60.96.9:80 -> <my_ip_addr>:64704) clientside (<my_ip_addr>:64704 -> 61.60.96.9:80) (Server side: vip=/Common/VS_Http profile=http pool=/Common/HiNET_1 server_ip=61.60.96.9)

Mar 30 09:28:57 <my_username> err tmm1[17913]: 011f0016:3: http_process_state_prepend - Invalid action:0x109010 Server sends too much data. serverside (61.60.96.9:80 -> <my_ip_addr>:64705) clientside (<my_ip_addr>:64705 -> 61.60.96.9:80) (Server side: vip=/Common/VS_Http profile=http pool=/Common/HiNET_1 server_ip=61.60.96.9)

Mar 30 09:28:59 <my_username> err tmm2[17913]: 011f0016:3: http_process_state_prepend - Invalid action:0x109010 Server sends too much data. serverside (61.60.96.9:80 -> <my_ip_addr>:64706) clientside (<my_ip_addr>:64706 -> 61.60.96.9:80) (Server side: vip=/Common/VS_Http profile=http pool=/Common/HiNET_1 server_ip=61.60.96.9)

Mar 30 09:29:00 <my_username> err tmm3[17913]: 011f0016:3: http_process_state_prepend - Invalid action:0x109010 Server sends too much data. serverside (61.60.96.9:80 -> <my_ip_addr>:64707) clientside (<my_ip_addr>:64707 -> 61.60.96.9:80) (Server side: vip=/Common/VS_Http profile=http pool=/Common/HiNET_1 server_ip=61.60.96.9)

發現為以下問題導致:http_process_state_prepend - Invalid action:0x109010 Server sends too much data.

解決方法

根據官方文檔 K5922: Error Message: http_process_state_prepend - Invalid action 提到,可能是 Web Server 發送的資料長度比 Content-Length 內的值還高,不符 RFC 規範。
或是有做 connection mirroringHTTP pipeliningOneConnect等等也會導致。

另外根據這篇討論:http_process_state_prepend - Server sends too much data ,可以利用在 iRule 加上 http::disable 來跳過對包含 Content-Disposition HTTP 包的檢查

1
2
3
4
5
when HTTP_RESPONSE { 
if { [HTTP::header exists "Content-Disposition"] } {
HTTP::disable
}
}

或是利用以下指令也可以全域啟用 Pass-through Content-Length 值不規範的 HTTP 包

1
~ # tmsh modify sys db tmm.http.passthru.invalid_content_length value enable

參考資料