首先了解如何從包頭過濾信息
proto[x:y] : 過濾從x字節(jié)開始的y字節(jié)數(shù)。比如ip[2:2]過濾出3凡泣、4字節(jié)(第一字節(jié)從0開始排)
proto[x:y] & z = 0 : proto[x:y]和z的與操作為0
proto[x:y] & z !=0 : proto[x:y]和z的與操作不為0
proto[x:y] & z = z : proto[x:y]和z的與操作為z
proto[x:y] = z : proto[x:y]等于z
操作符 : >, <, >=, <=, =, !=
IP頭(IPV4)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding | <-- optional
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DATA ... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
中文:
/*IP頭定義枉疼,共20個字節(jié)*/
typedef struct _IP_HEADER
{
char m_cVersionAndHeaderLen; //版本信息(前4位)皮假,頭長度(后4位)
char m_cTypeOfService; // 服務類型8位
short m_sTotalLenOfPacket; //數(shù)據(jù)包長度
short m_sPacketID; //數(shù)據(jù)包標識
short m_sSliceinfo; //分片使用
char m_cTTL; //存活時間
char m_cTypeOfProtocol; //協(xié)議類型
short m_sCheckSum; //校驗和
unsigned int m_uiSourIp; //源ip
unsigned int m_uiDestIp; //目的ip
} __attribute__((packed))IP_HEADER, *PIP_HEADER ;
-
版本:
? 指IP協(xié)議的版本,通信雙方使用的IP協(xié)議版本必須一致骂维。一般的值為0100(IPv4)惹资,0110(IPv6)。
首部長度:
? 長度4比特航闺。這個字段的作用是為了描述IP包頭的長度褪测,因為在IP包頭中有變長的可選部分。該部分占4個bit位潦刃,單位為32bit(4個字節(jié))侮措,即本區(qū)域值= IP頭部長度(單位為bit)/(84),因此乖杠,一個IP包頭的長度最長為“1111”分扎,即154=60個字節(jié)。IP包頭最小長度為20字節(jié)胧洒。
-
優(yōu)先級與服務類型:
? 長度8比特畏吓,定義了數(shù)據(jù)包傳輸?shù)木o急程度以及時延、可靠性卫漫、傳輸成本等菲饼。
總長度:
? 16比特,以字節(jié)為單位描述IP包的總長度(包括頭部和數(shù)據(jù)兩部分)列赎,最大值為65535宏悦。第二行中標識符、標志和段偏移量通常聯(lián)合使用包吝,用于數(shù)據(jù)拆分時的分組和重組饼煞。
- 標識符:
? 對于上層發(fā)來的較大的數(shù)據(jù)包,往往需要拆分诗越。路由器將一個大包進行拆分后派哲,拆出來的所有部分被標上相同的值,該值即為標識符掺喻,用于告訴目的端哪些包屬于同一個大包。
- 標志:
? 長度3比特储矩。該字段第一位不使用感耙。第二位是DF(Don't Fragment)位,DF位設為1時表明路由器不能對該上層數(shù)據(jù)包分段持隧。如果一個上層數(shù)據(jù)包無法在不分段的情況下進行轉發(fā)即硼,則路由器會丟棄該上層數(shù)據(jù)包并返回一個錯誤信息。第三位是MF(More Fragments)位屡拨,當路由器對一個上層數(shù)據(jù)包分段只酥,則路由器會在除了最后一個分段的IP包的包頭中將MF位設為1褥实。
- 段偏移量:
? 長度13比特,表示一個數(shù)據(jù)包在原先被拆分前的大包中的位置裂允。接收端據(jù)此來還原和組裝IP包损离。
- TTL:
? 表示IP包的生存時間,長度8比特绝编。長度8比特僻澎。當IP包進行傳送時,先會對該字段賦予某個特定的值十饥。當IP包經(jīng)過每一個沿途的路由器的時候窟勃,每個沿途的路由器會將IP包的TTL值減少1。如果TTL減少為0逗堵,則該IP包會被丟棄秉氧。這個字段可以防止由于路由環(huán)路而導致IP包在網(wǎng)絡中不停被轉發(fā)。
- 協(xié)議號:
? 長度8比特蜒秤,標識上一層即傳輸層在本次數(shù)據(jù)傳輸中所使用的協(xié)議汁咏。比如6代表TCP,17代表UDP等
- 首部校驗和:
? 長度16位垦藏。用來做IP頭部的正確性檢測梆暖,但不包含數(shù)據(jù)部分。 因為每個路由器要改變TTL的值,所以路由器會為每個通過的數(shù)據(jù)包重新計算這個值掂骏。
- 源地址:
? 長度32比特轰驳,標識IP包的起源地址。
- 目標地址:
? 長度32比特弟灼,表示IP包的目的地址级解。
- 可選項:
? 可變長字段,主要用于測試田绑,由起源設備跟據(jù)需要改寫勤哗。
- 填充:
? 因為IP包頭長度(Header Length)部分的單位為32bit,所以IP包頭的長度必須為32bit的整數(shù)倍掩驱。因此芒划,在可選項后面,IP協(xié)議會填充若干個0欧穴,以達到32bit的整數(shù)倍
IP選項
一般
的IP頭是20字節(jié)民逼,但IP頭有選項設置,不能直接從偏移21字節(jié)處讀取數(shù)據(jù)涮帘。IP頭有個長度字段可以知道頭長度是否大于20字節(jié)拼苍。
通常第一個字節(jié)的二進制值是:01000101,
分成兩個部分:
0100 = 4 表示IP版本
0101 = 5 表示IP頭32 bit的塊數(shù)调缨,
5 x 32 bits = 160 bits or 20 bytes
如果第一字節(jié)第二部分的值大于5疮鲫,那么表示頭有IP選項吆你。
下面介紹有過濾方法
**0100 0101 **: 第一字節(jié)的二進制
0000 1111 : 與操作
<=========
0000 0101 : 結果
正確的過濾方法:
tcpdump -i eth1 'ip[0] & 15 > 5'
或者
tcpdump -i eth1 'ip[0] & 0x0f > 5'
分片標記
當發(fā)送端的MTU大于到目的路徑鏈路上的MTU時就會被分片,分片信息在IP頭的第七和第八字節(jié):
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Bit 0: 保留俊犯,必須是0
Bit 1: (DF) 0 = 可能分片, 1 = 不分片
Bit 2: (MF) 0 = 最后的分片, 1 = 還有分片
Fragment Offset字段只有在分片的時候才使用妇多。
要抓帶DF位標記的不分片的包,第七字節(jié)的值應該是:
01000000 = 64
tcpdump -i eth1 'ip[6] = 64'
抓分片包
- 匹配MF瘫析,分片包
tcpdump -i eth1 'ip[6] = 32'
最后分片包的開始3位是0砌梆,但是有Fragment Offset字段。
- 匹配分片和最后分片
tcpdump -i eth1 '((ip[6:2] > 0) and (not ip[6] = 64))'
測試分片可以用下面的命令:
ping -M want -s 3000 192.168.1.1
匹配小TTL
TTL字段在第九字節(jié)贬循,并且正好是完整的一個字節(jié)咸包,TTL最大值是255,二進制為11111111杖虾。
可以用下面的命令驗證一下:
$ ping -M want -s 3000 -t 256 192.168.1.200
ping: ttl 256 out of range
+-+-+-+-+-+-+-+-+
| Time to Live |
+-+-+-+-+-+-+-+-+
- 在網(wǎng)關可以用下面的命令看看網(wǎng)絡中誰在使用
traceroute
tcpdump -i eth1 'ip[8] < 5'
抓大于X字節(jié)的包
- 大于600字節(jié)
tcpdump -i eth1 'ip[2:2] > 600'
更多的過濾方式
首先還是需要知道TCP基本結構
- TCP頭
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |C|E|U|A|P|R|S|F| |
| Offset| Res. |W|C|R|C|S|S|Y|I| Window |
| | |R|E|G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/*TCP頭定義烂瘫,共20個字節(jié)*/
typedef struct _TCP_HEADER
{
short m_sSourPort; //源端口號16bit
short m_sDestPort; //目的端口號16bit
unsigned int m_uiSequNum; //序列號32bit
unsigned int m_uiAcknowledgeNum; //確認號32bit
short m_sHeaderLenAndFlag; //前4位:TCP頭長度;中6位:保留奇适;后6位:標志位
short m_sWindowSize; //窗口大小16bit
short m_sCheckSum; //檢驗和16bit
short m_surgentPointer; //緊急數(shù)據(jù)偏移量16bit
}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;
/*TCP頭中的選項定義
kind(8bit)+Length(8bit坟比,整個選項的長度,包含前兩部分)+內容(如果有的話)
KIND =
1表示 無操作NOP嚷往,無后面的部分
2表示 maximum segment 后面的LENGTH就是maximum segment選項的長度(以byte為單位葛账,1+1+內容部分長度)
3表示 windows scale 后面的LENGTH就是 windows scale選項的長度(以byte為單位,1+1+內容部分長度)
4表示 SACK permitted LENGTH為2皮仁,沒有內容部分
5表示這是一個SACK包 LENGTH為2籍琳,沒有內容部分
8表示時間戳,LENGTH為10贷祈,含8個字節(jié)的時間戳
*/
16位源端口號和16位目的端口號趋急。
32位序號:
? 一次TCP通信過程中某一個傳輸方向上的字節(jié)流的每個字節(jié)的編號,通過這個來確認發(fā)送的數(shù)據(jù)有序势誊,比如現(xiàn)在序列號為1000呜达,發(fā)送了1000,下一個序列號就是2000粟耻。
32位確認號:
? 用來響應TCP報文段查近,給收到的TCP報文段的序號加1,三握時還要攜帶自己的序號挤忙。
4位頭部長度:
? 標識該TCP頭部有多少個4字節(jié)嗦嗡,共表示最長15*4=60字節(jié)。同IP頭部饭玲。
6位保留:
? 6位標志。URG(緊急指針是否有效)ACK(表示確認號是否有效)PSH(提示接收端應用程序應該立即從TCP接收緩沖區(qū)讀走數(shù)據(jù))RST(表示要求對方重新建立連接)SYN(表示請求建立一個連接)FIN(表示通知對方本端要關閉連接)
16位窗口大小:
? TCP流量控制的一個手段叁执,用來告訴對端TCP緩沖區(qū)還能容納多少字節(jié)茄厘。
16位校驗和:
? 由發(fā)送端填充矮冬,接收端對報文段執(zhí)行CRC算法以檢驗TCP報文段在傳輸中是否損壞。
16位緊急指針:
? 一個正的偏移量次哈,它和序號段的值相加表示最后一個緊急數(shù)據(jù)的下一字節(jié)的序號胎署。
標志位字段(U、A窑滞、P琼牧、R、S哀卫、F):
占6比特巨坊。各比特的含義如下:
- URG:緊急指針(urgent pointer)有效。
- ACK:確認序號有效此改。
- PSH:接收方應該盡快將這個報文段交給應用層趾撵。
- RST:重建連接。
- SYN:發(fā)起一個連接共啃。
- FIN:釋放一個連接占调。
- 窗口大小字段:占16比特。此字段用來進行流量控制移剪。單位為字節(jié)數(shù)究珊,這個值是本機期望一次接收的字節(jié)數(shù)。
- TCP校驗和字段:占16比特纵苛。對整個TCP報文段剿涮,即TCP頭部和TCP數(shù)據(jù)進行校驗和計算,并由目標端進行驗證赶站。
- 緊急指針字段:占16比特幔虏。它是一個偏移量,和序號字段中的值相加表示緊急數(shù)據(jù)最后一個字節(jié)的序號贝椿。
- 選項字段:占32比特想括。可能包括"窗口擴大因子"烙博、"時間戳"等選項瑟蜈。
- 抓取源端口大于1024的TCP數(shù)據(jù)包
tcpdump -i eth1 'tcp[0:2] > 1024'
- 匹配TCP數(shù)據(jù)包的特殊標記
TCP標記定義在TCP頭的第十四個字節(jié)
+-+-+-+-+-+-+-+-+
|C|E|U|A|P|R|S|F|
|W|C|R|C|S|S|Y|I|
|R|E|G|K|H|T|N|N|
+-+-+-+-+-+-+-+-+
- 只抓SYN包,第十四字節(jié)是二進制的00000010渣窜,也就是十進制的2
tcpdump -i eth1 'tcp[13] = 2'
- 抓SYN, ACK (00010010 or 18)
tcpdump -i eth1 'tcp[13] = 18'
- 抓SYN或者SYN-ACK
tcpdump -i eth1 'tcp[13] & 2 = 2'
- 抓PSH-ACK
tcpdump -i eth1 'tcp[13] = 24'
- 抓所有包含F(xiàn)IN標記的包(FIN通常和ACK一起铺根,表示幽會完了,回見)
tcpdump -i eth1 'tcp[13] & 1 = 1'
- 抓RST
tcpdump -i eth1 'tcp[13] & 4 = 4'
常用的字段偏移名字
tcpdump考慮了一些數(shù)字恐懼癥者的需求乔宿,提供了部分常用的字段偏移名字:
-
icmptype
(ICMP類型字段) -
icmpcode
(ICMP符號字段) -
tcpflags
(TCP標記字段)
ICMP類型值有:
icmp-echoreply
, icmp-unreach
, icmp-sourcequench
, icmp-redirect
,icmp-echo
,icmp-routeradvert
,icmp-routersolicit
,icmp-timxceed
,icmp-paramprob
,icmp-tstamp
,icmp-tstampreply
,icmp-ireq
,icmp-ireqreply
,icmp-maskreq
,icmp-maskreply
TCP標記值:
tcp-fin
, tcp-syn
, tcp-rst
, tcp-push
, tcp-push
, tcp-ack
, tcp-urg
這樣上面按照TCP標記位抓包的就可以寫直觀的表達式了:
- 只抓SYN包
tcpdump -i eth1 'tcp[tcpflags] = tcp-syn'
- 抓SYN, ACK
tcpdump -i eth1 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0'
抓SMTP數(shù)據(jù)
tcpdump -i eth1 '((port 25) and (tcp[(tcp[12]>>2):4] = 0x4d41494c))'
抓取數(shù)據(jù)區(qū)開始為"MAIL"的包位迂,"MAIL"的十六進制為0x4d41494c。
抓HTTP GET數(shù)據(jù)
tcpdump -i eth1 'tcp[(tcp[12]>>2):4] = 0x47455420'
"GET "的十六進制是47455420
抓SSH返回
tcpdump -i eth1 'tcp[(tcp[12]>>2):4] = 0x5353482D'
"SSH-"的十六進制是0x5353482D
tcpdump -i eth1 '(tcp[(tcp[12]>>2):4] = 0x5353482D) and (tcp[((tcp[12]>>2)+4):2] = 0x312E)'