iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
Security

企業管理自動化與執行框架-以SOC運作為實例系列 第 15 篇

SOC團隊版Node說明--防禦決策(DecisionWriter)

  • 分享至 

  • xImage
  •  
顯示名稱 防禦決策
node_type DecisionWriter
一句話用途 把「封鎖/解除封鎖/放行/升級/觀察」這樣的處置決定寫成一筆記錄, 讓已配對的外部防禦端依設定的執行點各自拉走實施;節點本身不連任何防火牆。
會讓流程等待 否。同步寫入後立即回報成功或失敗;失敗時佇列會依系統共用機制自動重試 (最多 3 次),重試期間節點停在原地,不會往任何出線推進,也不會自動結束流程。
出線 不挑邊。依系統共用規則,成功時所有出線同時往下走;通常只接一條。
可用範圍 所有企業(非受限節點,不需要企業授權)

1. 這個節點做什麼

防禦決策(DecisionWriter)把「這個目標現在該不該被擋」的一個處置決定,寫成 od_defense_decisions 表的一筆記錄。這是平台端通用、廠牌中性的防禦決策廣播機制: 不管企業實際部署的是哪一種防火牆、WAF 或 CDN,只要有對應的執行端程式依約定欄位拉取這張表, 就能把同一份決策套用到不同設備上。節點本身完全不會連線任何防火牆——它只負責 「寫一筆決策」,真正落地生效與否,要看有沒有已配對的防禦節點在拉取、或平台是否把它渲染進 EDL 黑名單(見「4. 出線行為」與「6. 注意事項」)。

適用情境:需要把一個判斷結果——通常來自簽核節點的人工決定,或分支節點的自動判斷——轉成 「要不要封鎖/放行某個來源」的正式紀錄時使用。它也常被拿來記錄「放行」這種消極決定, 因為之後同一個目標再次進案時,看得到前次已經判斷過。

不適合的情境:如果目的只是「讓某些人知道發生了這件事」,不涉及實際的封鎖/放行動作, 應改用緊急廣播(AlertBroadcast)、Email 或 Telegram 節點——這個節點寫的是給 防禦設備看的資料,不是給人看的通知(雖然實務上常常兩者搭配,見「5. 常見設計方式」)。 它也不適合拿來記「這個案件最終結論是什麼」這種案件層級的狀態:它寫的是「目標 X 現在該不該被擋」 這種以目標為單位的獨立紀錄,同一個目標的多筆決策彼此會互相取代,不是逐案累積的日誌。

2. 設定欄位

2.1 基本設定

面板欄位 config key 必填 預設值 說明
動作 action 必填 面板預設「封鎖 (block)」 五選一:block/unblock/allow/ escalate/observe。留空/非法值會在寫入時被拒絕 (handler 只檢查非空字串,合法值集合由底層的決策服務再驗證一次)。
目標型別 target_type 必填 面板預設 ip 九選一:ip/ipv6/cidr(網段)/ domain/url/asn/country/ user_agent/jwt_sub。
目標值 target_value 必填 — 支援變數替換,通常填 ${f.actor_ip} 之類引用表單欄位的樣板。 替換後若為空字串,節點會直接失敗(見「6. 注意事項」第一條)。

2.2 執行點

面板欄位 config key 必填 預設值 說明
執行點(nftables/edl/crowdsec/cloudflare 四個勾選框+「其他執行點」自由輸入) enforcement_points 選填 面板初次開啟時預設勾選 nftables 與 edl;未設定時 handler 端視為空陣列 決定這筆決策會被哪些外部執行端拉走,純粹是篩選用的標籤,本身不會去操作任何防火牆。 接受陣列或逗號分隔字串。action=allow 時只有 edl 真正支援, 其餘固定執行點會被系統自動濾掉(詳見「6. 注意事項」)。cloudflare 目前尚未有 任何執行端實作,勾選也不會產生效果。

2.3 嚴重度與存續時間

