1. 程式人生 > >記一次lvs-tunnel模式的故障分析(SYN_REC)

記一次lvs-tunnel模式的故障分析(SYN_REC)

過濾 oot som 一次 hose 不知道 也會 推理 min

一、測試環境

類型 IP
負載均衡器 eth0:10.20.73.20
VIP eth0:0 10.20.73.29
後端真實機 10.0.0.7(web01)、10.0.0.9(web02)

二、異常現象

在client上ping VIP是通的,但是訪問服務的時候卻發現不通。 技術分享

DR上所有連接都為SYN_RECE狀態。(類似TCP SYN Flood。) 技術分享

三、故障排除思路

1、抓包 技術分享 從RS上抓包的情況來看,也和ipvsadm列出來的結果是一樣的,服務器收到客戶端發過來的S標記的包後再也沒了下文。在DR上抓包,也是同樣的效果。 2、分析 1.說明客戶端發的包確實到了DR,並且DR也已經把包發送給了後端RS,問題應該出現在RS上。 此時的數據流分析如下: 客戶端發送S標記的包過來,服務端發送ACK確認後,就老老實實在在等待客戶端發送ACK過來後,就可以愉快的工作了,但是萬萬沒想到的是,此時服務端的ACK包被無情的過濾了,客戶端不可能發ACK過來,所以就一直停留在SYN_RECE狀態了。 3、解決過程
1.抓包,只能看到結果,但是還不知道具體導致RS不回應Client的原因; 2、關閉防火墻、關閉selinux,reboot,問題依舊,沒得到解決; 3、以為是沒有開啟路由轉發導致,所以就echo "1" > /proc/sys/net/ipv4/ip_forward,打開RS的路由轉發功能。 4.上面三板斧過後,還是不見效,於是就開始找度娘了,先是網上搜了一大把關於怎麽配置lvs tunnel的文章,先看看是不是我配置有誤,經過查看和對比,沒有問題。問題還是沒有得到解決。 5.當天晚上,沒睡好覺,第二天一早就起來,繼續排查和搜資料,可能是tunnel模式在現實中使用的比較少,所以網上關於tunnel提問的人也不是很多。看來這個問題只能自己摸索了。 於是先從tunnel模式的數據流著手, 【CIP->VIP】:客戶端訪問調度器上的VIP 【DIP->RIP|CIP->VIP】:DR經過IPIP協議將IP包進行二次包裝,其實就是把包頭進行特殊封裝,把上次的包頭作為數據包裝了進去。 【VIP->CIP】:RIP收到包後,進行包頭解析,發現是從DIP發過來的,但是因為RS上是經過IPIP協議進行解包的,所以他看到的真實源IP為VIP,目標IP為CIP,而此時,源IP恰巧就在RS上,嘿嘿,這裏不是恰巧,是特意設置的,而且把他的嘴給封了,arp廣播被禁用,這樣,他就不會喊人了,把自己就當成了源IP了,所以此時RS就直接回應CIP了。 上面說了一大推理論,看來也沒有解決問題,但是從上面的整個數據流來看,比較清晰明了,問題就出在RS發包上。但是為什麽RS會丟包呢?思考了好久,反復模擬發包過程,突然想起了之前濤哥(網絡老師)說的一句話,"數據在網絡上是雙向的,我們要最好確保他來回一致,如果來回路線不一致的話,就可能有去無回了,此時需要我們給他指定回來的路"。這個場景正好是路由來回不一致的場景,但是我已經指定了回來的路由/sbin/route add -host $VIP dev tunl0,那為什麽還不行呢?是不是linux系統本身也會有限制呢?於是就把思維轉向了sysctl中的那些內核參數,度娘一上,發現還真有個反向路徑過濾參數rp_filter,這個參數也沒有錯,他正是為了幹掉哪些DDOS攻擊裏面的TCP SYN Flood。而我們此時的場景正好符合他的要求,所以被無情的過濾了。具體請參考:http://en.wikipedia.org/wiki/Reverse_path_filtering 大概意思如下: 設置參數為0 非源檢測,即對源不進行檢測。註意:如果這裏不檢測的話,對於洪泛攻擊可能立馬就癱瘓了。
設置參數為2 嚴格模式,進來的每一個包都進行檢測,如果接口上不是最佳回包,數據庫包將會檢測失敗。默認情況下,失敗的的包會丟掉。 設置參數為2 松散模式,每個進來的包將會進行檢測,如果源地址通過本機任何接口都不可達的話,數據包將會失敗。 rp_filter - INTEGER(參數為整數) 0 - No source validation. 1 - Strict mode as defined in RFC3704 Strict Reverse Path Each incoming packet is tested against the FIB and if the interface is not the best reverse path the packet check will fail. By default failed packets are discarded. 2 - Loose mode as defined in RFC3704 Loose Reverse Path Each incoming packet‘s source address is also tested against the FIB and if the source address is not reachable via any interface the packet check will fail. Current recommended practice in RFC3704 is to enable strict mode to prevent IP spoofing from DDos attacks. If using asymmetric routing or other complicated routing, then loose mode is recommended. The max value from conf/{all,interface}/rp_filter is used when doing source validation on the {interface}. Default value is 0. Note that some distributions enable it in startup scripts. Red Hat are (correctly) setting rp_filter to 1, strict mode. In this case a packet coming in eth0 will have its source address routed out on the same interface that it came in on (because that‘s the default route). However, a packet coming in on eth1 will have it source address routed out on a different interface to the one it came in on and it will be discarded. Silently. This is basically asymmetric routing and is quite possibly not what you want anyway (it messes up TCP flow control) so there are two ways to fix this: stick with asymmetric routing and permit it or fix the asymmetric routing. The first one is easiest: in /etc/sysctl.conf change rp_filter=1 to rp_filter=2). You‘ll need to load that and restart the network. It‘s probably easiest to reboot :-) to be sure. I suspect that it was not restarting enough things that prevented this change from working before. The second one may be simple as simple as adding those routes that should go out on eth1 to the routing table or running some routing daemon. It depends on your network topology, basically. This would be the preferred solution if it‘s practicable. 註釋:解決方法,1是關閉反向路徑過濾功能;2是添加一條滿足反向路徑過濾的路由。 由於linux系統處於自身保護考慮,這個參數默認設置成1,:嚴格模式。 二話不說,我先把參數給調了,看看效果,於是在tunnel模式裏面加了一行: echo "0" >/proc/sys/net/ipv4/conf/tunl0/rp_filter 重啟服務: service ipvstunl stop service ipvstunl start 測試:OK,正常了。 技術分享

記一次lvs-tunnel模式的故障分析(SYN_REC)