跳到主要內容
節省工具箱Jason Tools
經驗分享

Windows DNS Server 記錄送進 Graylog

Jason Cheng 發布 瀏覽 1 次
Windows DNS Server 記錄送進 Graylog
本文目錄
  1. 架構
  2. 啟用 DNS 偵錯記錄
  3. 設定 NXLog
  4. Graylog 接收
  5. 用擷取器拆解欄位
  6. 驗證
  7. 注意事項
  8. 結論
  9. 參考資料

資安事件調查時,DNS 查詢紀錄常常是最關鍵的線索:哪台電腦查了可疑的網域、什麼時間開始連到中繼站,DNS 記錄裡都看得到。但 Windows DNS Server 預設不會記錄查詢內容,就算開了偵錯記錄,也只是一個巨大的純文字檔,很難搜尋與統計。

這篇整理把 Windows DNS Server 的查詢記錄透過 NXLog 送進 Graylog、再拆解成欄位的完整做法。

架構

Windows DNS Server(偵錯記錄檔) → NXLog(讀檔、過濾、轉碼) → GELF UDP → Graylog(擷取器拆欄位)

啟用 DNS 偵錯記錄

在 DNS 管理員中,對伺服器按右鍵選「內容」,切到「偵錯記錄」頁籤:

DNS 伺服器內容的偵錯記錄頁籤
DNS 伺服器內容的偵錯記錄頁籤

建議的勾選:

項目建議說明
記錄封包供偵錯之用勾選總開關
封包方向連入,需要時再加連出連入是用戶端送來的查詢
傳輸通訊協定UDP,需要時再加 TCP一般查詢都是 UDP
封包內容查詢/傳輸只記查詢就夠用
封包類型要求,需要時再加回應要求就有查詢的網域與類型
詳細資料不勾勾了會多出很多行,NXLog 也要另外處理
檔案路徑和名稱例如 D:\temp\dns\dns.log一定要填,否則預設寫在系統目錄
最大容量例如 500 MB達到上限時會覆寫最舊的內容

勾越多,記錄量越大,DNS 伺服器的負擔也越重。我的建議是先從「連入、UDP、查詢、要求」開始,確認記錄量可以接受,再視需要增加。

注意:偵錯記錄只有一個檔案,達到最大容量時會覆寫最舊的內容,不會切成多個檔案。NXLog 要讀的就是這一個檔案,記錄的保存交給 Graylog。

設定 NXLog

在 DNS 伺服器上安裝 NXLog,在設定檔加入:

<Extension gelf>
    Module      xm_gelf
</Extension>

<Extension charconv>
    Module      xm_charconv
</Extension>

