Ryuのソースコードリーディング その2 パケットの解析
バイナリデータからパケットのデコード
バイナリデータは、Wiresharkでキャプチャした以下のTCPのSYNパケットを用いました。
以下が、SYNパケットのバイナリ(実際には文字列)になります。
08002745b4a308002700187a080045000030239e40008006e50dc0a83865c0
a83866ed6d00162a94e8ad0000000070022000703d0000020405b401010402
上の文字列(str)を一度バイナリ(bin)に変換してから、Packetクラスを作成しました。その後クラスメソッドのget_protocolを用いて、イーサフレーム(pkt_eth)とipv4(pkt_ip)とtcp(pkt_tcp)のヘッダを取り出しました。確かにデコードされた結果、Wiresharkの値と同じものが表示されていることがわかります。
>>> from ryu.lib.packet import * >>> import binascii >>> str = "08002745b4a308002700187a080045000030239e40008006e50dc0a83865c0a83866ed6d00162a94e8ad0000000070022000703d0000020405b401010402" >>> bin = binascii.a2b_hex(str) >>> bin "\x08\x00'E\xb4\xa3\x08\x00'\x00\x18z\x08\x00E\x00\x000#\x9e@\x00\x80\x06\xe5\r\xc0\xa88e\xc0\xa88f\xedm\x00\x16*\x94\xe8\xad\x00\x00\x00\x00p\x02 \x00p=\x00\x00\x02\x04\x05\xb4\x01\x01\x04\x02" >>> pkt = packet.Packet(data=bin) >>> pkt ethernet(dst='08:00:27:45:b4:a3',ethertype=2048,src='08:00:27:00:18:7a'), ipv4(csum=58637,dst='192.168.56.102',flags=2,header_length=5,identification=9118,offset=0,option=None,proto=6,src='192.168.56.101',tos=0,total_length=48,ttl=128,version=4), tcp(ack=0,bits=2,csum=28733,dst_port=22,offset=7,option='\x02\x04\x05\xb4\x01\x01\x04\x02',seq=714401965,src_port=60781,urgent=0,window_size=8192) >>> pkt_eth = pkt.get_protocol(ethernet.ethernet) >>> pkt_eth ethernet(dst='08:00:27:45:b4:a3',ethertype=2048,src='08:00:27:00:18:7a') >>> pkt_ip = pkt.get_protocol(ipv4.ipv4) >>> pkt_ip ipv4(csum=58637,dst='192.168.56.102',flags=2,header_length=5,identification=9118,offset=0,option=None,proto=6,src='192.168.56.101',tos=0,total_length=48,ttl=128,version=4) >>> pkt_tcp = pkt.get_protocol(tcp.tcp) >>> pkt_tcp tcp(ack=0,bits=2,csum=28733,dst_port=22,offset=7,option='\x02\x04\x05\xb4\x01\x01\x04\x02',seq=714401965,src_port=60781,urgent=0,window_size=8192)
以下の結果からパケットクラスの__init__の処理により、リストのprotocolsにプロトコルのヘッダがあり、文字列のdataに引数のバイナリがあることが確認できます。
>>> pkt.protocols [ethernet(dst='08:00:27:45:b4:a3',ethertype=2048,src='08:00:27:00:18:7a'), ipv4(csum=58637,dst='192.168.56.102',flags=2,header_length=5,identification=9118,offset=0,option=None,proto=6,src='192.168.56.101',tos=0,total_length=48,ttl=128,version=4), tcp(ack=0,bits=2,csum=28733,dst_port=22,offset=7,option='\x02\x04\x05\xb4\x01\x01\x04\x02',seq=714401965,src_port=60781,urgent=0,window_size=8192)] >>> type(pkt.protocols) <type 'list'> >>> pkt.data "\x08\x00'E\xb4\xa3\x08\x00'\x00\x18z\x08\x00E\x00\x000#\x9e@\x00\x80\x06\xe5\r\xc0\xa88e\xc0\xa88f\xedm\x00\x16*\x94\xe8\xad\x00\x00\x00\x00p\x02 \x00p=\x00\x00\x02\x04\x05\xb4\x01\x01\x04\x02" >>> type(pkt.data) <type 'str'>