面板欄位 config key 必填 預設值 說明
嚴重度 severity 選填 (未指定) 五選一:info/low/medium/high/ critical。純分級標記,不影響是否寫入成功。
TTL 秒 ttl_seconds 選填 留空=永久 留空或填 0 都代表永久,直到人工撤銷或另一筆決策覆蓋。 填其他值必須是可解析成正整數的數字,否則節點失敗。用來計算 expires_at。

2.4 決策來源與理由

面板欄位 config key 必填 預設值 說明
決策來源 decided_via 選填 空白=自動推斷 三選一:human(人工決策)/auto(自動決策)/ ai(AI 判定)。留空時走自動推斷,但實測這個推斷目前一律得到 auto(見「6. 注意事項」第二條)——只要這個節點在流程裡是由人工 簽核觸發的,一律明寫 human,不要依賴自動推斷。
理由範本 reason_template 選填 留空則 reason 欄位為 NULL 支援變數替換,寫入決策紀錄的 reason 欄位,方便事後追查這筆決策為何而寫。

2.5 封鎖保護清單覆寫

以下兩個欄位只在動作為「封鎖」且目標型別是 ip/ipv6/cidr 時才會在面板顯示、 也只有這個組合才會經過封鎖保護清單檢查(見「6. 注意事項」第三條的完整說明)。

面板欄位 config key 必填 預設值 說明
允許封鎖受保護目標(覆寫保護清單) allow_protected_target 選填 false 勾選後,即使命中保護清單仍會寫入決策,並在決策紀錄的 decision_metadata.protected_override 留下命中來源、網段等覆寫痕跡供稽核。
命中保護清單時 on_protected 選填 error 兩選一:error(預設,節點回報錯誤,流程停在此等人處理)/ skip(略過寫入、視為成功、流程正常往下走,不寫入任何決策)。 除 skip 以外的任何值(含空白或誤填)一律當作 error 處理。

3. 可用的變數與輸出

會做變數替換的只有目標值與理由範本兩個欄位,語法與所有節點共用: ${f.欄位}(表單欄位)、${fi.applicant|serial|...}(表單資訊)、 ${v.變數}(流程變數)、${wi.code|exec_code|name|status|depth}(流程實例, 僅此五個)、${n.name|id|type}(節點上下文)、${t.now|date|time}(時間)。 其餘欄位——動作、目標型別、執行點、嚴重度、TTL、決策來源、允許覆寫、命中保護清單時如何處理—— 全部是設定值,一律不會做變數替換,只能在面板上手動選擇或輸入固定值。

這個節點不會寫入任何流程變數(不呼叫設定流程變數的 API)。執行完成後能查到結果的 只有兩個地方:

  • 流程管理頁的執行紀錄(fw_node_execution_logs.log_data):含 decision_secure_code、action、target_type、 target_value、enforcement_points、ttl_seconds 等欄位。
  • od_defense_decisions 資料表本身:這是唯一能拿到完整決策紀錄(含 secure_code、目前狀態 status)的地方。若後續節點需要引用「這筆決策的 secure_code」,目前沒有現成的流程變數可讀,需要另外設計查表邏輯。

4. 出線行為

節點本身完全不挑邊,只回報「成功」或「失敗」兩種結果,不會使用 selected_edges 或 skip_advance 之類的機制。因此依系統共用規則,只要節點成功,接在它後面的所有出線都會 同時被走(設計上通常只接一條)。

成功:正常寫入
建立一筆 status='pending' 的決策紀錄,往下走。

成功:命中保護清單但 on_protected=skip
不寫入任何決策,但節點視為成功,一樣往下走。這裡的「略過」跟 Branch/ParallelJoin 用的「成功但不推進任何出線」是兩回事: 這個節點的「略過」只是不寫決策,流程仍然照常往下走同一組出線。

