golang拥有wireshark数据包解析能力
- 1. 功能和实现
wireshark拥有世界上最全面的协议解析能力并且还在不断更新中,通过调研,没有办法找到与wireshark同水平的解析工具。
为了使得golang语言可以拥有wireshark一样强大的协议解析能力,库 gowireshark通过golang --wrap–> c --wrap–> wireshark dll的形式做到了这点。
1. 功能和实现
简单来看下这个库的功能,并分析它的实现:
-
可以读取离线pcap文件或者抓取指定网卡数据包并解析
其中c封装的接口在include/目录的
lib.h
、offline.h
、online.h
中,print_xxx开头的接口调用的是原生的wireshark接口proto_tree_print
打印协议树,print_hex_data
打印十六进制;
get_proto_tree_json
接口封装的get_proto_tree_json
函数明显是改变自原生wireshark接口write_json_proto_tree
(print.c文件中),原本write_json_proto_tree
生成和输出json结果使用的是jdump对象,修改后使用cJson替代。 -
支持像wireshark一样解析各种协议,并输出为json格式,字段也能翻译成wireshark一样的解释性文字:
json结果:
{
"_index": "packets-2020-12-14",
"_type": "doc",
"_score": {},
"offset": ["0000", "0010", "0020", "0030", "0040", "0050", "0060"],
"hex": ["00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 02", "00 58 00 01 40 00 40 84 3c 1d 7f 00 00 01 7f 00", "00 01 98 3a 96 48 a6 25 c3 63 00 00 00 00 00 03", "00 38 e3 0b 04 a7 00 00 00 00 00 00 00 3e 40 01", "00 0e 00 00 02 00 4e 00 02 00 14 00 00 00 01 00", "00 00 00 00 00 00 00 00 00 00 00 00 00 00 d0 55", "79 4b 65 55 00 00 "],
"ascii": ["..............E.", ".X..@.@.<.......", "...:.H.%.c......", ".8...........>@.", "......N.........", "...............U", "yKeU.."],
"_source": {
"layers": {
"frame": {
"frame.section_number": "1",
"frame.interface_id": "0",
"frame.encap_type": "Ethernet (1)",
"frame.time": "Dec 14, 2020 16:01:11.974420814 UTC",
"frame.offset_shift": "0.000000000 seconds",
"frame.time_epoch": "1607961671.974420814 seconds",
"frame.time_delta": "0.000021538 seconds",
"frame.time_delta_displayed": "0.000021538 seconds",
"frame.time_relative": "0.000000000 seconds",
"frame.number": "5",
"frame.len": "102",
"frame.cap_len": "102",
"frame.marked": "False",
"frame.ignored": "False",
"frame.protocols": "eth:ethertype:ip:sctp:f1ap"
},
"eth": {
"eth.dst": "00:00:00:00:00:00 (00:00:00:00:00:00)",
"eth.dst_tree": {
"eth.dst_resolved": "00:00:00:00:00:00",
"eth.dst.oui": "00:00:00",
"eth.addr": "00:00:00:00:00:00 (00:00:00:00:00:00)",
"eth.addr_resolved": "00:00:00:00:00:00",
"eth.addr.oui": "00:00:00",
"eth.dst.lg": "Globally unique address (factory default)",
"eth.lg": "Globally unique address (factory default)",
"eth.dst.ig": "Individual address (unicast)",
"eth.ig": "Individual address (unicast)"
},
"eth.src": "00:00:00:00:00:00 (00:00:00:00:00:00)",
"eth.src_tree": {
"eth.src_resolved": "00:00:00:00:00:00",
"eth.src.oui": "00:00:00",
"eth.addr": "00:00:00:00:00:00 (00:00:00:00:00:00)",
"eth.addr_resolved": "00:00:00:00:00:00",
"eth.addr.oui": "00:00:00",
"eth.src.lg": "Globally unique address (factory default)",
"eth.lg": "Globally unique address (factory default)",
"eth.src.ig": "Individual address (unicast)",
"eth.ig": "Individual address (unicast)"
},
"eth.type": "IPv4 (0x0800)"
},
"ip": {
"ip.version": "4",
"ip.hdr_len": "20",
"ip.dsfield": "0x02",
"ip.dsfield_tree": {
"ip.dsfield.dscp": "Default (0)",
"ip.dsfield.ecn": "ECN-Capable Transport codepoint '10' (2)"
},
"ip.len": "88",
"ip.id": "0x0001 (1)",
"ip.flags": "0x02",
"ip.flags_tree": {
"ip.flags.rb": "Not set",
"ip.flags.df": "Set",
"ip.flags.mf": "Not set"
},
"ip.frag_offset": "0",
"ip.ttl": "64",
"ip.proto": "SCTP (132)",
"ip.checksum": "0x3c1d",
"ip.checksum.status": "Unverified",
"ip.src": "127.0.0.1",
"ip.addr": "127.0.0.1",
"ip.src_host": "127.0.0.1",
"ip.host": "127.0.0.1",
"ip.dst": "127.0.0.1",
"ip.dst_host": "127.0.0.1"
},
"sctp": {
"sctp.srcport": "38970",
"sctp.dstport": "38472",
"sctp.verification_tag": "0xa625c363",
"sctp.assoc_index": "65535",
"sctp.port": "38970",
"sctp.checksum": "0x00000000",
"sctp.checksum.status": "Unverified",
"DATA chunk (ordered, complete segment, TSN: 0, SID: 0, SSN: 0, PPID: 62, payload length: 40 bytes)": {
"sctp.chunk_type": "DATA (0)",
"sctp.chunk_type_tree": {
"sctp.chunk_bit_1": "Stop processing of the packet",
"sctp.chunk_bit_2": "Do not report"
},
"sctp.chunk_flags": "0x03",
"sctp.chunk_flags_tree": {
"sctp.data_i_bit": "Possibly delay SACK",
"sctp.data_u_bit": "Ordered delivery",
"sctp.data_b_bit": "First segment",
"sctp.data_e_bit": "Last segment"
},
"sctp.chunk_length": "56",
"sctp.data_tsn": "0",
"sctp.data_tsn_raw": "3809150119",
"sctp.data_sid": "0x0000",
"sctp.data_ssn": "0",
"sctp.data_payload_proto_id": "F1 AP (62)"
}
},
"f1ap": {
"per.choice_index": "1",
"f1ap.F1AP_PDU": "successfulOutcome (1)",
"f1ap.F1AP_PDU_tree": {
"f1ap.successfulOutcome_element": {
"f1ap.procedureCode": "id-F1Setup (1)",
"per.enum_index": "0",
"f1ap.criticality": "reject (0)",
"per.open_type_length": "14",
"f1ap.value_element": {
"f1ap.F1SetupResponse_element": {
"per.extension_bit": "0",
"per.sequence_of_length": "2",
"f1ap.protocolIEs": "2",
"f1ap.protocolIEs_tree": {
"Item 0: id-TransactionID": {
"f1ap.ProtocolIE_Field_element": {
"f1ap.id": "id-TransactionID (78)",
"per.enum_index": "0",
"f1ap.criticality": "reject (0)",
"per.open_type_length": "2",
"f1ap.value_element": {
"per.extension_present_bit": "0",
"f1ap.TransactionID": "20"
}
}
},
"Item 1: id-Cause": {
"f1ap.ProtocolIE_Field_element": {
"f1ap.id": "id-Cause (0)",
"per.enum_index": "0",
"f1ap.criticality": "reject (0)",
"per.open_type_length": "1",
"f1ap.value_element": {
"per.choice_index": "0",
"f1ap.Cause": "radioNetwork (0)",
"f1ap.Cause_tree": {
"per.extension_present_bit": "0",
"per.enum_index": "0",
"f1ap.radioNetwork": "unspecified (0)"
}
}
}
}
}
}
}
}
}
}
}
}
}
- 目前好像还有内存泄露问题和支持多设备实时读取解析功能,wireshark应该无法在线程或协程层面实现并发读取解析,如果使用这个库,也许可以通过docker启动多个微服务来做到。