Wazuh Decoders & Rules: โมเดลความเข้าใจที่หายไป
คู่มือฉบับสมบูรณ์สำหรับมือใหม่ — อธิบายว่า Wazuh decoders และ rules ทำงานร่วมกันอย่างไร, field คืออะไร, มาจากไหน, เมื่อไหรต้องใช้ decoder และ log กลายเป็น alert ได้อย่างไร
Tags: Wazuh · OSSEC · SIEM · Blue Team · Detection Engineering
ระดับ: มือใหม่ → ระดับกลาง | เวลาอ่าน: 15 นาที
ถ้าคุณเคยมองไฟล์ Wazuh rule แล้วถามตัวเองว่า:
- "field นี้มาจากไหนกันแน่ — จาก rule, decoder หรือ log ตัวเอง?"
- "จำเป็นต้องมี decoder ไหมถึงจะให้ rule ทำงานได้?"
- "ทำไม rule
<field>ของฉันถึงไม่ยิง ทั้งๆ ที่เห็น string อยู่ใน log ชัดๆ?"
…คุณไม่ได้อยู่คนเดียว นี่คือคำถามที่คนส่วนใหญ่เจอตอนเริ่มเขียน Wazuh rules บทความนี้จะตอบทุกข้อ ทีละขั้น พร้อม diagram ทุกช่วง
1. ภาพรวม: Wazuh ประมวลผล Log อย่างไร
ก่อนที่ rule จะถูกประเมินแม้แต่ข้อเดียว Wazuh จะส่ง log ที่เข้ามาทุกรายการผ่าน pipeline สองขั้นตอน:
flowchart LR
A(["📄 Raw Log"]) --> B["Decoder Stage\nextract named fields"]
B --> C["Rules Engine\nmatch conditions"]
C --> D(["🚨 Alert or No Alert"])
style A fill:#1a1f2e,stroke:#5b8fff,color:#c8cdd8
style B fill:#1a2e1f,stroke:#00e5a0,color:#c8cdd8
style C fill:#2a1f10,stroke:#ff6b35,color:#c8cdd8
style D fill:#0d2e1a,stroke:#00e5a0,color:#00e5a0
ขั้นที่ 1 — Decoder: รับ raw log string และดึง field ที่มีชื่อออกมาเป็นโครงสร้าง ขั้นตอนนี้ไม่บังคับ — ถ้าไม่มี decoder ตรงกับ log นั้น log จะผ่านไปเป็น plain string ตามเดิม
ขั้นที่ 2 — Rules Engine: ประเมิน log (และ field ที่ decode แล้ว) กับ rules ของคุณ ขั้นตอนนี้ทำงานเสมอ ไม่ว่าจะมี decoder หรือไม่
สิ่งสำคัญที่ต้องจำ: rules engine จะเห็นอะไรนั้น ขึ้นอยู่กับว่า decoder ทำงานก่อนหรือเปล่า
2. "Field" ใน Wazuh คืออะไร?
field คือข้อมูลที่มีชื่อ ซึ่งถูกดึงออกจาก raw log โดย decoder
ลองดู raw SSH log นี้:
Jan 10 12:00:00 webserver sshd[1234]: Failed password for root from 203.0.113.5 port 22
Wazuh มี SSH decoder ในตัวที่อ่านบรรทัดนั้นและดึงข้อมูลออกมา:
srcip = 203.0.113.5
user = root
action = Failed password
ข้อมูลเหล่านี้กลายเป็น named fields ที่ rules สามารถ match ได้อย่างแม่นยำ แทนที่จะต้องสแกน raw string ทั้งบรรทัด
ถ้าไม่มี decoder, rules engine จะเห็นแค่ raw log text เท่านั้น แต่ถ้ามี decoder, มันจะเห็นทั้ง raw text และ field ที่ดึงออกมาด้วย
3. Rules และ Decoders เชื่อมกันอย่างไร
นี่คือจุดที่คนส่วนใหญ่สับสน มี rule tags หลายตัว และแต่ละตัวทำงานต่างกันมากขึ้นอยู่กับว่า decoder ทำงานหรือไม่:
| Rule Tag | ต้องการ Decoder? | จับ match อะไร |
|---|---|---|
<match> |
❌ ไม่ต้อง | ค้นหา substring ใน raw log line |
<field name="x"> |
✅ ต้อง | ค่าของ field ที่ decoder ดึงออกมา |
<decoded_as> |
✅ ต้อง | ตรวจว่า decoder ที่ระบุประมวลผล log นี้หรือไม่ |
<if_sid> |
❌ ไม่ต้อง | ตรวจว่า parent rule เคย fire ก่อนหน้าหรือไม่ (chaining) |
<same_field> |
✅ ต้อง | เชื่อม field ระหว่างหลาย event |
<list field="x"> |
✅ ต้อง | ค้นหาใน CDB / threat-intel list |
flowchart TD
A(["Raw Log"]) --> B{"Did a decoder\nrun on this log?"}
B -- "No" --> C["Only raw string\navailable to rules"]
B -- "Yes" --> D["Named fields\navailable to rules"]
C --> E["match ✅\nif_sid ✅\nfield ❌\ndecoded_as ❌"]
D --> F["match ✅\nif_sid ✅\nfield ✅\ndecoded_as ✅"]
style A fill:#1a1f2e,stroke:#5b8fff,color:#c8cdd8
style B fill:#2a1f10,stroke:#ff6b35,color:#ff6b35
style C fill:#2e0d0d,stroke:#ff4444,color:#c8cdd8
style D fill:#1a2e1f,stroke:#00e5a0,color:#c8cdd8
style E fill:#2e0d0d,stroke:#ff4444,color:#c8cdd8
style F fill:#0d2e1a,stroke:#00e5a0,color:#c8cdd8
<match> ทำงานได้เสมอเพราะเป็นแค่การค้นหา substring ใน raw log — ไม่สนใจว่า decoder ทำงานหรือเปล่า <field> จะทำงานได้ก็ต่อเมื่อ decoder ดึง field นั้นออกมาแล้วเท่านั้น
4. โครงสร้าง Wazuh Decoder: name, prematch, regex, order
มาสร้าง decoder ตั้งแต่ต้นและอธิบายทุก tag สมมติว่าแอปของคุณเขียน log แบบนี้:
2024-01-10 12:00:00 app=myapp action=login user=alice srcip=203.0.113.5 status=failed
นี่คือ decoder ที่ดึง field ที่ต้องการ:
<decoder name="myapp">
<prematch>app=myapp</prematch>
<regex>action=(\w+) user=(\w+) srcip=(\d+\.\d+\.\d+\.\d+) status=(\w+)</regex>
<order>action, user, srcip, status</order>
</decoder>
flowchart LR
A(["Raw Log\napp=myapp action=login user=alice ..."])
A --> B{"prematch\napp=myapp found?"}
B -- "No" --> C(["Skip this decoder"])
B -- "Yes" --> D["Run regex\nextract capture groups"]
D --> E["Map via order\ngroup 1 to action\ngroup 2 to user\ngroup 3 to srcip\ngroup 4 to status"]
E --> F(["Fields ready\naction=login\nuser=alice\nsrcip=203.0.113.5\nstatus=failed"])
style A fill:#1a1f2e,stroke:#5b8fff,color:#c8cdd8
style B fill:#2a1f10,stroke:#ff6b35,color:#ff6b35
style C fill:#2e0d0d,stroke:#ff4444,color:#888
style D fill:#1a2e1f,stroke:#00e5a0,color:#c8cdd8
style E fill:#1a2e1f,stroke:#00e5a0,color:#c8cdd8
style F fill:#0d2e1a,stroke:#00e5a0,color:#00e5a0
name="myapp"
ชื่อ label ของ decoder นี้ Rules สามารถอ้างอิงได้ด้วย <decoded_as>myapp</decoded_as> เพื่อให้ fire เฉพาะ log ที่ decoder นี้ประมวลผลแล้ว
<prematch> — ตัวกรองด่วนก่อน regex
ก่อนรัน regex ที่หนัก Wazuh จะตรวจก่อนว่า: string นี้มีอยู่ใน log ไหม? ถ้าไม่มี decoder จะถูกข้ามทันที นี่คือ การ optimize ประสิทธิภาพ — regex นั้น cost สูง แต่ prematch cost ต่ำ ควรใส่ไว้เสมอ
Log: "2024-01-10 app=myapp action=login user=alice ..."
^^^^^^^^
prematch พบ "app=myapp" → ไปต่อที่ regex
Log: "Jan 10 kernel: eth0 link up"
ไม่พบ "app=myapp" → ข้าม decoder ทั้งหมด
<regex> — capture groups ดึงค่า
วงเล็บ () แต่ละคู่คือ capture group ค่าที่ regex จับได้ข้างในจะกลายเป็นค่าของ field
action=(\w+)
└──┘ group 1 — จับอักขระ word ตั้งแต่ 1 ตัวขึ้นไป
Input: action=login
Result: login → group 1
user=(\w+)
└──┘ group 2
Input: user=alice
Result: alice → group 2
srcip=(\d+\.\d+\.\d+\.\d+)
└─────────────────┘ group 3 — pattern IP address
Input: srcip=203.0.113.5
Result: 203.0.113.5 → group 3
status=(\w+)
└──┘ group 4
Input: status=failed
Result: failed → group 4
<order> — ตั้งชื่อ capture groups
<order>action, user, srcip, status</order>
นี่คือการ map: group 1 → action, group 2 → user, group 3 → srcip, group 4 → status
⚠️ กฎสำคัญ: จำนวนชื่อใน
<order>ต้อง ตรงกันพอดี กับจำนวน()groups ใน<regex>สี่ groups → สี่ชื่อ ถ้าไม่ตรง decoder จะ fail โดยไม่มีการแจ้งเตือน
5. ข้อผิดพลาดที่พบบ่อย: <prematch> ไม่ได้ดึง Field ออกมา
นี่คือความเข้าใจผิดที่พบบ่อยที่สุดในหมู่คนที่เพิ่งเริ่มใช้ Wazuh
Q: <prematch> ตรวจหา app=myapp — แปลว่า app กลายเป็น field ที่ใช้ใน rules ได้ไหม?
ไม่. <prematch> เป็นแค่ตัวกรอง มันตรวจว่า string มีอยู่ใน log หรือไม่ เพื่อตัดสินใจว่าจะทำงานต่อหรือหยุด มันไม่ดึงอะไรออกมาเลย
flowchart TD
A["prematch: app=myapp"] --> B["Filter only ❌\napp NOT a field\ncannot use in rules"]
C["regex: app=group1 user=group2\norder: app, user"] --> D["app = myapp ✅\nuser = alice ✅\nboth usable in rules"]
style A fill:#2a1f10,stroke:#ff6b35,color:#c8cdd8
style B fill:#2e0d0d,stroke:#ff4444,color:#c8cdd8
style C fill:#1a2e1f,stroke:#00e5a0,color:#c8cdd8
style D fill:#0d2e1a,stroke:#00e5a0,color:#c8cdd8
Field จะมาจาก <regex> capture groups ที่ map ผ่าน <order> เท่านั้น ถ้าอยากให้ app เป็น field ที่ใช้งานได้ ต้องจับมันใน regex:
<!-- app ไม่ใช่ field — ใช้แค่เป็น pre-filter -->
<prematch>app=myapp</prematch>
<regex>action=(\w+) user=(\w+)</regex>
<order>action, user</order>
<!-- app เป็น field — จับใน regex แล้ว -->
<prematch>app=</prematch>
<regex>app=(\w+) action=(\w+) user=(\w+)</regex>
<order>app, action, user</order>
6. Flow ทั้งหมด: Raw Log → Decoder → Rule Chain → Alert
มาติดตามตัวอย่างที่เป็นจริงตั้งแต่ต้นจนจบ ผู้ใช้ login ผิดสามครั้ง — เราต้องการ detect สิ่งนี้ด้วย rule chain
Raw log:
2024-01-10 12:00:00 app=myapp action=login user=alice srcip=203.0.113.5 status=failed
flowchart TD
A(["Raw Log - app=myapp action=login user=alice status=failed"])
A --> B{"prematch - app=myapp found?"}
B -- "No" --> C(["No decoder runs - log stays as raw string"])
B -- "Yes" --> D["Regex extracts: action=login, user=alice, srcip=203.0.113.5, status=failed"]
C --> F
D --> F
F(["Rules Engine"])
F --> G
G{"Rule 1000 - match: app=myapp"}
G -- "string not found" --> Z(["No Alert"])
G -- "string found" --> H
H{"Rule 1001 - if_sid: 1000 - field: status=failed"}
H -- "field missing - no decoder ran" --> Z
H -- "field exists" --> I
I{"Rule 1002 - if_sid: 1001 - same_field: user - frequency 3 in 60s"}
I -- "not yet 3 times" --> Z
I -- "3 failures same user" --> J
J(["ALERT level 10 - Brute force: alice failed 3 times"])
style A fill:#1a1f2e,stroke:#5b8fff,color:#c8cdd8
style B fill:#2a1f10,stroke:#ff6b35,color:#ff6b35
style C fill:#1a1f2e,stroke:#444,color:#888
style D fill:#1a2e1f,stroke:#00e5a0,color:#c8cdd8
style F fill:#1a1f2e,stroke:#5b8fff,color:#c8cdd8
style G fill:#2a1f10,stroke:#ff6b35,color:#c8cdd8
style H fill:#2a1f10,stroke:#ff6b35,color:#c8cdd8
style I fill:#2a1f10,stroke:#ff6b35,color:#c8cdd8
style J fill:#0d2e1a,stroke:#00e5a0,color:#00e5a0
style Z fill:#2e0d0d,stroke:#ff4444,color:#ff4444
สังเกตที่ Rule 1001: ถ้าไม่มี decoder ทำงาน field status จะไม่ถูกดึงออกมา การตรวจ <field name="status"> จะ fail อย่างเงียบๆ — แม้ว่า raw log จะมี status=failed อยู่ชัดๆ นี่คือสาเหตุที่พบบ่อยที่สุดที่ทำให้ rules ดูเหมือนไม่ทำงาน
7. จะเกิดอะไรขึ้นถ้าไม่มี Decoder?
Rules ของคุณจะยังทำงานได้บางส่วน — แต่เฉพาะ tag ที่ไม่ต้องการ field ที่ดึงออกมาเท่านั้น
| Rule Tag | ไม่มี Decoder | เหตุผล |
|---|---|---|
<match>app=myapp</match> |
✅ ทำงานได้ | ค้นหา substring ใน raw string ไม่ต้องการ field |
<if_sid>1000</if_sid> |
✅ ทำงานได้ | Rule chaining ไม่ต้องการ field |
<field name="status">failed</field> |
❌ Fail เงียบๆ | Field status ไม่ถูกดึงออกมา |
<same_field>user</same_field> |
❌ Fail เงียบๆ | Field user ไม่ถูกดึงออกมา |
<list field="srcip">blocklist</list> |
❌ Fail เงียบๆ | Field srcip ไม่ถูกดึงออกมา |
flowchart LR
A(["No Decoder"]) --> B["match\nraw string search"]
A --> C["if_sid\nrule chaining"]
A --> D["field\nextracted field"]
A --> E["same_field\nfield correlation"]
B --> F(["✅ Always works"])
C --> G(["✅ Always works"])
D --> H(["❌ Always fails"])
E --> I(["❌ Always fails"])
style F fill:#0d2e1a,stroke:#00e5a0,color:#00e5a0
style G fill:#0d2e1a,stroke:#00e5a0,color:#00e5a0
style H fill:#2e0d0d,stroke:#ff4444,color:#ff4444
style I fill:#2e0d0d,stroke:#ff4444,color:#ff4444
⚠️ Wazuh ไม่แจ้งเตือน เมื่อ
<field>fail เพราะไม่มี decoder ทำงาน มันแค่ไม่ match เฉยๆ นี่คือเหตุผลที่ rule ที่ดูถูกต้องอาจไม่ทำงานอย่างเงียบๆ
8. เมื่อไหรต้องใช้ Wazuh Decoder?
ใช้ decision tree นี้ทุกครั้งที่เขียน rule ใหม่:
flowchart TD
Q(["What does your rule need to do?"])
Q --> A["Detect that a\nstring exists in the log"]
Q --> B["Match a specific\nfield value precisely"]
Q --> C["Correlate events\nacross multiple logs"]
Q --> D["Look up a value\nin a threat-intel list"]
Q --> E["Parse a structured format\nFortiGate or JSON or CEF"]
A --> A1(["❌ No decoder needed\nuse match"])
B --> B1(["✅ Decoder needed\nuse field"])
C --> C1(["✅ Decoder needed\nuse same_field\nor different_field"])
D --> D1(["✅ Decoder needed\nuse list field"])
E --> E1(["✅ Decoder needed\nuse decoded_as"])
style A1 fill:#0d2e1a,stroke:#00e5a0,color:#c8cdd8
style B1 fill:#2e0d0d,stroke:#ff4444,color:#c8cdd8
style C1 fill:#2e0d0d,stroke:#ff4444,color:#c8cdd8
style D1 fill:#2e0d0d,stroke:#ff4444,color:#c8cdd8
style E1 fill:#2e0d0d,stroke:#ff4444,color:#c8cdd8
ตัวอย่างจริง:
| สิ่งที่ต้องการ detect | ต้องการ decoder? |
|---|---|
Log line มีคำว่า error |
❌ ไม่ต้อง — ใช้ <match>error</match> |
| SSH login ผิดจาก IP range ที่ระบุ | ✅ ต้อง — ต้องการ field srcip |
| Username เดิม login ผิดจาก 2 IP ต่างกัน | ✅ ต้อง — ต้องการ field user และ srcip |
| Source IP ตรงกับ IP อันตรายใน list | ✅ ต้อง — ต้องการ field srcip สำหรับ <list> |
| FortiGate firewall บล็อก connection | ✅ ต้อง — ต้องการ decoder สำหรับ format log FortiGate |
| Windows EventID 4625 (login ผิด) | ❌ ไม่ต้อง — Wazuh มี decoder built-in จัดการอยู่แล้ว |
9. ลำดับความสำคัญ Decoder: เมื่อ Built-in Decoders เข้ามาแทนที่
Wazuh มี built-in decoders สำหรับ log source ทั่วไป — SSH, Windows, FortiGate, Apache และอื่นๆ decoder เหล่านี้ทำงานก่อน custom decoders ของคุณเสมอ
เรื่องนี้สำคัญมากเมื่อคุณเขียน custom rule สำหรับ log source ที่ Wazuh รู้จักอยู่แล้ว:
flowchart TD
A(["Log from a known source\ne.g. FortiGate with date= logid="])
A --> B{"Does a built-in\ndecoder match?"}
B -- "Yes" --> C["Built-in decoder fires\ne.g. fortigate-firewall-v6"]
B -- "No" --> D["Custom decoder checked"]
C --> E{"Does your custom rule\nchain off the right parent?"}
E -- "chains off built-in group\nif_group: fortigate" --> F(["✅ Rule fires correctly"])
E -- "chains off custom rule\nif_sid: your-base-rule" --> G(["❌ Parent never fired\nrule never matches"])
D --> H(["Custom decoder fires\nnormal flow"])
style A fill:#1a1f2e,stroke:#5b8fff,color:#c8cdd8
style B fill:#2a1f10,stroke:#ff6b35,color:#ff6b35
style C fill:#1a2e1f,stroke:#00e5a0,color:#c8cdd8
style F fill:#0d2e1a,stroke:#00e5a0,color:#00e5a0
style G fill:#2e0d0d,stroke:#ff4444,color:#ff4444
style H fill:#1a2e1f,stroke:#00e5a0,color:#c8cdd8
วิธีแก้คือใช้ <if_group> เพื่อ chain ต่อจาก rule group ของ built-in decoder แทนที่จะเป็น base rule ของคุณเอง:
<!-- ❌ ผิด — base rule ของคุณไม่ fire สำหรับ log FortiGate -->
<rule id="200">
<if_sid>100</if_sid> <!-- custom base rule ของคุณ -->
<field name="action">deny</field>
</rule>
<!-- ✅ ถูก — chain ต่อจาก built-in fortigate group -->
<rule id="200">
<if_group>fortigate</if_group>
<field name="action">deny</field>
</rule>
10. Cheatsheet: สรุป Decoder & Rule Tags ทั้งหมด
| Tag | ขั้นตอน | ดึง Field ได้? | ต้องการ Decoder? | ใช้สำหรับ |
|---|---|---|---|---|
<prematch> |
Decoder | ❌ ไม่ | — | ตัวกรองด่วนก่อน regex |
<regex> + <order> |
Decoder | ✅ ได้ | — | ดึง field ที่มีชื่อจาก log |
<match> |
Rule | — | ❌ ไม่ | จับ substring ใน raw log |
<field> |
Rule | — | ✅ ต้อง | Match ค่า field ที่ดึงออกมาแล้ว |
<decoded_as> |
Rule | — | ✅ ต้อง | ให้ match เฉพาะเมื่อ decoder ที่ระบุทำงาน |
<if_sid> |
Rule | — | ❌ ไม่ | Chain ต่อจาก parent rule ด้วย ID |
<if_group> |
Rule | — | ❌ ไม่ | Chain ต่อจาก rule group (เช่น built-in fortigate) |
<same_field> |
Rule | — | ✅ ต้อง | Correlate event ซ้ำๆ ที่มี field เดียวกัน |
<different_field> |
Rule | — | ✅ ต้อง | ตรวจ user เดิม แต่ IP ต่างกัน (impossible travel) |
<list field> |
Rule | — | ✅ ต้อง | Threat-intel CDB lookup จาก field ที่ decode แล้ว |
สรุป
Pipeline ของ Wazuh นั้นง่ายมากเมื่อเข้าใจโมเดลสองขั้นตอน:
- Decoders ทำงานก่อน — แปลง raw log text เป็น named fields โดยใช้
<prematch>(กรอง),<regex>(ดึง) และ<order>(ตั้งชื่อ) มีเพียง capture groups ใน<regex>เท่านั้นที่กลายเป็น field ส่วน<prematch>ไม่ดึงอะไรเลย - Rules ทำงานหลัง —
<match>ทำงานกับ raw text โดยไม่ต้องการ decoder;<field>,<same_field>และ<list>จะทำงานได้ก็ต่อเมื่อ decoder ดึง field เหล่านั้นออกมาแล้วเท่านั้น
เมื่อ rule ไม่ทำงานอย่างเงียบๆ สาเหตุมักเป็นหนึ่งในนี้:
- คุณใช้
<field>แต่ decoder ไม่ได้ดึง field นั้นออกมา - Built-in decoder ทำงานก่อน custom ของคุณ ทำให้
<if_sid>chain พัง - จำนวนชื่อใน
<order>ไม่ตรงกับจำนวน groups ใน<regex>
เริ่มต้นด้วย rule ที่ใช้แค่ <match> เพื่อยืนยันว่า log ถึง Wazuh และ base rules ทำงาน แล้วค่อยเพิ่ม decoder และ <field> rules เมื่อต้องการ match ที่แม่นยำระดับ field
คำถามที่พบบ่อย (FAQ)
Q: <prematch> สร้าง field ที่ใช้ใน rules ได้ไหม?
ไม่. <prematch> เป็นแค่ตัวกรอง performance — ตรวจว่า string มีอยู่ใน log ก่อนรัน regex ไม่ดึงอะไรออกมา Field จะถูกสร้างโดย capture groups ของ <regex> ที่ map ด้วย <order> เท่านั้น
Q: Wazuh rule ทำงานได้ไหมถ้าไม่มี decoder?
ได้ ตราบเท่าที่ใช้แค่ <match> หรือ <if_sid> สอง tag นี้ทำงานกับ raw log string และไม่ต้องการ field ที่ decode แล้ว แต่ tag อย่าง <field>, <decoded_as>, <same_field> และ <list field> จะ fail เงียบๆ โดยไม่มีการแจ้งเตือน
Q: <if_sid> ใช้ทำอะไรใน Wazuh?
<if_sid> เชื่อม child rule เข้ากับ parent rule ด้วย rule ID child จะ fire ก็ต่อเมื่อ parent match ใน event เดียวกันแล้วเท่านั้น นี่คือวิธีที่ Wazuh สร้าง cascading detection — base rule match log source แล้ว child rules ตรวจ condition ที่เฉพาะเจาะจงยิ่งขึ้น
Q: <match> กับ <field> ใน Wazuh rule ต่างกันอย่างไร?
<match> ค้นหา substring ใน raw log line ทั้งบรรทัด — ไม่ต้องการ decoder ส่วน <field name="x"> match กับ field ที่มีชื่อเฉพาะซึ่ง decoder ต้องดึงออกมาก่อน ใช้ <match> สำหรับ detection แบบกว้าง และใช้ <field> เมื่อต้องการความแม่นยำกับค่าที่ระบุ
Q: Wazuh decoder มี capture groups ได้กี่ตัว?
ไม่มีเอกสารระบุขีดจำกัดที่ชัดเจน แต่จำนวน () groups ใน <regex> ต้องตรงกับจำนวนชื่อที่คั่นด้วย comma ใน <order> ถ้าไม่ตรง decoder จะ fail เงียบๆ โดยไม่มีข้อความ error
Q: ทำไม rule ถึงไม่ fire ทั้งๆ ที่ string อยู่ใน log?
สาเหตุที่เป็นไปได้มากที่สุด: (1) คุณใช้ <field> แต่ decoder ไม่ได้ดึง field นั้นออกมา (2) built-in decoder ทำงานก่อนและทำให้ <if_sid> chain พัง หรือ (3) string ใน <prematch> ไม่ปรากฏใน log ใช้ wazuh-logtest เพื่อ trace ว่า decoder และ rule ทำงานยังไงกับ log บรรทัดนั้น
Q: wazuh-logtest คืออะไร และใช้ยังไง?
wazuh-logtest เป็นเครื่องมือ built-in ของ Wazuh ที่ให้คุณวาง raw log line แล้วดูได้ทันทีว่า decoder ไหน match, field อะไรถูกดึงออกมา และ rule ไหน fire นี่คือวิธีที่เร็วที่สุดในการ debug decoder หรือ rule ที่ไม่ทำงานตามที่คาด รันได้จาก Wazuh manager CLI หรือจาก Wazuh web UI ที่ Tools → Logtest
ส่วนหนึ่งของซีรีส์ Detection Engineering พบข้อผิดพลาดหรืออยากแนะนำตัวอย่างเพิ่มเติม? เปิด issue หรือติดต่อมาได้เลย
Get in Touch with us
Related Posts
- การสร้างระบบติดตาม OEE แบบเรียลไทม์สำหรับโรงงานอุตสาหกรรม
- ความเชื่อเรื่อง Enterprise Software ราคาเป็นล้านกำลังจะจบลง มื่อ Open‑Source + AI กำลังแทนที่ระบบองค์กรราคาแพง
- วิธี Cache ข้อมูล Ecommerce โดยไม่แสดงราคาหรือสต็อกที่ล้าสมัย
- การนำ AI เข้าสู่ระบบ Legacy: บูรณาการ ERP, SCADA และระบบ On-Premise ด้วย Machine Learning
- ราคาของความฉลาด: AI ต้องใช้เงินเท่าไหร่กันแน่
- ทำไม RAG App ของคุณถึงพังใน Production (และวิธีแก้ไข)
- AI-Assisted Programming ในยุค AI: บทเรียนจาก *The Elements of Style* ที่ช่วยให้คุณเขียนโค้ดได้ดีกว่าด้วย Copilot
- มายาคติ AI แทนที่มนุษย์: ทำไมองค์กรยังต้องการวิศวกรและระบบซอฟต์แวร์จริงในปี 2026
- NSM vs AV vs IPS vs IDS vs EDR: ระบบความปลอดภัยของคุณขาดอะไรอยู่?
- ระบบ Network Security Monitoring (NSM) ผสานพลัง AI
- วิธีสร้างระบบ Enterprise ด้วย Open-Source + AI
- AI จะมาแทนที่บริษัทพัฒนาซอฟต์แวร์ในปี 2026 หรือไม่? ความจริงที่ผู้บริหารองค์กรต้องรู้
- วิธีสร้าง Enterprise System ด้วย Open-Source + AI (คู่มือเชิงปฏิบัติ ปี 2026)
- การพัฒนาซอฟต์แวร์ด้วย AI — สร้างเพื่อธุรกิจ ไม่ใช่แค่เขียนโค้ด
- Agentic Commerce: อนาคตของระบบการสั่งซื้ออัตโนมัติ (คู่มือฉบับสมบูรณ์ ปี 2026)
- วิธีสร้าง Automated Decision Logic ใน SOC ยุคใหม่ (ด้วย Shuffle + SOC Integrator)
- ทำไมเราจึงออกแบบ SOC Integrator แทนการเชื่อมต่อเครื่องมือแบบตรง ๆ (Tool-to-Tool)
- การพัฒนาระบบสถานีชาร์จ EV ด้วย OCPP 1.6 คู่มือสาธิตการใช้งานจริง: Dashboard, API และสถานีชาร์จ EV
- การเปลี่ยนแปลงทักษะของนักพัฒนาซอฟต์แวร์ (2026)
- Retro Tech Revival: จากความคลาสสิกสู่ไอเดียผลิตภัณฑ์ที่สร้างได้จริง