失敗
以下任一情況都會讓節點回報失敗:action/target_type 為空;target_value 變數替換後為空字串;ttl_seconds 給了但無法解析成正整數; 命中封鎖保護清單且 on_protected 不是 skip;或底層驗證失敗(action/ target_type 不在合法值清單、target_value 超過 500 字、或走保護清單檢查時 target_value 不是合法的 IP/CIDR)。節點失敗時佇列會依系統共用的重試機制自動重試 (最多 3 次相同失敗才整個標記為執行失敗),重試期間不會往任何出線推進,流程實例維持在執行中, 不會自動判定失敗或結束——等同卡在那裡,需要人工介入。

5. 常見設計方式

5.1 人工簽核後才寫入決策(取自 SOC 團隊版)

https://ithelp.ithome.com.tw/upload/images/20260929/20184261y3a5kmpOT6.png

5.2 自動封鎖前用分支擋掉沒有目標值的案件(取自 node展覽館示範)

https://ithelp.ithome.com.tw/upload/images/20260929/201842619fnIMJkW6r.png

6. 注意事項

目標值替換後為空,節點會失敗並可能讓流程卡住
症狀:流程實例一直停在執行中,流程管理頁看得到某個防禦決策節點反覆重試最終變成 FAILED,但整個流程沒有結束、也沒有任何錯誤通知使用者。
原因:target_value 通常引用表單欄位(如 ${f.actor_ip}), 一旦該欄位留空或這個節點跟不含該欄位的分支並行執行,變數替換後就是空字串,節點直接回報失敗; 失敗只會觸發系統共用的自動重試(最多 3 次),不會自動改走別的路徑。
正確做法:在這個節點之前放一個分支,先判斷目標欄位是否為空,有值才進入這個節點, 留空則改走另一條安全路徑(見「5.2 常見設計方式」)。

不明寫「決策來源」,實測一律得到 auto
症狀:決策歷史清單裡,明明是資安人員簽核後才觸發的封鎖,「決策來源」欄卻顯示 auto(自動決策),不是 human(人工決策)。
原因:留空時節點會嘗試自動推斷——原本的邏輯是檢查「流程實例上一個完成的節點是不是簽核」, 是的話才判定為 human。但目前用來做這個比對的資料欄位在流程實例的資料模型裡並不存在, 所以這個判斷永遠不成立,自動推斷目前一律得到 auto——不只在並行分支下 不可靠,任何情況下都不可靠。
正確做法:只要這個節點是接在人工簽核之後,一律在「決策來源」欄位明寫 human;自動判斷觸發的節點則明寫 auto。不要留空賭自動推斷。

命中封鎖保護清單,決策被拒絕寫入
症狀:節點回報失敗,訊息提到「命中封鎖保護清單」,明明只是想封鎖一個位址。
原因:只要動作是「封鎖」、目標型別是 ip/ipv6/cidr,寫入前一定會先比對保護清單。 保護清單分三層:內建(16 條常見保留網段,如私有網段、回送位址、link-local、CGNAT、群播與保留位址, 含對應的 IPv6 範圍)、平台設定(系統管理者維護)、企業自訂(在「開放防禦 → 封鎖保護清單」頁面維護)。 只要目標與保護網段有任何重疊就算命中,不是「完全落在裡面」才算——所以拿一個很大的 網段當目標,只要跟保護清單有一小段重疊,一樣會被擋下。
正確做法:如果真的需要封鎖落在保護範圍內的位址(常見情境是內部主機被入侵、需要隔離), 有兩個正當做法:①到「開放防禦 → 封鎖保護清單」頁面新增一筆豁免項目——豁免的判定比 命中嚴格,必須要封鎖的目標完全是豁免網段的子網路才會生效,豁免一台主機不會連帶讓整個 網段變成可封鎖;②在節點的「允許封鎖受保護目標」勾選覆寫,這種決策會在紀錄裡留下覆寫痕跡,事後查得到 是誰、繞過了哪一條保護。「命中保護清單時」欄位另外決定要停(預設,節點失敗、流程停在此等人處理)還是 略過(不寫決策但讓流程正常往下走,適合後面還接通知節點的設計)。

