dnstap

ソース

dnstap は dnstap へのログ記録を可能にします。

概要

dnstap は DNS ソフトウェア向けの柔軟な構造化バイナリログの形式です。 https://dnstap.info を参照してください。このプラグインは、CoreDNS に dnstap ログの出力をさせます。

メッセージはすべて受信されるとすぐにソケットに送信され、dnstap プラグインには 10000 個のメッセージのバッファがあり、その数を超えると dnstap メッセージはドロップされます(これはログに記録されます)。

構文

dnstap SOCKET [full] {
  [identity IDENTITY]
  [version VERSION]
  [extra EXTRA]
  [skipverify]
}
  • SOCKET は dnstap コマンドラインツールに提供されるソケット(パス)です。
  • full はワイヤー形式の DNS メッセージを含めるかどうかを表します。
  • IDENTITY はサーバの ID を上書きします。デフォルトでは、ホスト名が使用されます。
  • VERSION はバージョンフィールドを上書きします。デフォルトでは、CoreDNS のバージョンが使用されます。
  • EXTRA は dnstap ペイロードの「追加」フィールドを定義し、メタデータ の置き換えが使用できます。
  • skipverify は接続中の TLS 検証をスキップします。デフォルトでは、安全になります。

クライアントからのリクエストと応答に関する情報を /tmp/dnstap.sock に記録します。

dnstap /tmp/dnstap.sock

クライアントからのリクエストと応答に関するワイヤー形式の DNS メッセージを含む情報を /tmp/dnstap.sock に記録します。

dnstap unix:///tmp/dnstap.sock full

リモートエンドポイントに記録します。

dnstap tcp://127.0.0.1:6000 full

FQDN でリモートエンドポイントに記録します。

dnstap tcp://example.com:6000 full

ソケットに記録し、デフォルトの ID とバージョンを上書きします。

dnstap /tmp/dnstap.sock {
  identity my-dns-server1
  version MyDNSServer-1.2.3
}

ソケットに記録し、dnstap ペイロードの「追加」フィールドをカスタマイズします。他のプラグインが提供するメタデータを追加のフィールドで使用できます。

forward . 8.8.8.8
metadata
dnstap /tmp/dnstap.sock {
  extra "upstream: {/forward/upstream}"
}

リモート TLS エンドポイントに記録します。

dnstap tls://127.0.0.1:6000 full {
  skipverify
}

複数のタップを定義するには、dnstap を繰り返し使用します。次の例は、クライアントからのリクエストと応答に関するワイヤー形式の DNS メッセージを含む情報を /tmp/dnstap.sock に記録し、さらに、ワイヤー形式の DNS メッセージなしでクライアントからのリクエストと応答をリモート FQDN に送信します。

dnstap /tmp/dnstap.sock full
dnstap tcp://example.com:6000

コマンドラインツール

Dnstap には、ログを検査するために使用できるコマンドラインツールがあります。このツールは GitHub: https://github.com/dnstap/golang-dnstap にあります。Go で記述されています。

次のコマンドは、指定されたソケットでリッスンし、メッセージをデコードして stdout に送信します。

$ dnstap -u /tmp/dnstap.sock

次のコマンドは、指定されたソケットでリッスンし、メッセージのペイロードをバイナリ dnstap 形式のログファイルに保存します。

$ dnstap -u /tmp/dnstap.sock -w /tmp/test.dnstap

ポート 6000 で dnstap メッセージをリッスンします。

$ dnstap -l 127.0.0.1:6000

プラグインで Dnstap を使用する

セットアップ関数で、構成で読み込まれたすべての dnstap プラグインのリストを収集して格納します。

x :=  &ExamplePlugin{}

c.OnStartup(func() error {
    if taph := dnsserver.GetConfig(c).Handler("dnstap"); taph != nil {
        for tapPlugin, ok := taph.(*dnstap.Dnstap); ok; tapPlugin, ok = tapPlugin.Next.(*dnstap.Dnstap) {
            x.tapPlugins = append(x.tapPlugins, tapPlugin)
        }
    }
    return nil
})

次に、プラグインで

import (
  "github.com/coredns/coredns/plugin/dnstap/msg"
  "github.com/coredns/coredns/request"

  tap "github.com/dnstap/golang-dnstap"
)

func (x ExamplePlugin) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
    for _, tapPlugin := range x.tapPlugins {
        q := new(msg.Msg)
        msg.SetQueryTime(q, time.Now())
        msg.SetQueryAddress(q, w.RemoteAddr())
        if tapPlugin.IncludeRawMessage {
            buf, _ := r.Pack() // r has been seen packed/unpacked before, this should not fail
            q.QueryMessage = buf
        }
        msg.SetType(q, tap.Message_CLIENT_QUERY)
        
        // if no metadata interpretation is needed, just send the message
        tapPlugin.TapMessage(q)

        // OR: to interpret the metadata in "extra" field, give more context info
        tapPlugin.TapMessageWithMetadata(ctx, q, request.Request{W: w, Req: query})
    }
    // ...
}

参照

dnstap.info Web サイトに dnstap プロトコルの情報があります。forward プラグインの dnstap.go は dnstap を使用してアップストリームに送信されるメッセージをタップします。