0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

tcpdumpで得たパケットキャプチャをJavaで読み込む

Posted at

tcpdumpでパケットキャプチャした結果を読みたいが、Wiresharkで調べるのではなく、なんらかのプログラムで読み込ませたい。pktsというJavaライブラリを使って読み込むことができたので、実施した内容をメモする。

キャプチャを行なったコマンド

TCPハンドシェイクの最初のSYNパケットとDNS応答から、通信先のドメインの一覧を取得したいので以下のようにフィルターを設定した

# 次の条件のいずれか満たすパケットを抽出する
# - SYNフラグが立っている、かつ、ACKフラグが立っていない
# - 送信元ポートが53(DNS)
sudo tcpdump -s 0 -i en0 -nn -w tcpdump.pcap \('(tcp[tcpflags] & tcp-syn)' != 0 and '(tcp[tcpflags] & tcp-ack) ==0'\) or src port 53

Javaで読み込む方法

pktsというJavaライブラリを使った。簡単な実装例の一部は以下の通り。

final Pcap pcap = Pcap.openStream("tcpdump.pcap");
pcap.loop(new PacketHandler() {
  @Override
  public boolean nextPacket(Packet packet) throws IOException {
    if (packet.hasProtocol(Protocol.UDP)) {
      System.out.println(packet.getPacket(Protocol.UDP).getPayload());
    }
  }  
}

IPv4やUDPの場合、パケットを取得することでそのヘッダー部分の情報を取得できる。

if (packet.hasProtocol(Protocol.IPv4)) {
  IPv4Packet ipv4Packet = (IPv4Packet) packet.getPacket(Protocol.IPv4);
  String srcIP = ipv4Packet.getSourceIP();
  String dstIP = ipv4Packet.getDestinationIP();
}

Payloadの内容を読み込みたい場合は、以下のような方法でバイト配列として取得できる。

UDPPacket udpPacket = (UDPPacket) packet.getPacket(Protocol.UDP);
Buffer buffer = udpPacket.getPayload();
byte[] bytes = buffer.getArray();

DNSのパケットとしてパースする部分は、DNSのパケットフォーマットを参考にして自前で書く必要がある。DNSの場合はドメイン部分や応答の数が可変なのでやや面倒。フォーマットを気にせずにとりあえず文字で読むことだけを目指して非常に雑に実装したものはこちら

参考にしたリンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?