執行點只是篩選標籤,不會真的去設定防火牆
勾選 nftables/edl/crowdsec 只是讓已配對的外部執行端知道 「這筆決策跟我有關」,節點本身完全不會連線任何設備。cloudflare 目前沒有任何執行端支援, 勾了也不會有效果。action=allow 時,畫面上即使勾選了 nftables/ crowdsec,寫入時也會被系統自動過濾掉(這兩個執行端只認得封鎖與解除封鎖,收到放行類指令 會直接回報「不支援的動作」),全部被濾掉時會自動保留 edl。平台自己輸出的 「EDL 黑名單」有獨立判斷邏輯:只要是該企業所有仍在有效期內的封鎖決策,不論有沒有勾選 edl 這個執行點都會被收進清單;反過來,決策的執行點就算勾了 edl,如果對應的封鎖已經被更晚的一筆放行或解除封鎖決策覆蓋(依目標值比對), 一樣不會出現在清單裡。

TTL 到期不是「消失」,是排程另外補一筆解除決策
設定了 TTL 且已過期的封鎖決策,不會被直接刪除或原地改狀態就算了事:平台排程會掃到這些過期決策, 另外新建一筆「解除封鎖」的決策(狀態一樣是待執行),原決策狀態才改成「已過期」。這代表 TTL 到期後仍然需要有執行端把新建的「解除封鎖」決策拉走並實際執行,才會真的解除。人工在管理頁按「撤銷」 也是同樣的機制:新建一筆解除封鎖決策,原決策標成「已撤銷」,而不是直接刪除原紀錄。

7. 在 node展覽館 實際操作

對應「NT-23 DecisionWriter 示範」。流程:送出表單後先經過一個自簽的核准關卡(核准/駁回); 核准後由一個分支判斷表單裡「要阻擋的來源 IP」欄位是否留空——有值才會呼叫這個節點寫入封鎖決策 (severity=high,ttl_seconds=3600 即一小時後過期,decided_via 明寫 human,執行點勾了 nftables 與 edl),留空則改走另一條 只寫說明文字的路徑,兩種情況流程都會正常結束。阻擋目標一律落在 123.123.0.0/16 這個測試網段,不是任何真實或內網位址,也不在保護清單範圍內。

操作方式:到表單中心開啟「NT-23 DecisionWriter 示範表單」,直接送出(預設值已落在測試網段), 核准後回到「填寫表單」重新打開這張單,「處置結果」欄位會顯示這次到底寫了封鎖決策還是跳過了。 若想示範防呆路徑,送單前先把「要阻擋的來源 IP」欄位清空即可。

要看實際寫入的決策紀錄,可查詢 od_defense_decisions 表(依 reason 欄位是否含有示範標記篩選);若這筆決策仍在有效期內,下一次 EDL 渲染也會把它收進當期的封鎖清單。 若想示範「命中保護清單而被拒絕」的情境,示範腳本另外提供一段獨立驗證:在保護清單暫時新增一筆 限縮在測試網段內的自訂保護項目,直接呼叫節點底層真正呼叫的決策寫入函式,確認落在該保護網段內的 目標會被拒絕寫入、資料庫完全沒有新增任何決策,驗證完立刻刪除這筆暫時的保護清單項目——這與流程節點 呼叫的是同一支函式,驗證的是同一套判定邏輯。

8. 相關節點

  • 簽核(FormAdapter):最常見的觸發來源——由人在簽核關卡 選擇要封鎖還是放行,選項各自接一個防禦決策節點。
  • 分支(Branch):自動封鎖前用來擋掉目標值為空的案件,是這個節點 最重要的搭配。
  • 緊急廣播(AlertBroadcast):寫入決策之後常見緊接一則通報, 讓相關人員知道剛剛封鎖了什麼。
  • 寫入欄位(OpFieldWrite):這個節點不寫流程變數,需要把 處置結果留在表單上讓送單者看到時,改用這個節點把說明文字寫回表單欄位。

上一篇
SOC團隊版Node說明--分支(Branch)
下一篇
SOC團隊版Node說明--暫停(Delay)
系列文
企業管理自動化與執行框架-以SOC運作為實例 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言