DNS リゾルバキャッシュの内容を表示する


どうもみむらです。

Windows は内部に DNS キャッシュを持っていまして、
その中身というのはやはり見てみたいものです。

ただ見るだけであれば、
ipconfig /displaydns
と打てば一覧で出てきてしまいますが、
今回は API を呼び出して取得してみます。


情報を取得するためには、dnsapi.dll にある “DnsGetCacheDataTable” という API を呼び出します。

#include <Windows.h>
#include <WinDNS.h>
#pragma comment(lib,"Dnsapi.lib")

typedef LSTATUS(WINAPI *PDnsGetCacheDataTable)(PDNS_RECORD*);

void main()
{ 
	PDNS_RECORD entry; PDnsGetCacheDataTable dgcdt = (PDnsGetCacheDataTable)GetProcAddress(LoadLibrary(L"dnsapi.dll"), "DnsGetCacheDataTable");
	dgcdt(&entry);
	DnsRecordListFree(entry, DnsFreeRecordList);
}

ヘッダファイルに書かれていない API ですので、GetProcAddress で関数アドレスを取得して
動的に呼び出してやる必要があります。

image

実行しますとこのように、 “pNext” に次の情報が入った
「片方向のリンクリスト」の形で情報が入ったデータが返されます。

 

さらにここから、IP アドレスも求めるということであれば、
DnsQuery 関数を “DNS_QUERY_NO_WIRE_QUERY” ( キャッシュのみに問い合わせるオプション )を付けて呼び出すことで求まります。

#include <Windows.h>
#include <WinDNS.h>
#include <stdio.h>

#pragma comment(lib,"Dnsapi.lib")
#pragma comment(lib,"ws2_32.lib")

typedef LSTATUS(WINAPI *PDnsGetCacheDataTable)(PDNS_RECORD*);

void main()
{
	PDNS_RECORD entry, orig_entry, data;

	PDnsGetCacheDataTable dgcdt = (PDnsGetCacheDataTable)GetProcAddress(LoadLibrary(L"dnsapi.dll"), "DnsGetCacheDataTable");

	dgcdt(&orig_entry);
	entry = orig_entry;

	while (entry != NULL && entry->pNext != NULL)
	{
		DnsQuery(entry->pName, DNS_TYPE_A, DNS_QUERY_NO_WIRE_QUERY, 0, &data, 0);

		if (data != NULL)
		{
			IN_ADDR addr;

			addr.S_un.S_addr = data->Data.A.IpAddress;
			printf("%S : %s\n", entry->pName, inet_ntoa(addr));
		}

		entry = entry->pNext;
	}

	DnsRecordListFree(orig_entry, DnsFreeRecordList);
}

実行結果としてはこんな感じ:

image

・・・私がどこによくアクセスするかが丸わかりですね・・


というわけで・・
このような感じで、リゾルバキャッシュのデータを取り出すことが出来ました。

ですが、一点注意点として
“DnsGetCacheDataTable” 関数は MSDN にて明確にドキュメント化されていません。

ですので、今後呼び出し方法が変更される可能性は十分にあります。

使う場合は “現状は動く” 程度でとらえて頂ければと思います。


 

関連記事