# 空白行
define DNS_EMPTY_REGEX            /^(?:\s*)$/
# 註解行(# 或 ; 開頭)
define DNS_COMMENT_REGEX          /^\s*[#;]/
# 不是日期開頭的行(YYYY/M/D 加空白)
define DNS_NOT_DATE_START_REGEX   /^(?!\d{4}\/\d{1,2}\/\d{1,2}\s)/

<Input in_dnslog>
    Module      im_file
    File        "D:\\temp\\dns\\dns.log"
    InputType   LineBased
    SavePos     TRUE
    Exec        $raw_event = convert($raw_event, "cp950", "utf-8");
    <Exec>
        # 1) 丟掉空白行
        if $raw_event =~ %DNS_EMPTY_REGEX% { drop(); }
        # 2) 丟掉註解行
        if $raw_event =~ %DNS_COMMENT_REGEX% { drop(); }
        # 3) 丟掉不是日期開頭的行(檔頭說明、詳細資料的延續行)
        if $raw_event =~ %DNS_NOT_DATE_START_REGEX% { drop(); }

        # 整行放在 dns_message,交給 Graylog 拆解
        $dns_message = $raw_event;

        # 摘要用行尾的查詢網域
        if $raw_event =~ /\s([^\s]+)$/ {
            $short_message = $1;
        } else {
            $short_message = $raw_event;
        }

        delete($full_message);
        delete($raw_event);

        $SourceName    = "windows-dns-debug";
        $SeverityValue = 6;
    </Exec>
</Input>

<Output out_dnslog>
    Module      om_udp
    Host        192.168.1.10:12201
    OutputType  GELF
</Output>

<Route dnslog>
    Path in_dnslog => out_dnslog
</Route>

幾個重點:

  • File:要和 DNS 偵錯記錄設定的路徑一致
  • convert(..., "cp950", "utf-8"):繁體中文版 Windows 寫出的記錄是 Big5(cp950),要轉成 UTF-8,否則時間欄位裡的「上午」「下午」會變亂碼
  • 三條過濾規則:偵錯記錄檔開頭有一大段說明文字,這些都不是查詢記錄,先在 NXLog 端丟掉,不要送進 Graylog
  • Host:改成你的 Graylog 主機與 GELF UDP Input 的通訊埠

注意:第三條規則「日期開頭」是依繁體中文版 Windows 的日期格式(2025/8/19 下午 03:26:43)寫的。英文版 Windows 的格式是 8/19/2025 3:26:43 PM,這條規則會把所有記錄都丟掉,要改成對應的格式。先打開記錄檔看一下實際的格式再調整。

重新啟動 NXLog 服務後,檢查 NXLog 自己的記錄檔,看到成功連線就代表設定沒問題:

INFO [om_udp|out_dnslog] connecting to 192.168.1.10:12201
INFO [om_udp|out_dnslog] successfully connected to 192.168.1.10:12201

Graylog 接收

Graylog 要先有一個 GELF UDP 的 Input,通訊埠和 NXLog 設定的一致。收到記錄後,在搜尋頁面展開任一筆,至少會看到這些欄位:

欄位內容
dns_message完整的一行 DNS 記錄
message查詢的網域(原始格式)
SourceNamewindows-dns-debug
SourceModuleName、SourceModuleTypeNXLog 的 Input 名稱與模組
EventReceivedTimeNXLog 讀到這一行的時間

左側的「Received by」會顯示是哪個 Input 收到的,下一步要用到它。

用擷取器拆解欄位

到「System → Inputs」,找到剛才的 Input,按「Manage extractors」:

在 Input 清單中按 Manage extractors
在 Input 清單中按 Manage extractors

右上角「Actions → Import extractors」:

Import extractors
Import extractors

貼上以下 JSON,按「Add extractors to input」:

{
  "extractors": [
    {
      "title": "msdns_1",
      "extractor_type": "grok",
      "converters": [],
      "order": 0,
      "cursor_strategy": "copy",
      "source_field": "dns_message",
      "target_field": "",
      "extractor_config": {
        "grok_pattern": "%{DATA:QueryDateTime}\\s+%{WORD:thread_id}\\s+%{WORD:context}\\s+%{BASE16NUM:internal_id}\\s+%{WORD:protocol}\\s+%{WORD:direction}\\s+%{IPV4:remote_ip}\\s+%{BASE16NUM:xid}\\s+(?:(?<qr>R)\\s+)?%{WORD:opcode}\\s+\\[%{BASE16NUM:flags_hex}\\s+%{WORD:flags_codes}\\s+%{WORD:response_code}\\]\\s+%{WORD:querytype}\\s+%{GREEDYDATA:queryname_s}"
      },
      "condition_type": "none",
      "condition_value": ""
    },
    {
      "title": "msdns_queryname_s",
      "extractor_type": "regex_replace",
      "converters": [],
      "order": 1,
      "cursor_strategy": "copy",
      "source_field": "queryname_s",
      "target_field": "queryname",
      "extractor_config": {
        "regex": "\\(\\d+\\)",
        "replacement": ".",
        "replace_all": true
      },
      "condition_type": "none",
      "condition_value": ""
    },
    {
      "title": "msdns_queryname_2",
      "extractor_type": "regex_replace",
      "converters": [],
      "order": 2,
      "cursor_strategy": "copy",
      "source_field": "queryname",
      "target_field": "queryname",
      "extractor_config": {
        "regex": "^\\.+|\\.+$",
        "replacement": "",
        "replace_all": true
      },
      "condition_type": "none",
      "condition_value": ""
    }
  ],
  "version": "6.0.3"
}
貼上擷取器 JSON
貼上擷取器 JSON

三個擷取器的作用:

順序名稱作用
1msdns_1用 Grok 把整行拆成時間、方向、來源 IP、查詢類型、回應碼等欄位
2msdns_queryname_s把 DNS 記錄的網域格式 (7)master5(10)teamviewer(3)com(0) 裡的 (數字) 換成 .
3msdns_queryname_2去掉頭尾多出來的 .,得到 master5.teamviewer.com

DNS 偵錯記錄裡的網域是以「(長度)標籤」的格式記錄的,所以要經過第 2、3 步才會變成一般看得懂的網域名稱。第 3 步的取代字元我設成空字串,這樣網域頭尾才不會殘留空白。

確認順序

擷取器一定要依序執行,順序錯了欄位就拆不出來。確認清單由上到下是 msdns_1、msdns_queryname_s、msdns_queryname_2,不對的話按「Sort extractors」調整:

擷取器的順序:msdns_1 → msdns_queryname_s → msdns_queryname_2
擷取器的順序:msdns_1 → msdns_queryname_s → msdns_queryname_2

驗證

新進來的記錄就會帶有拆好的欄位:

拆解完成的 DNS 記錄
拆解完成的 DNS 記錄

分析時最常用的欄位:

欄位用途
queryname查詢的網域,找可疑網域、統計熱門網域
remote_ip發出查詢的用戶端 IP,找出是哪台電腦
querytype查詢類型(A、AAAA、MX、TXT 等),大量 TXT 查詢可能是 DNS 通道
response_code回應碼,大量 NXDOMAIN 可能是惡意程式在試網域
directionRcv 是收到的查詢,Snd 是送出的回應

例如找出查詢某個可疑網域的電腦:

queryname:*example-bad-domain.com

再用 remote_ip 做統計,就知道是哪幾台電腦。

注意事項

  • 擷取器只對新進來的記錄生效,之前收到的記錄不會重新拆解
  • 記錄量:DNS 查詢量大的環境,一天可能有上百萬筆,Graylog 的儲存空間與 index 保留期要先估算
  • 隱私:DNS 查詢紀錄可以看出每個人瀏覽了哪些網站,屬於敏感資料,存取權限要控管,並在資訊安全政策中說明
  • Windows Server 2016 以上也可以改用 DNS 的分析事件記錄(Analytic log,透過 ETW),效能影響比偵錯記錄小,但要搭配支援 ETW 的收集工具

結論

Windows DNS 偵錯記錄本身很難用,但送進 Graylog 拆成欄位之後,就能直接搜尋「誰查了什麼網域」,資安事件調查時非常有用。關鍵是 NXLog 端先轉碼、過濾掉非記錄的行,Graylog 端的擷取器順序要對。

參考資料

Jason Cheng

Jason Cheng

企業開源技術顧問,專注架構規劃與實務導入

關於作者 →

延伸閱讀