四層負載均衡詳解
一、集群概念
1、 集群(cluster)技術是一種較新的技術,通過集群技術,可以在付出較低成本的情況下獲得在性能、可靠性、靈活性方面的相對較高的收益,其任務調度則是集群系統中的核心技術。
2、 集群是一組相互獨立的、通過高速網絡互聯的計算機,它們構成了一個組,並以單一系統的模式加以管理。一個客戶與集群相互作用時,集群像是一個獨立的服務器。
3、 集群組成后,可以利用多個計算機和組合進行海量請求處理(負載均衡),從而獲得很高的處理效率,也可以用多個計算機做備份(高可用),使得任何一個機器壞了整個系統還是能正常運行。集群在目前互聯網公司是必備的技術,極大提高互聯網業務的可用性和可縮放性。
二、負載均衡集群
負載均衡集群為企業需求提供了可解決容量問題的有效方案,使負載可以在計算機集群中盡可能平均地分攤處理。
負載通常包括應用程序處理負載和網絡流量負載。這樣的系統非常適合向使用同一組應用程序的大量用戶提供服務。每個節點都可以承擔一定的處理負載,並且可以實現處理負載在節點之間的動態分配,以實現負載均衡。對於網絡流量負載,當網絡服務程序接受了高入網流量,以致無法迅速處理,這時,網絡流量就會發送給在其它節點上運行的網絡服務程序。也可根據服務器的承載能力,進行服務請求的分發,從而使用戶的請求得到更快速的處理。
負載均衡技術類型:基於 4 層負載均衡技術和基於 7 層負載均衡技術
負載均衡實現方式:硬件負載均衡設備或者軟件負載均衡
硬件負載均衡產品:F5 BIG-IP 、Citrix Netscaler 、深信服 、Array 、Radware
軟件負載均衡產品: LVS(Linux Virtual Server)、 Haproxy、Nginx、Ats(apache traffic server)
1、實現效果圖
2、負載均衡分類
負載均衡根據所采用的設備對象(軟/硬件負載均衡),應用的OSI網絡層次(網絡層次上的負載均衡),及應用的地理結構(本地/全局負載均衡)等來分類。本文着重介紹的是根據應用的 OSI 網絡層次來分類的兩個負載均衡類型。
我們先來看一張圖,相信很多同學對這張圖都不陌生,這是一張網絡模型圖,包含了 OSI 模型及 TCP/IP 模型,兩個模型雖然有一點點區別,但主要的目的是一樣的,模型圖描述了通信是怎么進行的。它解決了實現有效通信所需要的所有過程,並將這些過程划分為邏輯上的層。層可以簡單地理解成數據通信需要的步驟。
根據負載均衡所作用在 OSI 模型的位置不同,負載均衡可以大概分為以下幾類:
-
二層負載均衡(mac)
根據OSI模型分的二層負載,一般是用虛擬mac地址方式,外部對虛擬MAC地址請求,負載均衡接收后分配后端實際的MAC地址響應。
-
三層負載均衡(ip)
一般采用虛擬IP地址方式,外部對虛擬的ip地址請求,負載均衡接收后分配后端實際的IP地址響應。
-
四層負載均衡(tcp)
在三層負載均衡的基礎上,用ip+port接收請求,再轉發到對應的機器。
-
七層負載均衡(http)
根據虛擬的url或IP,主機名接收請求,再轉向相應的處理服務器。
在實際應用中,比較常見的就是四層負載及七層負載。這里也重點說下這兩種負載。
3、四層負載均衡
基於IP+端口的負載均衡
所謂四層負載均衡,也就是主要通過報文中的目標地址和端口,再加上負載均衡設備設置的服務器選擇方式,決定最終選擇的內部服務器。
layer4
- 在三層負載均衡的基礎上,通過發布三層的IP地址(VIP),然后加四層的端口號,來決定哪些流量需要做負載均衡,對需要處理的流量進行NAT處理,轉發至后台服務器,並記錄下這個TCP或者UDP的流量是由哪台服務器處理的,后續這個連接的所有流量都同樣轉發到同一台服務器處理。
- 以常見的TCP為例,負載均衡設備在接收到第一個來自客戶端的SYN 請求時,即通過上述方式選擇一個最佳的服務器,並對報文中目標IP地址進行修改(改為后端服務器IP),直接轉發給該服務器。TCP的連接建立,即三次握手是客戶端和服務器直接建立的,負載均衡設備只是起到一個類似路由器的轉發動作。在某些部署情況下,為保證服務器回包可以正確返回給負載均衡設備,在轉發報文的同時可能還會對報文原來的源地址進行修改。
- 對應的負載均衡器稱為四層交換機(L4 switch),主要分析IP層及TCP/UDP層,實現四層負載均衡。此種負載均衡器不支持應用協議(如HTTP/FTP/MySQL等等)
要處理的流量進行NAT處理,轉發至后台服務器,並記錄下這個TCP或者UDP的流量是由哪台服務器處理的,后續這個連接的所有流量都同樣轉發到同一台服務器處理。 - 實現四層負載均衡的軟件有:
- F5:硬件負載均衡器,功能很好,但是成本很高。
- lvs:重量級的四層負載軟件
- nginx:輕量級的四層負載軟件,帶緩存功能,正則表達式較靈活
- haproxy:模擬四層轉發,較靈活
4、七層的負載均衡
基於虛擬的URL或主機IP的負載均衡
所謂七層負載均衡,也稱為“內容交換”,也就是主要通過報文中的真正有意義的應用層內容,再加上負載均衡設備設置的服務器選擇方式,決定最終選擇的內部服務器。
layer7
- 在四層負載均衡的基礎上(沒有四層是絕對不可能有七層的),再考慮應用層的特征,比如同一個Web服務器的負載均衡,除了根據VIP加80端口辨別是否需要處理的流量,還可根據七層的URL、瀏覽器類別、語言來決定是否要進行負載均衡。舉個例子,如果你的Web服務器分成兩組,一組是中文語言的,一組是英文語言的,那么七層負載均衡就可以當用戶來訪問你的域名時,自動辨別用戶語言,然后選擇對應的語言服務器組進行負載均衡處理。
- 以常見的TCP為例,負載均衡設備如果要根據真正的應用層內容再選擇服務器,只能先代理最終的服務器和客戶端建立連接(三次握手)后,才可能接受到客戶端發送的真正應用層內容的報文,然后再根據該報文中的特定字段,再加上負載均衡設備設置的服務器選擇方式,決定最終選擇的內部服務器。負載均衡設備在這種情況下,更類似於一個代理服務器。負載均衡和前端的客戶端以及后端的服務器會分別建立TCP連接。所以從這個技術原理上來看,七層負載均衡明顯的對負載均衡設備的要求更高,處理七層的能力也必然會低於四層模式的部署方式。
- 對應的負載均衡器稱為七層交換機(L7 switch),除了支持四層負載均衡以外,還有分析應用層的信息,如HTTP協議URI或Cookie信息,實現七層負載均衡。此種負載均衡器能理解應用協議。
- 實現七層負載均衡的軟件有:
- haproxy:天生負載均衡技能,全面支持七層代理,會話保持,標記,路徑轉移;
- nginx:只在http協議和mail協議上功能比較好,性能與haproxy差不多;
- apache:功能較差
- Mysql proxy:功能尚可。
5、四層負載與七層負載的區別
四層負載均衡就像銀行的自助排號機,每一個達到銀行的客戶根據排號機的順序,選擇對應的窗口接受服務;而七層負載均衡像銀行大堂經理,先確認客戶需要辦理的業務,再安排排號。這樣辦理理財、存取款等業務的客戶,會根據銀行內部資源得到統一協調處理,加快客戶業務辦理流程。
四層負載均衡(layer 4) | 七層負載均衡(layer 7) | |
---|---|---|
基於 | 基於IP Port | URL |
類似於 | 路由器 | 代理服務器 |
握手次數 | 1 次 | 2 次 |
復雜度 | 低 | 高 |
性能 | 高;無需解析內容 | 中;需要算法識別 URL,Cookie 和 HTTP head 等信息 |
安全性 | 低,無法識別 DDoS等攻擊 | 高, 可以防御SYN cookie以SYN flood等 |
額外功能 | 無 | 會話保持,圖片壓縮,防盜鏈等 |
從上面的對比看來四層負載與七層負載最大的區別就是效率與功能的區別。四層負載架構設計比較簡單,無需解析具體的消息內容,在網絡吞吐量及處理能力上會相對比較高,而七層負載均衡的優勢則體現在功能多,控制靈活強大。在具體業務架構設計時,使用七層負載或者四層負載還得根據具體的情況綜合考慮。
三、LVS 實現四層負載均衡
1、LVS 介紹
(1)LVS 是 Linux Virtual Server
的簡稱,也就是 Linux 虛擬服務器, 是一個由章文嵩博士發起的自由軟件項目,它的官方站點是www.linuxvirtualserver.org。現在LVS已經是 Linux標准內核的一部分,在Linux2.4內核以前,使用LVS時必須要重新編譯內核以支持LVS功能模塊,但是從Linux2.4內核以后,已經完全內置了LVS的各個功能模塊,無需給內核打任何補丁,可以直接使用LVS提供的各種功能。
(2)LVS自從1998年開始,發展到現在已經是一個比較成熟的技術項目了。可以利用LVS技術實現高可伸縮的、高可用的網絡服務,例如WWW服務、Cache服務、DNS服務、FTP服務、MAIL服務、視頻/音頻點播服務等等,有許多比較著名網站和組織都在使用LVS架設的集群系統,例如:Linux的門戶網站(www.linux.com)、向RealPlayer提供音頻視頻服務而聞名的Real公司(www.real.com)、全球最大的開源網站(sourceforge.net)等。
(3)LVS軟件作用:通過LVS提供的負載均衡技術和Linux操作系統實現一個高性能、高可用的服務器群集,它具有良好可靠性、可擴展性和可操作性。從而以低廉的成本實現最優的服務性能。
2、LVS 優勢與不足
1.優勢
高並發連接:LVS基於內核網絡層面工作,有超強的承載能力和並發處理能力。單台LVS負載均衡器,可支持上萬並發連接。
穩定性強:是工作在網絡4層之上僅作分發之用,這個特點也決定了它在負載均衡軟件里的性能最強,穩定性最好,對內存和cpu資源消耗極低。
成本低廉:硬件負載均衡器少則十幾萬,多則幾十萬上百萬,LVS只需一台服務器和就能免費部署使用,性價比極高。
配置簡單:LVS配置非常簡單,僅需幾行命令即可完成配置,也可寫成腳本進行管理。
支持多種算法:支持多種論調算法,可根據業務場景靈活調配進行使用
支持多種工作模型:可根據業務場景,使用不同的工作模式來解決生產環境請求處理問題。
應用范圍廣:因為LVS工作在4層,所以它幾乎可以對所有應用做負載均衡,包括http、數據庫、DNS、ftp服務等等
2.不足
工作在4層,不支持7層規則修改,機制過於龐大,不適合小規模應用。
3、LVS 核心組件和專業術語
1.核心組件
LVS的管理工具和內核模塊 ipvsadm/ipvs
ipvsadm:用戶空間的命令行工具,用於管理集群服務及集群服務上的RS等;
ipvs:工作於內核上的netfilter INPUT鈎子之上的程序,可根據用戶定義的集群實現請求轉發;
2.專業術語
VS:Virtual Server #虛擬服務
Director, Balancer #負載均衡器、分發器
RS:Real Server #后端請求處理服務器
CIP: Client IP #用戶端IP
VIP:Director Virtual IP #負載均衡器虛擬IP
DIP:Director IP #負載均衡器IP
RIP:Real Server IP #后端請求處理服務器IP
4、LVS工作內核模型及工作模式·
1、當客戶端的請求到達負載均衡器的內核空間時,首先會到達 PREROUTING 鏈。
2、當內核發現請求數據包的目的地址是本機時,將數據包送往 INPUT 鏈。
3、LVS由用戶空間的ipvsadm和內核空間的IPVS組成,ipvsadm用來定義規則,IPVS利用ipvsadm定義的規則工作,IPVS工作在INPUT鏈上,當數據包到達INPUT鏈時,首先會被IPVS檢查,如果數據包里面的目的地址及端口沒有在規則里面,那么這條數據包將被放行至用戶空間。
4、如果數據包里面的目的地址及端口在規則里面,那么這條數據報文將被修改目的地址為事先定義好的后端服務器,並送往POSTROUTING鏈。
5、最后經由POSTROUTING鏈發往后端服務器。
圖解
5、LVS負載均衡四種工作模式
1、NAT工作模式
1.LVS NAT 模式介紹
Virtual Server via NAT(VS-NAT):用地址轉換實現虛擬服務器。分發器有能被外界訪問到的合法IP地址,它修改來自專有網絡的流出包的地址。外界看起來包是來自分發器本身,當外界包送到轉換器時,它能判斷出應該將包送到內部網的哪個節點。優點是節省IP 地址,能對內部進行偽裝;缺點是效率低,因為返回給請求方的流量經過轉換器。
2.LVS NAT 模式工作流程
1、 當用戶請求到達Director Server,此時請求的數據報文會先到內核空間的 PREROUTING鏈。 此時報文的源IP為CIP,目標IP為VIP
2、 PREROUTING檢查發現數據包的目標IP是本機,將數據包送至INPUT鏈
3、IPVS比對數據包請求的服務是否為集群服務,若是,修改數據包的目標IP地址為后端服務器IP,然后將數據包發至POSTROUTING鏈。 此時報文的源IP為CIP,目標IP為RIP
4、POSTROUTING鏈通過選路,將數據包發送給Real Server
5、Real Server比對發現目標為自己的IP,開始構建響應報文發回給Director Server。 此時報文的源IP為RIP,目標IP為CIP
6、Director Server 把RS來到響應包,通過FORWORD 轉發給client 在響應客戶端前,此時會將源IP地址修改為自己的VIP地址,然后響應給客戶端。 此時報文的源IP為VIP,目標IP為CIP
3.LVS NET 模式圖解
2、DR 工作模式
1.LVS DR 模式介紹
Virtual Server via Direct Routing(VS-DR):用直接路由技術實現虛擬服務器。當參與集群的計算機和作為控制管理的計算機在同一個網段時可以用此方法,控制管理的計算機接收到請求包時直接送到參與集群的節點。直接路由模式比較特別,很難說和什么方面相似,前種模式基本上都是工作在網絡層上(三層),而直接路由模式則應該是工作在數據鏈路層上(二層)。
2.LVS DR 模式工作原理
DR和REAL SERVER都使用同一個IP對外服務。但只有DR對ARP請求進行響應,所有REAL SERVER對本身這個IP的ARP請求保持靜默。也就是說,網關會把對這個服務IP的請求全部定向給DR,而DR收到數據包后根據調度算法,找出對應的 REAL SERVER,把目的MAC地址改為REAL SERVER的MAC並發給這台REAL SERVER。這時REAL SERVER收到這個數據包,則等於直接從客戶端收到這個數據包無異,處理后直接返回給客戶端。由於DR要對二層包頭進行改換,所以DR和REAL SERVER之間必須在一個廣播域,也可以簡單的理解為在同一台交換機上
3.LVS DR 模式工作流程
1、 當用戶請求到達Director Server,此時請求的數據報文會先到內核空間的PREROUTING鏈。 此時報文的源IP為CIP,目標IP為VIP
2、 PREROUTING檢查發現數據包的目標IP是本機,將數據包送至INPUT鏈
3、 IPVS比對數據包請求的服務是否為集群服務,若是,將請求報文中的源MAC地址修改為DIP的MAC地址,將目標MAC地址修改RIP的MAC地址,然后將數據包發至POSTROUTING鏈。 此時的源IP和目的IP均未修改,僅修改了源MAC地址為DIP的MAC地址,目標MAC地址為RIP的MAC地址
4、 由於DS和RS在同一個網絡中,所以是通過二層,數據鏈路層來傳輸。POSTROUTING鏈檢查目標MAC地址為RIP的MAC地址,那么此時數據包將會發至Real Server。
5、 RS發現請求報文的MAC地址是自己的MAC地址,就接收此報文。處理完成之后,將響應報文通過lo接口傳送給eth0網卡然后向外發出。 此時的源IP地址為VIP,目標IP為CIP
6、 響應報文最終送達至客戶端
4.LVS DR 模式特點
1、 保證前端路由將目標地址為VIP報文統統發給Director Server,而不是RS
2、 RS可以使用私有地址;也可以是公網地址,如果使用公網地址,此時可以通過互聯網對RIP進行直接訪問
3、 RS跟Director Server必須在同一個物理網絡中
4、 所有的請求報文經由Director Server,但響應報文必須不能進過Director Server
5、 不支持地址轉換,也不支持端口映射
6、 RS可以是大多數常見的操作系統
7、 RS的網關絕不允許指向DIP(因為我們不允許他經過director)
8、 RS上的lo接口配置VIP的IP地址
5.LVS DR 模式工作流程圖解
3、LVS TUN 工作模式
1.LVS TUN 模式介紹
用IP隧道技術實現虛擬服務器。這種方式是在集群的節點不在同一個網段時可用的轉發機制,是將IP包封裝在其他網絡流量中的方法。為了安全的考慮,應該使用隧道技術中的VPN,也可使用租用專線。 集群所能提供的服務是基於TCP/IP的Web服務、Mail服務、News服務、DNS服務、Proxy服務器等等.
TUN模式:采用NAT技術時,由於請求和響應報文都必須經過調度器地址重寫,當客戶請求越來越多時,調度器的處理能力將成為瓶頸。為了解決這個問題,調度器把請求報文通過IP隧道轉發至真實服務器,而真實服務器將響應直接返回給客戶,所以調度器只處理請求報文。由於一般網絡服務應答比請求報文大許多,采用 VS/TUN技術后,集群系統的最大吞吐量可以提高10倍
2.LVS TUN 模式工作流程
1、 客戶端將請求發往前端的負載均衡器,請求報文源地址是CIP,目標地址為VIP。
2、 負載均衡器收到報文后,發現請求的是在規則里面存在的地址,那么它將在客戶端請求報文的首部再封裝一層IP報文,將源地址改為DIP,目標地址改為RIP,並將此包發送給RS。
3、 RS收到請求報文后,會首先拆開第一層封裝,然后發現里面還有一層IP首部的目標地址是自己lo接口上的VIP,所以會處理次請求報文,並將響應報文通過lo接口送給eth0網卡直接發送給客戶端。注意:需要設置lo接口的VIP不能在共網上出現
3.LVS TUN 模式圖解
4、LVS full-nat 工作模式
lvs-fullnat(雙向轉換)
通過請求報文的源地址為DIP,目標為RIP來實現轉發:對於響應報文而言,修改源地址為VIP,目標地址為CIP來實現轉發:
CIP --> DIP VIP --> RIP
架構特點:這是一種對nat模型的改進,是一個擴展,使得RS與Director可以處於不同網絡。
(1)RIP,DIP可以使用私有地址;
(2)RIP和DIP可以不再同一個網絡中,且RIP的網關未必需要指向DIP;
(3)支持端口映射;
(4)RS的OS可以使用任意類型;
(5)請求報文經由Director,響應報文也經由Director
5、四者的區別
機器名稱 | IP配置 | 服務角色 | 備注 |
---|---|---|---|
lvs-server | VIP:172.16.100.1 DIP:192.168.100.1 | 負載均衡器 | 開啟路由功能(VIP橋接、DIP僅主機) |
rs01 | RIP:192.168.100.2 | 后端服務器 | 網關指向DIP(僅主機) |
rs02 | RIP:192.168.100.3 | 后端服務器 | 網關指向DIP(僅主機) |
rs03 | RIP:192.168.100.4 | 后端服務器 | 網關指向DIP(僅主機) |
lvs-nat與lvs-fullnat:請求和響應報文都經由Director
lvs-nat:RIP的網關要指向DIP
lvs-fullnat:RIP和DIP未必在同一IP網絡,但要能通信
lvs-dr與lvs-tun:請求報文要經由Director,但響應報文由RS直接發往Client
lvs-dr:通過封裝新的MAC首部實現,通過MAC網絡轉發
lvs-tun:通過在原IP報文外封裝新IP頭實現轉發,支持遠距離通信
6、LVS ipvsadm 命令的使用
1、LVS-server 安裝 lvs 管理軟件
[root@zdns.cn ~]# yum -y install ipvsadm
程序包:ipvsadm(LVS管理工具)
Unit File: ipvsadm.service
主程序:/usr/sbin/ipvsadm
規則保存工具:/usr/sbin/ipvsadm-save
規則重載工具:/usr/sbin/ipvsadm-restore
配置文件:/etc/sysconfig/ipvsadm-config
2、命令選項
-A --add-service #在服務器列表中新添加一條新的虛擬服務器記錄
-t #表示為tcp服務
-u #表示為udp服務
-s --scheduler #使用的調度算法, rr | wrr | lc | wlc | lblb | lblcr | dh | sh | sed | nq 默認調度算法是 wlc
例:ipvsadm -A -t 192.168.1.2:80 -s wrr
-a --add-server #在服務器表中添加一條新的真實主機記錄
-t --tcp-service #說明虛擬服務器提供tcp服務
-u --udp-service #說明虛擬服務器提供udp服務
-r --real-server #真實服務器地址
-m --masquerading #指定LVS工作模式為NAT模式
-w --weight #真實服務器的權值
-g --gatewaying #指定LVS工作模式為直接路由器模式(也是LVS默認的模式)
-i --ip #指定LVS的工作模式為隧道模式
-p #會話保持時間,定義流量被轉到同一個realserver的會話存留時間
例:ipvsadm -a -t 192.168.1.2:80 -r 192.168.2.10:80 -m -w 1
-E -edit-service #編輯內核虛擬服務器表中的一條虛擬服務器記錄。
-D -delete-service #刪除內核虛擬服務器表中的一條虛擬服務器記錄。
-C -clear #清除內核虛擬服務器表中的所有記錄。
-R -restore #恢復虛擬服務器規則
-S -save #保存虛擬服務器規則,輸出為-R 選項可讀的格式
-e -edit-server #編輯一條虛擬服務器記錄中的某條真實服務器記錄
-d -delete-server #刪除一條虛擬服務器記錄中的某條真實服務器記錄
-L|-l –list #顯示內核虛擬服務器表
--numeric, -n:#以數字形式輸出地址和端口號
--exact: #擴展信息,精確值
--connection,-c: #當前IPVS連接輸出
--stats: #統計信息
--rate : #輸出速率信息
參數也可以從/proc/net/ip_vs*映射文件中查看
-Z –zero #虛擬服務表計數器清零(清空當前的連接數量等)
7、實現 LVS 持久連接
1、定義
由於HTTP是一種無狀態協議,每次請求完畢之后就立即斷開了,當用戶瀏覽購物網站挑選商品的時候,看到一件商品加入購物車,此過程被重定向到了REALSERVER1上面來,當把第二件商品加入購物車又被重定向到了REALSERVER2上面,最后結賬的時候在REALSERVER2上面,只有一件商品,這顯然是用戶無法接受的,此時就需要一種持久連接機制,來把同一用戶的HTTP請求在超時時間內都重定向到同一台REALSERVER,超時時間可以自己定義,比如說2個小時,在超時時間內服務器會不斷追蹤用戶的訪問請求,把某一用戶的所有請求都轉發到同一台REALSERVER上面
對於電子商務網站來說,用戶在挑選商品的時候使用的是80端口來瀏覽的,當付款的時候則是通過443的ssl加密的方式,當然當用戶挑選完商品付款的時候我們當然不希望https的443跳轉到另外一台REALSERVER,很顯然應該是同一REALSERVER才對,這時候就要用到基於防火牆標記的持久連接,通過定義端口的姻親關系來實現
2、功能
無論ipvs使用何種scheduler,其都能夠實現在指定時間范圍內始終將來自同一個ip地址的請求發往同一個RS;此功能是通過lvs持久連接模板實現,其與調度方法無關;
[root@zdns.cn ~]# iptables -t mangle -A PREROUTING -d 172.16.100.100 -p tcp --dport 80 -j MARK --set-mark 99
#在iptables 打上標記,把80端口標記為99
[root@zdns.cn ~]# iptables -t mangle -A PREROUTING -d 172.16.100.100-p tcp --dport 443 -j MARK --set-mark 99
#在iptables打上標記,把443端口標記為99
[root@zdns.cn ~]# ipvsadm -A -f 99 -s rr -p
在lvs上建立基於99號標記的虛擬服務
[root@zdns.cn ~]# ipvsadm -a -f 99 -r 172.16.100.2 -g
設置后端服務地址
[root@zdns.cn ~]# ipvsadm -a -f 99 -r 172.16.100.3 -g
8、LVS的調度算法
LVS的調度算法分為靜態與動態兩類。
1、靜態算法(4種)
只根據算法進行調度 而不考慮后端服務器的實際連接情況和負載情況
1、RR:輪叫調度(Round Robin)
調度器通過”輪叫”調度算法將外部請求按順序輪流分配到集群中的真實服務器上,它均等地對待每一台服務器,而不管服務器上實際的連接數和系統負載。
2、WRR:加權輪叫(Weight RR)
調度器通過“加權輪叫”調度算法根據真實服務器的不同處理能力來調度訪問請求。這樣可以保證處理能力強的服務器處理更多的訪問流量。調度器可以自動問詢真實服務器的負載情況,並動態地調整其權值。
3、DH:目標地址散列調度(Destination Hash )
根據請求的目標IP地址,作為散列鍵(HashKey)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空。
4、SH:源地址 hash(Source Hash)
源地址散列”調度算法根據請求的源IP地址,作為散列鍵(HashKey)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空。
2、動態算法(6種)
前端的調度器會根據后端真實服務器的實際連接情況來分配請求
1、LC:最少鏈接(Least Connections)
調度器通過”最少連接”調度算法動態地將網絡請求調度到已建立的鏈接數最少的服務器上。如果集群系統的真實服務器具有相近的系統性能,采用”最小連接”調度算法可以較好地均衡負載。
2、WLC:加權最少連接(默認采用的就是這種)(Weighted Least Connections)
在集群系統中的服務器性能差異較大的情況下,調度器采用“加權最少鏈接”調度算法優化負載均衡性能,具有較高權值的服務器將承受較大比例的活動連接負載。調度器可以自動問詢真實服務器的負載情況,並動態地調整其權值。
3、SED:最短期望延遲調度(Shortest Expected Delay )
在WLC基礎上改進,Overhead = (ACTIVE+1)*256/加權,不再考慮非活動狀態,把當前處於活動狀態的數目+1來實現,數目最小的,接受下次請求,+1的目的是為了考慮加權的時候,非活動連接過多缺陷:當權限過大的時候,會倒置空閑服務器一直處於無連接狀態。
4、NQ:永不排隊/最少隊列調度(Never Queue Scheduling NQ)
無需隊列。如果有台 realserver的連接數=0就直接分配過去,不需要再進行sed運算,保證不會有一個主機很空間。在SED基礎上無論+幾,第二次一定給下一個,保證不會有一個主機不會很空閑着,不考慮非活動連接,才用NQ,SED要考慮活動狀態連接,對於DNS的UDP不需要考慮非活動連接,而httpd的處於保持狀態的服務就需要考慮非活動連接給服務器的壓力。
5、LBLC:基於局部性的最少鏈接(locality-Based Least Connections)
基於局部性的最少鏈接”調度算法是針對目標IP地址的負載均衡,目前主要用於Cache集群系統。該算法根據請求的目標IP地址找出該目標IP地址最近使用的服務器,若該服務器是可用的且沒有超載,將請求發送到該服務器;若服務器不存在,或者該服務器超載且有服務器處於一半的工作負載,則用“最少鏈接”的原則選出一個可用的服務器,將請求發送到該服務器。
6、LBLCR:帶復制的基於局部性最少連接(Locality-Based Least Connections with Replication)
帶復制的基於局部性最少鏈接”調度算法也是針對目標IP地址的負載均衡,目前主要用於Cache集群系統。它與LBLC算法的不同之處是它要維護從一個目標IP地址到一組服務器的映射,而LBLC算法維護從一個目標IP地址到一台服務器的映射。該算法根據請求的目標IP地址找出該目標IP地址對應的服務器組,按”最小連接”原則從服務器組中選出一台服務器,若服務器沒有超載,將請求發送到該服務器;若服務器超載,則按“最小連接”原則從這個集群中選出一台服務器,將該服務器加入到服務器組中,將請求發送到該服務器。同時,當該服務器組有一段時間沒有被修改,將最忙的服務器從服務器組中刪除,以降低復制的程度。
三、LVS NAT 模式搭建【擴展】
三台服務器A、B、C:
1、 A: load balancer
(調度器dir,分發器) 在虛擬機設置里添加新網卡並設為僅主機模式連接,查看IP
內網網卡:192.168.31.128,網關保持不變(192.168.31.2)
外網網卡:192.168.229.128,不用設置,重啟網絡即可,此地址跟網卡設置里看到的地址保持一致
[root@zdns.cn ~]# setenforce 0 # 關閉selinux
[root@zdns.cn ~]# systemctl stop firewalld # 停止firewalld
[root@zdns.cn ~]# systemctl disable firewalld # 關閉firewalld
[root@zdns.cn ~]# yum install -y iptables-services # 安裝iptables
[root@zdns.cn ~]# systemctl enable iptables # 添加iptables服務
[root@zdns.cn ~]# service iptables start # 啟動iptables服務
[root@zdns.cn ~]# iptables -F # 清空iptables規則
[root@zdns.cn ~]# service iptables save # 保存空規則
1、創建 LVS 的 NAT 規則腳本
[root@zdns.cn ~]# vim /usr/local/sbin/lvs_nat.sh
#! /bin/bash
# director 服務器上開啟路由轉發功能
[root@zdns.cn ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
# 關閉icmp的重定向,開啟icmp則無法將數據包轉發至real server上,也無法返回
[root@zdns.cn ~]# echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
[root@zdns.cn ~]# echo 0 > /proc/sys/net/ipv4/conf/default/send_redirects
[root@zdns.cn ~]# echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects
[root@zdns.cn ~]# echo 0 > /proc/sys/net/ipv4/conf/ens37/send_redirects
# director 設置nat防火牆
[root@zdns.cn ~]# iptables -t nat -F 清空所有規則
[root@zdns.cn ~]# iptables -t nat -X 清空所有鏈
[root@zdns.cn ~]# iptables -t nat -A POSTROUTING -s 192.168.31.0/24 -j MASQUERADE 增加路由轉發規則
# director設置ipvsadm變量
IPVSADM='/usr/sbin/ipvsadm'
$IPVSADM -C # 清空所有規則
$IPVSADM -A -t 192.168.229.128:80 -s wlc -p 3 # 保持登陸時限persistent 設為0會報錯
# 訪問規則,-A指定轉發模式,-t指定分發器ip, -s指定調度算法(rr,wrr,wlc,lc)-p登陸保持時限,3秒
$IPVSADM -a -t 192.168.229.128:80 -r 192.168.31.129:80 -m -w 1
# 轉發規則,-a指定轉發規則 -t指定director ip,-r指定real server ip -m指定NAT模式(masquerade) -w指定權重為1
$IPVSADM -a -t 192.168.229.128:80 -r 192.168.31.130:80 -m -w 1
# 轉發規則,-a指定轉發規則 -t指定director ip,-r指定real server ip -m指定NAT模式(masquerade) -w指定權重為1
2、給腳本設權
[root@zdns.cn ~]# chmod 755 /usr/local/sbin/lvs_nat.sh
3、執行腳本
[root@zdns.cn ~]# sh /usr/local/sbin/lvs_nat.sh
排錯:當給主規則的登陸保持時限(persistent)設為0時,執行腳本會報錯
[root@zdns.cn ~]# /usr/local/sbin/lvs_nat.sh
invalid timeout value `0' specified
Memory allocation problem
2、B: real server
(web服務器) 內網網卡:192.168.31.129 網關改為129.168.31.128
安裝nginx,並啟動,在默認主頁里寫入,real server 1 關閉selinux,清空防火牆規則
3、C: real server
(web服務器) 內網網卡:192.168.31.130 網關改為129.168.31.128
安裝nginx,並啟動,在默認主頁里寫入,real server 2 關閉selinux,清空防火牆規則
4、測試
瀏覽器里訪問192.168.229.128,(A主機外網網卡地址)多刷新幾次看結果,服務器的切換。
瀏覽器上因為有本地緩存的原因,雖已經設定了登陸保持時限為1秒,但每次刷新都會保持在real server 2主機上。可以在調度機里用 curl 192.168.229.128 測試訪問,調度算法采用rr,效果更明顯。
1、用 ipvsadm 命令查看轉發規則
[root@zdns.cn ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.229.128:80 wlc persistent 1
-> 192.168.31.129:80 Masq 1 0 0
-> 192.168.31.130:80 Masq 1 0 0
2、查看 iptables nat 鏈的轉發規則
[root@zdns.cn ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 26 packets, 4015 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 2 packets, 404 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 1 packets, 328 bytes)
pkts bytes target prot opt in out source destination
7 532 MASQUERADE all -- * * 192.168.31.0/24 0.0.0.0/0
四、LVS DR 模式搭建
三台服務器A、B、C:
1、A: load balancer
(調度器dir,分發器)
內網網卡:192.168.31.128,網關保持不變(192.168.31.2)
外網網卡:192.168.229.128,先不用理會,這里用不到
[root@a.zdns.cn ~]# setenforce 0 # 關閉selinux
[root@a.zdns.cn ~]# systemctl stop firewalld # 停止firewalld
[root@a.zdns.cn ~]# systemctl disable firewalld # 關閉firewalld
[root@a.zdns.cn ~]# yum install -y iptables-services # 安裝iptables
[root@a.zdns.cn ~]# systemctl enable iptables # 添加iptables服務
[root@a.zdns.cn ~]# systemctl start iptables.service # 啟動iptables服務
[root@a.zdns.cn ~]# iptables -F # 清空iptables規則
[root@a.zdns.cn ~]# service iptables save # 保存空規則
[root@a.zdns.cn ~]# yum -y install ipvsadm net-tools
1、創建 LVS 的 DR 規則腳本
寫入以下內容:
[root@zdns.cn ~]# vim /usr/local/sbin/lvs_dr.sh
echo 1 > /proc/sys/net/ipv4/ip_forward # 打開路由轉發
ipv=/usr/sbin/ipvsadm # 設置ipvsadm變量
vip=192.168.31.200 # 設置公用ip變量(virtual ip)
rs1=192.168.31.129 # 設置real server1ip的變量
rs2=192.168.31.130 # 設置real server2ip的變量
ifdown eth0 # 關閉網卡
ifup eth0 # 啟動網卡,目的時清空臨時設定的ip,避免重復設定
ifconfig eth0:2 $vip broadcast $vip netmask 255.255.255.255 up # 綁定vip到虛擬網卡eth0:2上
route add -host $vip dev eth0:2 # 為eth0:2網卡添加網關
$ipv -C # 清空規則
$ipv -A -t $vip:80 -s wrr # -A指定轉發模式,-t指定director ip,-s指定調度算法 wrr加權輪詢調度
$ipv -a -t $vip:80 -r $rs1:80 -g -w 1
# 指定轉發規則,-a指定轉發規則,-t指定調度器(director)ip,-r指定real server IP,-g指定轉發模式為DR(gateway) -w指定權重
$ipv -a -t $vip:80 -r $rs2:80 -g -w 1
# 指定轉發規則,-a指定轉發規則,-t指定調度器(director)ip,-r指定real server IP,-g指定轉發模式為DR(gateway) -w指定權重
例子:
#!/bin/bash
echo 1 > /proc/sys/net/ipv4/ip_forward
ipv=/usr/sbin/ipvsadm
vip=192.168.152.200
rs1=192.168.152.132
rs2=192.168.152.133
ifdown eth0
ifup eth0
ifconfig eth0:2 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip dev eth0:2
$ipv -C
$ipv -A -t $vip:80 -s wrr
$ipv -a -t $vip:80 -r $rs1:80 -g -w 1
$ipv -a -t $vip:80 -r $rs2:80 -g -w 1
2、給腳本設權
[root@a.zdns.cn ~]# chmod 755 /usr/local/sbin/lvs_dr.sh
3、執行腳本
[root@a.zdns.cn ~]# sh /usr/local/sbin/lvs_dr.sh
4、查看路由上的 vip
[root@a.zdns.cn ~]# route -n
5、查看網卡 eth0 上的 vip
[root@a.zdns.cn ~]# ip addr
2、B: real server
(web服務器) 內網網卡:192.168.31.129 網關改回129.168.31.2
安裝nginx,並啟動,在默認主頁里寫入,real server 1 關閉selinux,清空防火牆規則
1、創建轉發腳本
[root@b.zdns.cn ~]# yum -y install net-tools
[root@b.zdns.cn ~]# vim /usr/local/sbin/lvs_rs.sh
寫入以下內容:
#/bin/bash
vip=192.168.31.200
#把vip綁定在lo上,是為了實現rs直接把結果返回給客戶端
ifdown lo
ifup lo
ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up綁定vip到虛擬網卡lo:0上
route add -host $vip lo:0為lo:0網卡添加網關
#以下操作為更改arp內核參數,目的是為了讓rs順利發送mac地址給客戶端
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
arp_ignore:定義對目標地址為本地IP的ARP詢問不同的應答模式0
0 - (默認值): 回應任何網絡接口上對任何本地IP地址的arp查詢請求
1 - 只回答目標IP地址是來訪網絡接口本地地址的ARP查詢請求
2 -只回答目標IP地址是來訪網絡接口本地地址的ARP查詢請求,且來訪IP必須在該網絡接口的子網段內
3 - 不回應該網絡界面的arp請求,而只對設置的唯一和連接地址做出回應
4-7 - 保留未使用
8 -不回應所有(本地地址)的arp查詢
arp_announce:對網絡接口上,本地IP地址的發出的,ARP回應,作出相應級別的限制: 確定不同程度的限制,宣布對來自本地源IP地址發出Arp請求的接口
0 - (默認) 在任意網絡接口(eth0,eth1,lo)上的任何本地地址
1 -盡量避免不在該網絡接口子網段的本地地址做出arp回應. 當發起ARP請求的源IP地址是被設置應該經由路由達到此網絡接口的時候很有用.此時會檢查來訪IP是否為所有接口上的子網段內ip之一.如果改來訪IP不屬於各個網絡接口上的子網段內,那么將采用級別2的方式來進行處理.
2 - 對查詢目標使用最適當的本地地址.在此模式下將忽略這個IP數據包的源地址並嘗試選擇與能與該地址通信的本地地址.首要是選擇所有的網絡接口的子網中外出訪問子網中包含該目標IP地址的本地地址. 如果沒有合適的地址被發現,將選擇當前的發送網絡接口或其他的有可能接受到該ARP回應的網絡接口來進行發送.
關於對arp_announce 理解的一點補充
其實就是路由器的問題,因為路由器一般是動態學習ARP包的(一般動態配置DHCP的話),當內網的機器要發送一個到外部的ip包,那么它就會請求 路由器的Mac地址,發送一個arp請求,這個arp請求里面包括了自己的ip地址和Mac地址,而linux默認是使用ip的源ip地址作為arp里面 的源ip地址,而不是使用發送設備上面的 ,這樣在lvs這樣的架構下,所有發送包都是同一個VIP地址,那么arp請求就會包括VIP地址和設備 Mac,而路由器收到這個arp請求就會更新自己的arp緩存,這樣就會造成ip欺騙了,VIP被搶奪,所以就會有問題。
arp緩存為什么會更新了,什么時候會更新呢,為了減少arp請求的次數,當主機接收到詢問自己的arp請求的時候,就會把源ip和源Mac放入自 己的arp表里面,方便接下來的通訊。如果收到不是詢問自己的包(arp是廣播的,所有人都收到),就會丟掉,這樣不會造成arp表里面無用數據太多導致 有用的記錄被刪除。
在設置參數的時候將arp_ignore 設置為1,意味着當別人的arp請求過來的時候,如果接收的設備上面沒有這個ip,就不做出響應,默認是0,只要這台機器上面任何一個設備上面有這個ip,就響應arp請求,並發送mac地址
例子:
#/bin/bash
vip=192.168.152.200
ifdown lo
ifup lo
ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip lo:0
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
2、給腳本設權
[root@b.zdns.cn ~]# chmod 755 /usr/local/sbin/lvs_rs.sh
3、執行腳本
[root@b.zdns.cn ~]# sh /usr/local/sbin/lvs_rs.sh
4、查看路由上的 vip
[root@b.zdns.cn ~]# route -n
5、查看網卡 lo 上的 vip
[root@b.zdns.cn ~]# ip addr
3、C: real server
(web服務器) 內網網卡:192.168.31.130 網關改回129.168.31.2
安裝nginx,並啟動,在默認主頁里寫入,real server 2 關閉selinux,清空防火牆規則
1、創建轉發腳本
[root@c.zdns.cn ~]# yum -y install net-tools
[root@c.zdns.cn ~]# vim /usr/local/sbin/lvs_rs.sh
寫入以下內容:
#/bin/bash
vip=192.168.31.200
#把vip綁定在lo上,是為了實現rs直接把結果返回給客戶端
ifdown lo
ifup lo
ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up綁定vip到虛擬網卡lo:0上
route add -host $vip lo:0為lo:0網卡添加網關
#以下操作為更改arp內核參數,目的是為了讓rs順利發送mac地址給客戶端
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
arp_ignore:定義對目標地址為本地IP的ARP詢問不同的應答模式0
0 - (默認值): 回應任何網絡接口上對任何本地IP地址的arp查詢請求
1 - 只回答目標IP地址是來訪網絡接口本地地址的ARP查詢請求
2 -只回答目標IP地址是來訪網絡接口本地地址的ARP查詢請求,且來訪IP必須在該網絡接口的子網段內
3 - 不回應該網絡界面的arp請求,而只對設置的唯一和連接地址做出回應
4-7 - 保留未使用
8 -不回應所有(本地地址)的arp查詢
arp_announce:對網絡接口上,本地IP地址的發出的,ARP回應,作出相應級別的限制: 確定不同程度的限制,宣布對來自本地源IP地址發出Arp請求的接口
0 - (默認) 在任意網絡接口(eth0,eth1,lo)上的任何本地地址
1 -盡量避免不在該網絡接口子網段的本地地址做出arp回應. 當發起ARP請求的源IP地址是被設置應該經由路由達到此網絡接口的時候很有用.此時會檢查來訪IP是否為所有接口上的子網段內ip之一.如果改來訪IP不屬於各個網絡接口上的子網段內,那么將采用級別2的方式來進行處理.
2 - 對查詢目標使用最適當的本地地址.在此模式下將忽略這個IP數據包的源地址並嘗試選擇與能與該地址通信的本地地址.首要是選擇所有的網絡接口的子網中外出訪問子網中包含該目標IP地址的本地地址. 如果沒有合適的地址被發現,將選擇當前的發送網絡接口或其他的有可能接受到該ARP回應的網絡接口來進行發送.
關於對arp_announce 理解的一點補充
其實就是路由器的問題,因為路由器一般是動態學習ARP包的(一般動態配置DHCP的話),當內網的機器要發送一個到外部的ip包,那么它就會請求 路由器的Mac地址,發送一個arp請求,這個arp請求里面包括了自己的ip地址和Mac地址,而linux默認是使用ip的源ip地址作為arp里面 的源ip地址,而不是使用發送設備上面的 ,這樣在lvs這樣的架構下,所有發送包都是同一個VIP地址,那么arp請求就會包括VIP地址和設備 Mac,而路由器收到這個arp請求就會更新自己的arp緩存,這樣就會造成ip欺騙了,VIP被搶奪,所以就會有問題。
arp緩存為什么會更新了,什么時候會更新呢,為了減少arp請求的次數,當主機接收到詢問自己的arp請求的時候,就會把源ip和源Mac放入自 己的arp表里面,方便接下來的通訊。如果收到不是詢問自己的包(arp是廣播的,所有人都收到),就會丟掉,這樣不會造成arp表里面無用數據太多導致 有用的記錄被刪除。
在設置參數的時候將arp_ignore 設置為1,意味着當別人的arp請求過來的時候,如果接收的設備上面沒有這個ip,就不做出響應,默認是0,只要這台機器上面任何一個設備上面有這個ip,就響應arp請求,並發送mac地址
例子:
#/bin/bash
vip=192.168.152.200
ifdown lo
ifup lo
ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip lo:0
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
2、給腳本設權
[root@c.zdns.cn ~]# chmod 755 /usr/local/sbin/lvs_rs.sh
3、執行腳本
[root@c.zdns.cn ~]# sh /usr/local/sbin/lvs_rs.sh
4、查看路由上的 vip
[root@c.zdns.cn ~]# route -n
5、查看網卡 lo 上的 vip
[root@c.zdns.cn ~]# ip addr
4、測試
瀏覽器里訪問192.168.31.200,(vip:vitrual ip)多刷新幾次看結果,服務器的切換。
瀏覽器上因為有本地緩存的原因,雖已經設定了登陸保持時限為1秒,但每次刷新都會保持在real server 2主機上。可以在調度機里用 curl 192.168.31.200 測試訪問,調度算法采用rr,效果更明顯。
1、用 ipvsadm 命令查看轉發規則
[root@a.zdns.cn ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.31.200:80 wrr
-> 192.168.31.129:80 Route 1 0 4
-> 192.168.31.130:80 Route 1 0 5
# ActiveConn是活動連接數,也就是tcp連接狀態的ESTABLISHED;InActConn是指除了ESTABLISHED以外的,所有的其它狀態的tcp連接
2、查看 iptables nat 鏈的轉發規則
[root@a.zdns.cn ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 89 packets, 13284 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 40 packets, 4692 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 7 packets, 2296 bytes)
pkts bytes target prot opt in out source destination
48 3648 MASQUERADE all -- * * 192.168.31.0/24 0.0.0.0/0
五、網絡抓包分析
1,網絡抓包介紹
1、Tcpdump簡介
tcpdump 命令是基於unix系統的命令行的數據報嗅探工具,可以抓取流動在網卡上的數據包。它的原理大概如下:linux 抓包是通過注冊一種虛擬的底層網絡協議來完成對網絡報文(准確的是網絡設備)消息的處理權。當網卡接收到一個網絡報文之后,它會遍歷系統中所有已經注冊的網絡協議,如以太網協議、x25協議處理模塊來嘗試進行報文的解析處理。當抓包模塊把自己偽裝成一個網絡協議的時候,系統在收到報文的時候就會給這個偽協議一次機會,讓它對網卡收到的包進行一次處理,此時該模塊就會趁機對報文進行窺探,也就是將報文完完整整的復制一份,假裝是自己接收的報文,匯報給抓包模塊。
2、Wireshark 簡介
Wireshark 是一個網絡協議檢測工具,支持Windows平台、Unix平台、Mac平台,一般只在圖形界面平台下使用Wireshark,如果是Linux的話,直接使用 tcpdump了,因為一般而言 Linux 都自帶的 tcpdump,或者用 tcpdump 抓包以后用 Wireshark 打開分析。
在Mac平台下,Wireshark 通過 WinPcap 進行抓包,封裝的很好,使用起來很方便,可以很容易的制定抓包過濾器或者顯示過濾器,具體簡單使用下面會介紹。Wireshark是一個免費的工具。
所以,tcpdump是用來抓取數據非常方便,Wireshark則是用於分析抓取到的數據比較方便。
2、Tcpdump 語法
1、查看本地網卡狀態
[root@zdns.cn ~]# netstat -i
Kernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
docker0 1500 40409 0 0 0 20376 0 0 0 BMU
eth0 1500 22999894941 0 0 0 25581016784 0 0 0 BMRU
lo 65536 850291094 0 0 0 850291094 0 0 0 LRU
-
Iface:存在的網卡。
-
MTU:最大傳輸單元。
-
RX-OK RX-ERR RX-DRP RX-OVR:正確接收數據報的數量以及發生錯誤、流式、碰撞的總數。
-
TX-OK TX-ERR TX-DRP TX-OVR:正確發送數據報的數量以及發生錯誤、流式、碰撞的總數。
[root@zdns.cn ~]# tcpdump --help tcpdump version 4.9.0 libpcap version 1.5.3 OpenSSL 1.0.1e-fips 11 Feb 2013 Usage: tcpdump [-aAbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ] [ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ] [ -i interface ] [ -j tstamptype ] [ -M secret ] [ --number ] [ -Q|-P in|out|inout ] [ -r file ] [ -s snaplen ] [ --time-stamp-precision precision ] [ --immediate-mode ] [ -T type ] [ --version ] [ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z postrotate-command ] [ -Z user ] [ expression ]
2、 Tcpdump 抓包分類
1、類型的關鍵字
- host:指明一台主機。如:host 192.168.152.110
- net:指明一個網絡地址,如:net 192.168.152.0
- port:指明端口號:如:port 8090
2、確定方向的關鍵字
- src:ip包的源地址,如:src 192.168.152.110
- dst:ip包的目標地址。如:dst 192.168.152.110
3、協議的關鍵字(缺省是所有協議的信息包)
- fddi、ip、arp、rarp、tcp、udp。
4、其它關鍵字
- gateway、broadcast、less、greater。
5、常用表達式
- ! or not
- && or and
- || or or
3、Tcpdump 參數詳解
- A:以ascii編碼打印每個報文(不包括鏈路的頭)。
- a:將網絡地址和廣播地址轉變成名字。
- c:抓取指定數目的包。
- C:用於判斷用 -w 選項將報文寫入的文件的大小是否超過這個值,如果超過了就新建文件(文件名后綴是1、2、3依次增加);
- d:將匹配信息包的代碼以人們能夠理解的匯編格式給出;
- dd:將匹配信息包的代碼以c語言程序段的格式給出;
- ddd:將匹配信息包的代碼以十進制的形式給出;
- D:列出當前主機的所有網卡編號和名稱,可以用於選項 -i;
- e:在輸出行打印出數據鏈路層的頭部信息;
- f:將外部的Internet地址以數字的形式打印出來;
- F<表達文件>:從指定的文件中讀取表達式,忽略其它的表達式;
- i<網絡界面>:監聽主機的該網卡上的數據流,如果沒有指定,就會使用最小網卡編號的網卡(在選項-D可知道,但是不包括環路接口),linux 2.2 內核及之后的版本支持 any 網卡,用於指代任意網卡;
- l:如果沒有使用 -w 選項,就可以將報文打印到 標准輸出終端(此時這是默認);
- n:顯示ip,而不是主機名;
- nn:顯示port,而不是服務名;
- N:不列出域名;
- O:不將數據包編碼最佳化;
- p:不讓網絡界面進入混雜模式;
- q:快速輸出,僅列出少數的傳輸協議信息;
- r<數據包文件>:從指定的文件中讀取包(這些包一般通過-w選項產生);
- s<數據包大小>:指定抓包顯示一行的寬度,-s0表示可按包長顯示完整的包,經常和-A一起用,默認截取長度為60個字節,但一般ethernet MTU都是1500字節。所以,要抓取大於60字節的包時,使用默認參數就會導致包數據丟失;
- S:用絕對而非相對數值列出TCP關聯數;
- t:在輸出的每一行不打印時間戳;
- tt:在輸出的每一行顯示未經格式化的時間戳記;
- T<數據包類型>:將監聽到的包直接解釋為指定的類型的報文,常見的類型有rpc (遠程過程調用)和snmp(簡單網絡管理協議);
- v:輸出一個稍微詳細的信息,例如在ip包中可以包括ttl和服務類型的信息;
- vv:輸出詳細的報文信息;
- x/-xx/-X/-XX:以十六進制顯示包內容,幾個選項只有細微的差別,詳見man手冊;
- w<數據包文件>:直接將包寫入文件中,並不分析和打印出來;
- expression:用於篩選的邏輯表達式;
4、Tcpdump 參數含義
[root@zdns.cn ~]# tcpdump host 192.168.152.110 -i eth0 -c 10 -l -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens5f0, link-type EN10MB (Ethernet), capture size 262144 bytes
10:59:51.071567 IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 1715331653:1715331865, ack 2259278754, win 65535, length 212
10:59:51.071699 IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 212:408, ack 1, win 65535, length 196
10:59:51.071794 IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 408:572, ack 1, win 65535, length 164
10:59:51.071861 IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 572:736, ack 1, win 65535, length 164
10:59:51.071910 IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 736:900, ack 1, win 65535, length 164
10:59:51.071958 IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 900:1064, ack 1, win 65535, length 164
10:59:51.072006 IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 1064:1228, ack 1, win 65535, length 164
10:59:51.072053 IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 1228:1392, ack 1, win 65535, length 164
10:59:51.072141 IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 1392:1556, ack 1, win 65535, length 164
10:59:51.077438 IP 192.168.152.110.7608 > 10.1.87.25.ssh: Flags [.], ack 212, win 63360, length 0
10 packets captured
13 packets received by filter
0 packets dropped by kernel
1、第一行:`tcpdump: verbose output suppressed, use -v or -vv for full protocol decode`
使用選項`v`和`vv`,可以看出更全的詳細內容。
2、第二行:`listening on ens5f0, link-type EN10MB (Ethernet), capture size 262144 bytes`,說明監聽的是`ens5f0`這個NIC設備的網絡包,且它的鏈路層是基於以太網的,要抓的包大小限制`262144`,裝包大小限制可以用利用`-s`來控制。
3、第三行:`10:59:51.071567 IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 1715331653:1715331865, ack 2259278754, win 65535, length 212`。
- `10:59:51.071567`:抓包時間為時、分、秒、微妙。
- `IP 192.168.152.21.ssh > 192.168.152.110.7608: Flags [P.], seq 1715331653:1715331865, ack 2259278754, win 65535, length 212`,這里用`man dump`這個命令引用說明:
上面視圖簡單的解釋就是該包`192.168.152.21`傳到`192.168.152.110`,通過的端口是`22`(ssh的端口)向`7608`,前幾個是使用的是`PUSH`的標識,最后一個是返回的`ACK`標識。
5、Tcpdump 命令實踐
1、直接啟動tcpdump,將抓取所有經過第一個網絡接口上的數據包
[root@zdns.cn ~]# tcpdump
2、抓取所有經過指定網絡接口上的數據包
[root@zdns.cn ~]# tcpdump -i eth0
3、抓取所有經過 eth0,目的或源地址是 192.168.152.255 的網絡數據:
[root@zdns.cn ~]# tcpdump -i eth0 host 192.168.152.100
4、抓取主機192.168.152.255和主機192.168.152.61或192.168.152.95的通信:
[root@zdns.cn ~]# tcpdump host 192.168.152.100 and 192.168.152.101 (或者用 or)
5、抓取主機192.168.1523.210除了和主機192.168.152.61之外所有主機通信的數據包:
[root@zdns.cn ~]# tcpdump -n host 192.168.152.100 and ! 192.168.152.101
6、抓取主機192.168.152.255除了和主機192.168.152.61之外所有主機通信的ip包
[root@zdns.cn ~]# tcpdump ip -n host 192.168.152.100 and ! 192.168.152.101
7、抓取主機192.168.152.3發送的所有數據:
[root@zdns.cn ~]# tcpdump -i eth0 src host 192.168.152.100 (注意數據流向)
8、抓取主機192.168.152.3接收的所有數據:
[root@zdns.cn ~]# tcpdump -i eth0 dst host 192.168.152.100 (注意數據流向)
9、抓取主機192.168.152.3所有在TCP 80端口的數據包:
[root@zdns.cn ~]# tcpdump -i eth0 host 192.168.152.3 and tcp port 80
10、抓取HTTP主機192.168.152.3在80端口接收到的數據包:
[root@zdns.cn ~]# tcpdump -i eth0 host 192.168.152.3 and dst port 80
11、抓取所有經過 eth0,目的或源端口是 25 的網絡數據
[root@zdns.cn ~]# tcpdump -i eth0 port 25
#源端口
[root@zdns.cn ~]# tcpdump -i eth0 src port 25
#目的端口
[root@zdns.cn ~]# tcpdump -i eth0 dst port 25 # 網絡過濾
12、抓取所有經過 eth0,網絡是 192.168上的數據包
[root@zdns.cn ~]# tcpdump-i eth0 net 192.168
[root@zdns.cn ~]# tcpdump -i enh0 src net 192.168
[root@zdns.cn ~]# tcpdump -i eth0 dst net 192.168
[root@zdns.cn ~]# tcpdump-i eth0 net 192.168.152
[root@zdns.cn ~]# tcpdump -i eth0 net 192.168.152.0/24
13、協議過濾
[root@zdns.cn ~]# tcpdump -i eth0 arp
[root@zdns.cn ~]# tcpdump-i eth0 ip
[root@zdns.cn ~]# tcpdump -i eth0
[root@zdns.cn ~]# tcptcpdump -i eth0 udp
[root@zdns.cn ~]# tcpdump -i eth0 icmp
14、抓取所有經過 eth0,目的地址是 192.168.152.254 或 192.168.152.200 端口是 80 的 TCP 數據
[root@qfedu.com ~]# tcpdump -i eth0 '((tcp) and (port 80) and ((dst host 192.168.152.254) or (dst host 192.168.152.200)))
15、抓取所有經過 eth0,目標 MAC 地址是 00:01:02:03:04:05 的 ICMP 數據
[root@qfedu.com ~]# tcpdump -i eth1 '((icmp) and ((ether dst host 00:01:02:03:04:05)))
16、抓取所有經過 eth0,目的網絡是 192.168,但目的主機不是 192.168.152.200 的 TCP 數據
[root@qfedu.com ~]# tcpdump -i eth0 '((tcp) and ((dst net 192.168) and (not dst host 192.168.152.200)))'
17、只抓 SYN 包
[root@qfedu.com ~]# tcpdump -i eth0 'tcp[tcpflags] =tcp-syn
18、抓 SYN, ACK
[root@zdns.cn ~]# tcpdump -i eth0 'tcp[tcpflags]'
19、抓 SMTP 數據,抓取數據區開始為”MAIL”的包,”MAIL”的十六進制為 0x4d41494c
[root@qfedu.com ~]# tcpdump -i eth0 '((port 25) and (tcp[(tcp[12]>>2):4] = 0x4d41494c))'
20、抓 HTTP GET 數據,”GET “的十六進制是 0x47455420
[root@qfedu.com ~]# tcpdump -i eth0 'tcp[(tcp[12]>x2):4] =0x47455429'
# 0x4745為"GET"前兩個字母"GE",0x4854為"HTTP"前兩個字母"HT"
[root@qfedu.com ~]# tcpdump -XvvennSs 0 -i eth0 tcp[20:2]=0x4745 or tcp[20:2]=0x4854
21、抓 SSH 返回,”SSH-“的十六進制是 0x5353482D
[root@qfedu.com ~]# tcpdump -i eth0 'tcp[(tcp[12]2):4]-0x5353482D'
# 抓老版本的SSH返回信息,如"SSH-1.99.."
[root@qfedu.com ~]# tcpdump -i eth0 (tcp (tcp[12]>>2):4] = 0x5353482D) and (tcp[((tcp[12]>2)+4):2] = 0x312E3)'
22、高級包頭過濾如前兩個的包頭過濾,首先了解如何從包頭過濾信息:
proto[x:y] # :過濾從x字節開始的y字節數。比如ip[2:2]過濾出3、4字節(第二字專從研始排)
操作符: >, =,
抓取端口大於1024的TCP數據包
[root@qfedu.com ~]# tcpdump -i eth0 'tcp[0:2] > 1024‘
23、抓 DNS 請求數據
[root@zdns.cn ~]# tcpdump -i eth0 udp dst port 53
24、其他-c 參數對於運維人員來說也比較常用,因為流量比較大的服務器,靠人工 CTRL+C 還是抓的太多,於是可以用-c 參數指定抓多少個包。
[root@zdns.cn ~]# time tcpdump -nn -i eth0 'tcp[tcpflags] = tcp-syn' -C 10000 > /dev/null
上面的命令計算抓10000個SYN包花費多少時間,可以判斷訪問量大概是多少。實時抓取端口號8000的GET包,然后寫入GET.log
[root@zdns.cn ~]# tcpdump -i eth0 '((port 8000) and (tcp[(tcp[12]>>2):4]=0x47455420))' -nnAL -w /tmp/GET.log
6、Tcpdump 抓包示例
想抓取訪問某個網站時的網絡數據。比如網站 http://www.baidu.com/ 怎么做?
1、通過tcpdump截獲主機 www.baidu.com 發送與接收所有的數據包
[root@zdns.cn ~]# tcpdump -i eth0 host www.baidu.com
2、訪問這個網站
[root@zdns.cn ~]# wget www.baidu.cn
查看控制台輸出
確認序列號ack為何是1。這是相對值,如何顯示絕對值
[root@zdns.cn ~]# tcpdump -S -i eth0 host www.baidu.com
[root@zdns.cn ~]# wget www.baidu.com
再次查看控制輸出
3、想要看到詳細的http報文。怎么做?
[root@zdns.cn ~]# tcpdump -A -i eth0 host www.baidu.com
將抓取的結果存到文件,比如文件file1
[root@zdns.cn ~]# tcpdump -A -i eth0 -w filel host www.baidu.com
如何讀取這個文件的基本信息
[root@zdns.cn ~]# tcpdump -r filel
想要了解更多,比如上面的http報文
[root@zdns.cn ~]# tcpdump -A -r filel
也同時想要將確認序列號ack打印成絕對值
[root@zdns.cn ~]# tcpdump -AS -r filel
注:無參數的選項比如-A,-S,-e,等。均可以共用一個減號 'src host www.baidu.cn' 屬於expression ,如果太長,可以用單引號括起來:
[root@zdns.cn ~]# tcpdump -i eth0 'src host www. baidu.com'
4、分析抓取到的報文
16:50:11.916308 IP 192.168.152.3.52346 > 61.135.169.121.http: Flags [P.], seq 1888894293:1888894434, ack 2526934942, win 8192, Length 14 1: HTTP: GET/ HTTP/1.1
第一列是時間戳:時、分、秒、微秒
第二列是網際網路協議的名稱
第三列是報文發送方的十進制的網際網路協議地址,以及緊跟其后的端口號(偶爾會是某個協議名如http,如果在此處仍然顯示端口號加上-n選項
第四列是大於號
第五列是報文接收方的十進制的網際網路協議地址,以及緊跟其后的端口號(偶爾會是某個協議名如http,如果在此處仍然顯示端口號加上-n選項)
第六列是冒號第七列是Flags標識,可能的取值是[S.] [] [P.] [F.]
第八、九、.…列是tcp協議報文頭的一些變量值:
seq是請求同步的序列號
ack是已經同步的序列號
win是當前可用窗口大小
length是tcp協議報文體的長度
如果加入了-5選項,會看到的seg, ack是兩個冒號分割的值,分別表示變更前后的值。
7、Tcpdump 抓取 TCP 包分析
TCP傳輸控制協議是面向連接的可靠的傳輸層協議,在進行數據傳輸之前,需要在傳輸數據的兩端(客戶端和服務器端)創建一個連接,這個連接由一對插口地址唯一標識,即是在IP報文首部的源IP地址、目的IP地址,以及TCP數據報首部的源端口地址和目的端口地址。TCP首部結構如下:
注意:通常情況下,一個正常的TCP連接,都會有三個階段:1、TCP三次握手;2、數據傳送;3、TCP四次揮手
其中在TCP連接和斷開連接過程中的關鍵部分如下:
-
源端口號:即發送方的端口號,在TCP連接過程中,對於客戶端,端口號往往由內核分配,無需進程指定;
-
目的端口號:即發送目的的端口號;
-
序號:即為發送的數據段首個字節的序號;
-
確認序號:在收到對方發來的數據報,發送確認時期待對方下一次發送的數據序號;
-
SYN:同步序列編號,Synchronize Sequence Numbers;
-
ACK:確認編號,Acknowledgement Number;
-
FIN:結束標志,FINish;
1、TCP三次握手
三次握手的過程如下:
- step1. 由客戶端向服務器端發起TCP連接請求。Client發送:同步序列編號SYN置為1,發送序號Seq為一個隨機數,這里假設為X,確認序號ACK置為0;
- step2. 服務器端接收到連接請求。Server響應:同步序列編號SYN置為1,並將確認序號ACK置為X+1,然后生成一個隨機數Y作為發送序號Seq(因為所確認的數據報的確認序號未初始化);
- step3. 客戶端對接收到的確認進行確認。Client發送:將確認序號ACK置為Y+1,然后將發送序號Seq置為X+1(即為接收到的數據報的確認序號);
為什么是三次握手而不是兩次對於step3的作用,假設一種情況,客戶端A向服務器B發送一個連接請求數據報,然后這個數據報在網絡中滯留導致其遲到了,雖然遲到了,但是服務器仍然會接收並發回一個確認數據報。但是A卻因為久久收不到B的確認而將發送的請求連接置為失效,等到一段時間后,接到B發送過來的確認,A認為自己現在沒有發送連接,而B卻一直以為連接成功了,於是一直在等待A的動作,而A將不會有任何的動作了。這會導致服務器資源白白浪費掉了,因此,兩次握手是不行的,因此需要再加上一次,對B發過來的確認再進行一次確認,即確認這次連接是有效的,從而建立連接。
對於雙方,發送序號的初始化為何值有的系統中是顯式的初始化序號是0,但是這種已知的初始化值是非常危險的,因為這會使得一些黑客鑽漏洞,發送一些數據報來破壞連接。因此,初始化序號因為取隨機數會更好一些,並且是越隨機越安全。
1.Tcpdump抓TCP三次握手抓包分析
[root@zdns.cn ~]# tcpdump host 192.168.152.3 -i lo and tcp port 8080
# 接着再運行:
[root@zdns.cn ~]# curl http://192.168.152.3:8080/atbg/doc
2.控制台輸出
# TCP三次握手start
16:00:13.486776 IP 192.168.152.3.61725 > 192.168.152.3.8080: Flags [S], seq 1944916150,win 65535,options [mss 16344 ,nop ,wscale 5 , nop,nop,TS val 906474698 ecr O,sackoK,eol], length 0
16:00:13.486850 IP 192.168.152.3.8080 > 192.168.152.3.61725: Flags [S.], seq 1119565918, ack 1944916151, win 65535, options_ [mss 16344 ,nop,wscale 5,nop ,nop,TS val 906474698 ecr 906474698, sackOK, eol], length 0
16:00:13.486860 IP 192.168.152.3.61725 > 192.168.152.3.8080: Flags [.],ack 1119565919,win 12759,options [nop ,nop,TS val 906474698 ecr 906474698], length0
16:00:13. 486868 IP 192.168.152.3.8080 > 192.168.152.3.61725: Flags [.], ack 1944916151, win 12759, options [nop ,nop,TS val 906474698 ecr 906474698], length0
# TCP三次握手end
#傳輸數據start
16:00:13.486923 IP 192.168.152.3.61725 > 192.168.152..3.8080: Flags [P.], seq 1944916151:1944916238,ack 1119565919, win 12759,options [nop,nop,TS val 906474698 ecr 906474698], length 87: HTTP: GET /atbg/doc HTTP/1.1
16:00:13. .486944 IP 192.168.152.3.8080 > 192.168.152.3.61725: FLags [.],ack 1944916238, win 12756,options [nop ,nop,TS val 906474698 ecr 906474698], length0
16:00:13.489750 IP 192.168.152.3.8080 > 192.168.152.3.61725: Flags [P.], seq 1119565919:1119571913, ack 1944916238, win 12756, options [nop , nop,p,ts val 906474701 ecr 906474698], length 5994: HTTP: HTTP/1.1 200 0K
16:00:13.489784 IP 192.168.152.3.61725 > 192.168.152.3.8080: FLags [.],ack 1119571913, win 12572, options [nop,nop,TS val 906474701 ecr 906474701], length❷
#傳輸數據end
# TCP四次揮手start
16:00:13.490836 IP 192.168.152.3.61725 > 192.168.152.3.8080: Flags_ [F.], seq 1944916238, ack 1119571913,win 12572,options [nop,nop,TS val 906474702 ecr906474701],length 0
16:00:13490869 IP 192.168.152.3. 8080 > 10.37. 63.3.61725: Flags [.],ack 1944916239, win 12756, options [nop ,nop,TS val 906474702 ecr 906474702], length0
16:00:13.490875 IP 192.168.152.3.61725 > 192.168.152.3.8080: Flags [.], ack_ 1119571913, win 12572, options [nop,nop,TS val 906474702 ecr 906474702], length0
16:00:13.491004 IP 192.168.152.3.8080 > 192.168.152.3.61725: Flags [F.],seq 1119571913, ack 1944916239,win 12756, options [nop,nop,TS val 906474702 ecr906474702],length
16:00:13.491081 IP 10.37. 63.3.61725 > 192.168.152.3. 8080: Flags [.],ack 1119571914, win 12572, options [nop ,nop,TS val 906474702 ecr 906474702], length0
# TCP四次揮手end
每一行中間都有這個包所攜帶的標志:
- S=SYN,發起連接標志。
- P=PUSH,傳送數據標志。
- F=FIN,關閉連接標志。
- ack,表示確認包。
- RST=RESET,異常關閉連接。
- .,表示沒有任何標志。
第1行:16:00:13.486776,從192.168.152.3(client)的臨時端口61725向192.168.152.3(server)的8080監聽端口發起連接,client初始包序號seq為1944916150,滑動窗口大小為65535字節(滑動窗口即tcp接收緩沖區的大小,用於tcp擁塞控制),mss大小為16344(即可接收的最大包長度,通常為MTU減40字節,IP頭和TCP頭各20字節)。【seq=1944916150,ack=0,syn=1】
第2行:16:00:13.486850,server響應連接,同時帶上第一個包的ack信息,為client端的初始包序號seq加1,即1944916151,即server端下次等待接受這個包序號的包,用於tcp字節流的順序控制。Server端的初始包序號seq為1119565918,mss也是16344。【seq=1119565918,ack=1944916151,syn=1】
第3行:15:46:13.084161,client再次發送確認連接,tcp連接三次握手完成,等待傳輸數據包。【ack=1119565919,seq=1944916151】
2、TCP四次揮手
連接雙方在完成數據傳輸之后就需要斷開連接。由於TCP連接是屬於全雙工的,即連接雙方可以在一條TCP連接上互相傳輸數據,因此在斷開時存在一個半關閉狀態,即有有一方失去發送數據的能力,卻還能接收數據。因此,斷開連接需要分為四次。主要過程如下:
- step1. 主機A向主機B發起斷開連接請求,之后主機A進入FIN-WAIT-1狀態;
- step2. 主機B收到主機A的請求后,向主機A發回確認,然后進入CLOSE-WAIT狀態;
- step3. 主機A收到B的確認之后,進入FIN-WAIT-2狀態,此時便是半關閉狀態,即主機A失去發送能力,但是主機B卻還能向A發送數據,並且A可以接收數據。此時主機B占主導位置了,如果需要繼續關閉則需要主機B來操作了;
- step4. 主機B向A發出斷開連接請求,然后進入LAST-ACK狀態;
- step5. 主機A接收到請求后發送確認,進入TIME-WAIT狀態,等待2MSL之后進入CLOSED狀態,而主機B則在接受到確認后進入CLOSED狀態;
為何主機A在發送了最后的確認后沒有進入CLOSED狀態,反而進入了一個等待2MSL的TIME-WAIT主要作用有兩個:
第一,確保主機A最后發送的確認能夠到達主機B。如果處於LAST-ACK狀態的主機B一直收不到來自主機A的確認,它會重傳斷開連接請求,然后主機A就可以有足夠的時間去再次發送確認。但是這也只能盡最大力量來確保能夠正常斷開,如果主機A的確認總是在網絡中滯留失效,從而超過了2MSL,最后也無法正常斷開;
第二,如果主機A在發送了確認之后立即進入CLOSED狀態。假設之后主機A再次向主機B發送一條連接請求,而這條連接請求比之前的確認報文更早地到達主機B,則會使得主機B以為這條連接請求是在舊的連接中A發出的報文,並不看成是一條新的連接請求了,即使得這個連接請求失效了,增加2MSL的時間可以使得這個失效的連接請求報文作廢,這樣才不影響下次新的連接請求中出現失效的連接請求。
為什么斷開連接請求報文只有三個,而不是四個因為在TCP連接過程中,確認的發送有一個延時(即經受延時的確認),一端在發送確認的時候將等待一段時間,如果自己在這段事件內也有數據要發送,就跟確認一起發送,如果沒有,則確認單獨發送。而我們的抓包實驗中,由服務器端先斷開連接,之后客戶端在確認的延遲時間內,也有請求斷開連接需要發送,於是就與上次確認一起發送,因此就只有三個數據報了。
3、Wireshark 分析 Tcpdump 抓包結果
1、Tcpdump 抓包
tcpdump host 10.37.63.3 -i lo and port 8080 -n -w ./Desktop/tcpdump_10.37.63.3_8080_20160525.cap
# 然后再執行curl
curl http://10.37.63.3:8080/atbg/doc
2、Wireshark 分析
使用Wireshark打開tcpdump_10.37.63.3_8080_20160525.cap文件
- No. 1-4 行:TCP三次握手環節;
- No. 5-8 行:TCP傳輸數據環節;
- No. 9-13 行:TCP四次揮手環節;
3、查看 http 請求和響應的方法
彈窗如下圖所示,上面紅色部分為請求信息,下面藍色部分為響應信息:
以上是 Wireshark 分析 tcpdump 的簡單使用,Wireshark更強大的是過濾器工具,大家可以自行去多研究學習Wireshark.