Tcpcopy兩種架構原理詳解 2
Tcpcopy傳統架構在產品中實踐遇到一些問題,要理解和解決問題深入了解Tcpcopy兩種的架構的原理是必須的。當了解的越多就發現它不僅僅是一個工具,而需要掌握不僅僅是簡單的幾個使用命令。
Tcpcopy傳統架構與新架構最大的區別:傳統架構的intercept進程與測試服務器在同一臺機器上,新架構的intercept進程從測試服務器上offload出來,單獨部署在輔助服務器上。下面分別對兩種結構的原理詳細介紹。
傳統架構
Tcpcopy
傳統架構下,在線機器上面抓取請求數據包,默認采用raw socket input 接口。raw socket(原始套接字)可以接收本機網卡上的數據幀或者數據包,可監聽網絡的流量和分析。可以通過3種方式創建這類socket ,這里只詳細講tcpcopy使用的函數。Raw_socket的原理和其它使用方式,可參考 http://blog.sina.com.cn/s/blog_9599e95101010w2g.html
抓包函數:int sock = socket(AF_INET,SOCK_RAW,IPPROTO_TCP)。 第一個參數表示協議簇, AF_INET 代表TCP/IP協議。第二個參數表示SOCKET類型。第三個參數表協議類型。該套接字可以接收協議類型為tcp(也可以設置其它協議類型)發往本機的IP數據包,不能收到非發往本機IP的數據包(IP軟過濾會丟棄這些不是發往本機的數據包)。Tcpcopy利用Raw Socket只抓進來的包,而不能收到從本機發送出去的數據包這一特點,實現抓包的功能。系統在IP層會檢查有沒有進程創建這種類型的raw socket,如果有,這個包就會被復制一份并發送到這個socket的緩沖區,Tcpcopy就是通過這種方式來復制訪問流量的。
在發包前,調用函數sock = socket(AF_INET, SOCK_RAW,IPPROTO_RAW),并且設置setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &n, sizeof(n)),這樣IP數據包頭部就可以由用戶自己編寫(在不設置這個選項的情況下,IP協議會自動填充IP數據包的首部),Tcpcopy利用此函數將數據包的目的IP和端口改為測試機的IP和端口,如下:tcp_header->dest = remote_port;
ip_header->daddr = remote_ip;最后調用sendto函數發送包到測試前端機:
send_len = sendto(sock,(char *)ip_header,tot_len,0,(struct sockaddr *)&toaddr,sizeof(toaddr));
Intercept
測試機上Intercept進程主要完成的是對復制請求的響應包進行處理。復制的請求到達測試機經應用程序處理后的響應包如果不經處理,將會返回給線上客戶端。Tcpcopy傳統架構的使用需要Iptable這一工具輔助實現對響應包的處理。
modprobe ip_queue
iptables -I OUTPUT -p tcp –sport 2080 -j QUEUE
以上iptable命令,表示OUTPUT鏈從2080端口發出的包在IP層會被匹配發往目標QUEUE,而QUEUE是由ip_queue模塊實現(http://bbs.chinaunix.net/thread-1941806-1-1.shtml).因此在使用iptable命令前,內核需要使用modprobbe命令加載ip_queue模塊。有了以上兩個步驟, 所有匹配到iptable命令的報文將會調用IP Queue模塊的相關函數。
Tcpcopy服務器端的Intercept進程用如下方式創建Netlink socket:
int sock = socket(AF_NETLINK,SOCK_RAW,NETLINK_FIREWALL);
Netlink詳細介紹http://linux.chinaunix.net/techdoc/beginner/2008/11/12/1044982.shtml。
NETLINK_FIREWALL協議有三種消息類型:IPQM_MODE,IPQM_PACKET,IPQM_VERDICT.其中內核通過IPQM_PACKET消息將剛才截獲的返回結果包發送到Inercept。Intercept給內核發送一個IPQM_VERDICT消息告訴內核對這個包的裁決結果(DROP,ACCEPT)。Tcpcopy通過這樣的辦法將測試機上應用返回的結果截獲丟棄,并由Intercept返回一個Ip header。 Tcpcopy利用這個特點保留了一個允許訪問的ip列表,因為默認情況下訪問測試前端機上應用服務所得到的結果會在IP層被drop掉,造成在2080端口上無法訪問應用服務。有了這個白名單,即使是設置了iptables規則,在白名單內的機器上也是可以正常訪問測試前端機上的應用服務的。
新架構
Tcpcopy
新架構的Tcpcopy進程的實現與舊架構相比差別不大,在線機器上面抓請求數據包默認采用raw socket input 接口,增加了采用pcap 接口抓包的功能。Libpcap是Packet Capture Libray的英文縮寫,即數據包捕獲函數庫。該庫提供的C函數接口用于捕捉經過指定網絡接口的數據包,該接口應該是被設為混雜模式。常用的抓包軟件Tcpdump就是在Libpcap的基礎上開發而成的。Libpcap提供的接口函數實現和封裝了與數據包截獲有關的過程,工作原理不贅述,詳細可參考http://www.cnblogs.com/coder2012/archive/2013/04/13/3012390.html。根據使用手冊上的描述,新架構一般推薦使用Pcap抓包,安裝命令如下:
./configure --enable-advanced --enable-pcap
make
make install
新架構和傳統架構一樣,默認使用Raw socket output 接口發包,采用Raw Socket命令發包命令如下: ./tcpcopy -x 80-測試機IP:測試機應用端口 -s 服務服務器IP -i eth0 。其中-i參數指定pcap從哪個網卡抓取請求包。
此外,新架構還支持通過pcap_inject(編譯時候增加--enable-dlinject)來發包。使用pcap_inject發包有兩點好處:1.可以避開在線機器在IP層的防火墻設置,因為tcpcopy進程復制過來的包源IP還是線上客戶端的IP,在線機器上可能會被直接扔掉,在不能改變防火墻設置的情況下,采用pacp_inject直接從數據鏈路層發包,可以避開IP層復雜的防火墻設置;2.在壓力比較大的場合推薦使用pcap_inject 來發包,根據測試結果來看合理利用pcap_inject 來發包可提高30%的性能(詳見使用手冊),但是pcap_inject發包需要知道數據包從在線機器發出下一跳的網卡地址,這需要使用tcpdump工具抓包獲取.
Pcap發包命令:sudo ./tcpcopy -x 在線端口號@在線機器的出口網卡地址-測試機器的IP地址:測試機器的端口@下一跳網卡地址 -s 運行intercept的機器IP地址 -o 出口網卡設備 -i 抓包網卡設備。
測試服務器
新架構測試機部署上,需要更改其路由設置,目的是將測試應用程序的響應包路由到輔助測試服務器。以外網應用為例如下:
刪除測試服務器的外網IP的默認路由
route del default gw 原外網網關IP
添加輔助測試服務器IP作為測試服務器的默認路由
route add default gw 輔助服務器的外網IP
這里的意思就是說,在測試服務器返回給客戶端的響應走默認網關-輔助服務器的外網IP,但這臺機器其實并沒有開啟路由模式,所以這些響應包到了輔助測試機后,會在ip層被drop掉,這樣internet進程就可以在輔助測試服務器的數據鏈路層抓到這些響應包
輔助服務器
輔助服務器主要是用于捕獲測試服務器轉發過來的響應包,輔助服務器要確保沒有開啟路由模式cat /proc/sys/net/ipv4/ip_forward,為0表示沒有開啟。輔助服務器上采用的也是pcap抓取響應包,安裝命令如下:
./configure --enable-advanced --enable-pcap
make
make install
輔助服務器intercept進程通過pcap抓取測試機應用程序的響應包,將頭部抽取后發送給線上的tcpcopy進程,完成一次請求的復制。
小結:
Tcpcopy兩種架構都是通過巧妙地應用一些網絡工具和包實現其復制轉發的功能,傳統架構rawsocket+iptable+netlink,新架構pacp+route,通過對其深入的了解也拓展了許多網絡知識,在之后遇到一些問題也可以比較清楚明白的去解釋和分析。
對比兩種架構的原理和實踐中遇到的問題可以得出,傳統架構更容易實施,但是由于它借助于linux的IP_QUEUE模塊,其性能完全依賴于系統,在壓力較大時性能表現較差;而新架構將測試機和輔助服務器分離開來,性能有所提升,但是在部署實施受硬件條件制約,比如測試機和輔助測試服務器需在一個網段等,同時需要用到的網絡知識更多。在使用時,結合條件選擇合適的架構。
相關文章: