有时候,我们需要对客户端流量进行分析,了解未知的协议,但在一些严格企业级环境中,可能会遇到wireshark无法使用的情况,这时候就需要自己去编写一个本地工具以获取指定网卡流量信息。
1 | #coding=utf-8 |
TCP3次握手:
Protocol:TCP 10.126.1.209:53808 -> 172.30.1.71:80
send 12 bytes to remote.SYN=3097868532 ACK=0
0000 02 04 05 B4 01 03 03 08 01 01 04 02 <\x02><\x04><\x05><\xb4><\x01><\x03><\x03><\x08><\x01><\x01><\x04><\x02>
Protocol:TCP 10.126.1.209:53808 -> 172.30.1.71:80
send 0 bytes to remote.SYN=3097868533 ACK=1855514852
Protocol:TCP 172.30.1.71:80 -> 10.126.1.209:53808
recieved 12 bytes from remote.SYN=1855514851 ACK=3097868533
0000 02 04 05 B4 01 03 03 05 04 02 00 00 <\x02><\x04><\x05><\xb4><\x01><\x03><\x03><\x05><\x04><\x02><\x00><\x00>
TCP4次挥手:
Protocol:TCP 10.126.1.209:53808 -> 172.30.1.71:80
send 0 bytes to remote.SYN=3097869053 ACK=1855517028
Protocol:TCP 10.126.1.209:53808 -> 172.30.1.71:80
send 0 bytes to remote.SYN=3097869054 ACK=1855517029
Protocol:TCP 172.30.1.71:80 -> 10.126.1.209:53808
recieved 0 bytes from remote.SYN=1855517028 ACK=3097869054
Protocol:TCP 172.30.1.71:80 -> 10.126.1.209:53808
recieved 0 bytes from remote.SYN=1855517028 ACK=3097869054
HTTP请求:
Protocol:TCP 10.126.1.209:49981 -> 172.30.1.71:80
send 617 bytes to remote.SYN=3492030201 ACK=755814128
0000 47 45 54 20 2F 20 48 54 54 50 2F 31 2E 31 0D 0A GET / HTTP/1.1<\r><\n>
0010 48 6F 73 74 3A 20 31 37 32 2E 33 30 2E 31 2E 37 Host: 172.30.1.7
0020 31 0D 0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 1<\r><\n>Connection: k
0030 65 65 70 2D 61 6C 69 76 65 0D 0A 55 70 67 72 61 eep-alive<\r><\n>Upgra
0040 64 65 2D 49 6E 73 65 63 75 72 65 2D 52 65 71 75 de-Insecure-Requ
0050 65 73 74 73 3A 20 31 0D 0A 55 73 65 72 2D 41 67 ests: 1<\r><\n>User-Ag
0060 65 6E 74 3A 20 4D 6F 7A 69 6C 6C 61 2F 35 2E 30 ent: Mozilla/5.0
0070 20 28 57 69 6E 64 6F 77 73 20 4E 54 20 36 2E 33 (Windows NT 6.3
0080 3B 20 57 69 6E 36 34 3B 20 78 36 34 29 20 41 70 ; Win64; x64) Ap
0090 70 6C 65 57 65 62 4B 69 74 2F 35 33 37 2E 33 36 pleWebKit/537.36
00A0 20 28 4B 48 54 4D 4C 2C 20 6C 69 6B 65 20 47 65 (KHTML, like Ge
00B0 63 6B 6F 29 20 43 68 72 6F 6D 65 2F 36 38 2E 30 cko) Chrome/68.0
00C0 2E 33 34 34 30 2E 31 30 36 20 53 61 66 61 72 69 .3440.106 Safari
00D0 2F 35 33 37 2E 33 36 0D 0A 41 63 63 65 70 74 3A /537.36<\r><\n>Accept:
00E0 20 74 65 78 74 2F 68 74 6D 6C 2C 61 70 70 6C 69 text/html,appli
00F0 63 61 74 69 6F 6E 2F 78 68 74 6D 6C 2B 78 6D 6C cation/xhtml+xml
0100 2C 61 70 70 6C 69 63 61 74 69 6F 6E 2F 78 6D 6C ,application/xml
0110 3B 71 3D 30 2E 39 2C 69 6D 61 67 65 2F 77 65 62 ;q=0.9,image/web
0120 70 2C 69 6D 61 67 65 2F 61 70 6E 67 2C 2A 2F 2A p,image/apng,*/*
0130 3B 71 3D 30 2E 38 0D 0A 41 63 63 65 70 74 2D 45 ;q=0.8<\r><\n>Accept-E
0140 6E 63 6F 64 69 6E 67 3A 20 67 7A 69 70 2C 20 64 ncoding: gzip, d
0150 65 66 6C 61 74 65 0D 0A 41 63 63 65 70 74 2D 4C eflate<\r><\n>Accept-L
0160 61 6E 67 75 61 67 65 3A 20 7A 68 2D 43 4E 2C 7A anguage: zh-CN,z
0170 68 3B 71 3D 30 2E 39 0D 0A 43 6F 6F 6B 69 65 3A h;q=0.9<\r><\n>Cookie:
0180 20 63 73 72 66 74 6F 6B 65 6E 3D 63 50 33 30 30 csrftoken=cP300
0190 64 30 75 47 42 4E 49 38 75 77 4C 32 45 31 31 4A d0uGBNI8uwL2E11J
01A0 4C 66 37 42 57 6C 56 5A 32 72 57 44 4A 31 70 55 Lf7BWlVZ2rWDJ1pU
01B0 31 52 6C 6C 7A 42 35 4F 6A 6C 77 33 37 44 68 53 1RllzB5Ojlw37DhS
01C0 72 48 78 6A 36 31 46 45 6D 4C 44 3B 20 62 5F 74 rHxj61FEmLD; b_t
01D0 5F 73 3D 22 32 7C 31 3A 30 7C 31 30 3A 31 35 33 _s="2|1:0|10:153
01E0 38 32 30 33 39 34 34 7C 35 3A 62 5F 74 5F 73 7C 8203944|5:b_t_s|
01F0 34 38 3A 4F 44 59 33 4F 57 4A 69 4E 54 55 74 5A 48:ODY3OWJiNTUtZ
0200 47 55 7A 5A 69 30 30 4D 54 6B 79 4C 54 68 6D 4D GUzZi00MTkyLThmM
0210 6D 55 74 5A 6A 52 6A 4E 54 41 7A 5A 44 5A 6D 59 mUtZjRjNTAzZDZmY
0220 32 59 35 7C 62 66 30 30 65 30 36 61 32 34 33 65 2Y5|bf00e06a243e
0230 61 61 38 39 38 38 30 30 32 34 30 32 35 66 39 30 aa89880024025f90
0240 37 33 34 38 30 37 32 32 33 62 30 35 62 62 31 31 734807223b05bb11
0250 39 38 32 39 38 31 35 36 66 39 32 31 63 35 64 63 98298156f921c5dc
0260 34 65 61 31 22 0D 0A 0D 0A 4ea1"<\r><\n><\r><\n>
HTTP响应:
Protocol:TCP 172.30.1.71:80 -> 10.126.1.209:49981
recieved 238 bytes from remote.SYN=755814128 ACK=3492030818
0000 48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D HTTP/1.1 200 OK<\r>
0010 0A 53 65 72 76 65 72 3A 20 6E 67 69 6E 78 2F 31 <\n>Server: nginx/1
0020 2E 31 33 2E 39 0D 0A 44 61 74 65 3A 20 53 75 6E .13.9<\r><\n>Date: Sun
0030 2C 20 33 30 20 53 65 70 20 32 30 31 38 20 30 30 , 30 Sep 2018 00
0040 3A 35 39 3A 33 37 20 47 4D 54 0D 0A 43 6F 6E 74 :59:37 GMT<\r><\n>Cont
0050 65 6E 74 2D 54 79 70 65 3A 20 74 65 78 74 2F 68 ent-Type: text/h
0060 74 6D 6C 0D 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E tml<\r><\n>Content-Len
0070 67 74 68 3A 20 36 31 30 0D 0A 4C 61 73 74 2D 4D gth: 610<\r><\n>Last-M
0080 6F 64 69 66 69 65 64 3A 20 54 68 75 2C 20 32 37 odified: Thu, 27
0090 20 53 65 70 20 32 30 31 38 20 30 34 3A 33 39 3A Sep 2018 04:39:
00A0 31 38 20 47 4D 54 0D 0A 43 6F 6E 6E 65 63 74 69 18 GMT<\r><\n>Connecti
00B0 6F 6E 3A 20 6B 65 65 70 2D 61 6C 69 76 65 0D 0A on: keep-alive<\r><\n>
00C0 45 54 61 67 3A 20 22 35 62 61 63 35 65 66 36 2D ETag: "5bac5ef6-
00D0 32 36 32 22 0D 0A 41 63 63 65 70 74 2D 52 61 6E 262"<\r><\n>Accept-Ran
00E0 67 65 73 3A 20 62 79 74 65 73 0D 0A 0D 0A ges: bytes<\r><\n><\r><\n>
TCP为什么才用3次握手或者4次挥手呢?
我的理解是,3次握手保证了通讯双方以最少的次数确保信息传递的通路上,发送和接受都能保持通畅。
通俗来讲就是,假如A、B通讯,对于A、B都能确保——1)能收到对方发送给自己的信息;2)自己发送的信息能被对方收到。
假如只握手两次的话,A发送消息给B,B返回确认消息。 对于A来讲,能够满足上面2个条件。但对于B来讲,只能满足第一个条件,而无法满足第二个条件。
那为什么要4次挥手呢?
因为断开连接时,需要确保双方信息已经发送完毕。1)A发送结束信号给B;2)B告诉A:好的,我知道了;3)B继续发送数据完成,通知A:可以断开连接了;4)A收到B的通知后,断开连接。
补充:
ctypes 结构体位域
(位域名,c_ubyte,位域长度)
1.一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:
struct bs
{
unsigned a:4
unsigned b:5 /*从下一单元开始存放*/
unsigned c:4
}
2.由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度。
3.位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:
struct k
{
int a:1
int :2 /*无位域名,该2位不能使用*/
int b:3
int c:2
};
4.不够一个字节的位域,从后往前取bit
# -*-coding:utf-8 -*-
from ctypes import *
x = bytes("\x45\xA3\x35\x34\x56\x58\xA2\x31\x12\x89")
print bin(int("45",16)) #0b01000101
print bin(int("A3",16)) #0b10100011
print bin(int("35",16)) #0b00110101
class A(Structure):
_fields_ = [
("a",c_ubyte,3), #0b01000101,取最后3位 101 = 5
("b",c_ubyte,3), #0b01000101,再往前取3位 000 = 0
("c",c_ubyte,2), #0b01000101,取剩下的前2位 01 = 1
("d",c_ubyte,4), #0b10100011,取4位,0011 = 3
("e",c_ubyte,5) #0b00110101 前面剩余的位数不够,所以新使用一个字节,取后5位, 10101 = 21
]
def __new__(self,bytesBuffer):
return self.from_buffer_copy(bytesBuffer)
def __init__(self,bytesBuffer):
pass
if __name__ == '__main__':
print A(x).a #5
print A(x).b #0
print A(x).c #1
print A(x).d #3
print A(x).e #21