1.操作步骤:



1.1 服务器端安装rpcapd程序

1.2 本地Wireshark安装和配置

1.3 自定义应用层协议解析



1.1 服务器端安装rpcapd程序

①安装glibc程序,C运行库


redhat/centos系列安装
 
  
sudo yum install glibc-static
 
  

 
  
debian/ubuntu系列安装
 
  
sudo apt-get install libc6-dev


② 下载rpcapd安装包,也可以官网下载


wget http://www.winpcap.org/install/bin/WpcapSrc_4_1_2.zip
 
  
unzip WpcapSrc_4_1_2.zip



③ 编译rpcapd


cd winpcap/wpcap/libpcap
 
  
chmod +x configure runlex.sh
 
  
CFLAGS=-static ./configure
 
  
make
 
  
cd rpcapd && make


④ 运行rpcapd


./rpcapd -n -d


⑤ 检查rpcapd运行状态


netstat -nltp|grep rpcapd



查看端口和进程是否正常,默认端口2002





wireshark抓app wireshark抓app直播源_字段




1.2 本地Wireshark安装和配置

①安装wireshark程序




wireshark抓app wireshark抓app直播源_字段_02




②配置远程捕获接口(可以此时设置捕获过滤器条件)



wireshark抓app wireshark抓app直播源_Lua_03




③查看效果



wireshark抓app wireshark抓app直播源_wireshark抓app_04




1.3 自定义应用层协议解析

①Wireshark上配置Lua脚本插件地址



wireshark抓app wireshark抓app直播源_Lua_05




wireshark抓app wireshark抓app直播源_Wireshark_06


②Lua脚本文件如下packet-dt.lua(解析器表部分根据自己需要监听的UDP端口更改):


do
    local proto = Proto("SRUDP","Stream Rapid UDP")
    --协议的各个字段
    local f_protocol = ProtoField.uint32("SRUDP.protocol","Protocol", base.DEC)
    local f_version = ProtoField.uint32("SRUDP.version","Version", base.DEC)
    local f_msgCode = ProtoField.uint32("SRUDP.msgCode","MsgCode", base.DEC)
    local f_msgType = ProtoField.string("SRUDP.msgType","MsgType", base.UTF8)
    local f_connectId = ProtoField.uint64("SRUDP.connectId","ConnectId", base.DEC)
    local f_msgSeq = ProtoField.uint32("SRUDP.msgSeq","MsgSeq", base.DEC)
    local f_streamHash = ProtoField.uint64("SRUDP.streamHash","StreamHash", base.DEC)
    local f_tsIdx = ProtoField.uint32("SRUDP.tsIdx","TsIdx", base.DEC)
    local f_piecesCount = ProtoField.uint32("SRUDP.piecesCount","PiecesCount", base.DEC)
    local f_pieceSeq = ProtoField.uint32("SRUDP.pieceSeq","PieceSeq", base.DEC)
    local f_timestamp = ProtoField.uint64("SRUDP.timestamp","Timestamp", base.DEC)
    local f_payloadEncrypt = ProtoField.uint16("SRUDP.payloadEncrypt","PayloadEncrypt", base.DEC)
    local f_payloadType = ProtoField.uint16("SRUDP.payloadType","PayloadType", base.DEC)
    local f_payloadLength = ProtoField.uint32("SRUDP.payloadLength","PayloadLength", base.DEC)
    local f_requestParams = ProtoField.string("SRUDP.requestParams","RequestParams", base.UTF8)
    local f_body = ProtoField.bytes("SRUDP.body","Body")


    --这里把DT协议的全部字段都加到proto这个变量的fields字段里
    proto.fields = {
    f_protocol,
    f_version,
    f_msgCode,
    f_msgType,
    f_connectId,
    f_msgSeq,
    f_streamHash,
    f_tsIdx,
    f_piecesCount,
    f_pieceSeq,
    f_timestamp,
    f_payloadEncrypt,
    f_payloadType,
    f_payloadLength,
    f_requestParams,
    f_body
    }
    
    local function SRUDP_dissector(buf,pkt,root)
        local buf_len = buf:len();
        --先检查报文长度,太短的不是我的协议
        if buf_len > 1388 then return false end


        --验证一下identifier这个字段是不是0x12,如果不是的话,认为不是我要解析的packet
        local v_protocol = buf(0, 4)
        local v_version = buf(4, 4)
        local v_msgCode = buf(8, 4)
        local v_msgType
        local v_code = v_msgCode:uint()
        if(v_code == 1000)
        then
            v_msgType = 'SUBSCRIBE_AND_LOGIN'
        elseif(v_code == 1001)
        then
            v_msgType = 'SUBSCRIBE_ACK'
        elseif(v_code == 1002)
        then
            v_msgType = 'UNSUBSCRIBE'
        elseif(v_code == 1100)
        then
            v_msgType = 'NOTIFY_INDEX'
        elseif(v_code == 1101)
        then
            v_msgType = 'INDEX_REQUEST'
        elseif(v_code == 1200)
        then
            v_msgType = 'BLOCK_PUSH_RESPONSE'
        elseif(v_code == 1201)
        then
            v_msgType = 'BLOCK_REQUEST'
        elseif(v_code == 1300)
        then
            v_msgType = 'HEARTBEAT_REQUEST'
        elseif(v_code == 1301)
        then
            v_msgType = 'HEARTBEAT_RESPONSE'
        else
            v_msgType = 'UNKNOWN_MSG'
        end
        
            
        local v_connectId = buf(12, 8)
        local v_msgSeq = buf(20, 4)
        local v_streamHash = buf(24, 8)
        local v_tsIdx = buf(32, 4)
        local v_piecesCount = buf(36, 4)
        local v_pieceSeq = buf(40, 4)
        local v_timestamp = buf(44, 8)
        local v_payloadEncrypt = buf(52, 2)
        local v_payloadType = buf(54, 2)
        local v_payloadLength = buf(56, 4)
        local v_requestParams;
        local v_body;
        if(buf_len<1000)
        then
            v_requestParams = buf(60, buf_len-60)
        else    
            v_body = buf(60, buf_len-60)
        end
            


        
        --现在知道是我的协议了,放心大胆添加Packet Details
        local t = root:add(proto,buf)
        --在Packet List窗格的Protocol列可以展示出协议的名称
        pkt.cols.protocol = "SRUDP"
        --这里是把对应的字段的值填写正确,只有t:add过的才会显示在Packet Details信息里. 所以在之前定义fields的时候要把所有可能出现的都写上,但是实际解析的时候,如果某些字段没出现,就不要在这里add
        t:add(f_protocol,v_protocol)
        t:add(f_version,v_version)
        t:add(f_msgCode,v_msgCode)
        t:add(f_msgType,v_msgType)
        t:add(f_connectId,v_connectId)
        t:add(f_msgSeq,v_msgSeq)
        t:add(f_streamHash,v_streamHash)
        t:add(f_tsIdx,v_tsIdx)
        t:add(f_piecesCount,v_piecesCount)
        t:add(f_pieceSeq,v_pieceSeq)
        t:add(f_timestamp,v_timestamp)
        t:add(f_payloadEncrypt,v_payloadEncrypt)
        t:add(f_payloadType,v_payloadType)
        t:add(f_payloadLength,v_payloadLength)
        if(buf_len<1000)
        then
            t:add(f_requestParams,v_requestParams)
        else    
            t:add(f_body,v_body)
        end
                                              
        return true
    end
    
    
    --这里是获取data这个解析器
    local data_dis = Dissector.get("data")
    
    --这段代码是目的Packet符合条件时,被Wireshark自动调用的,是proto的成员方法
    function proto.dissector(buf,pkt,root)
        if SRUDP_dissector(buf,pkt,root) then
        else
            --data这个dissector几乎是必不可少的;当发现不是我的协议时,就应该调用data
            data_dis:call(buf,pkt,root)
        end
    end
    
    local udp_encap_table = DissectorTable.get("udp.port")
    --因为我们的DT协议的接受端口肯定是50002,所以这里只需要添加到"udp.port"这个DissectorTable里,并且指定值为50002即可。
    udp_encap_table:add(33188, proto)
    udp_encap_table:add(8891, proto)
end

③Lua脚本文件每次更新需要重新载入Lua插件



wireshark抓app wireshark抓app直播源_wireshark抓app_07




④效果查看




wireshark抓app wireshark抓app直播源_Wireshark_08



⑤现在可以实时解析远程服务器的发包收包情况了,同时可以自行解析应用层协议。优化点如下:

    1)监听接口时,精细化捕获过滤器条件,这样会减少解析包的数量。

    2)精细化显示过滤器条件,更专注于自定义协议解析。如只展示srudp协议

    3)优化lua脚本,当前使用udp.port解析器表来匹配自定义解析器,需要手动配置关联监听的UDP端口号,每次都需要手动关联并重新加载Lua插件。寻找一种更方便的匹配方式。

    4)Wireshark包解析界面,展示应用层消息类型和消息序号至主界面,对发包收包分别着色展示。