在 Day22,我們使用 SIGTERM 成功終止 Kali Linux 中的測試程序。
Day23 則加入 Response Policy,透過程序白名單、PID、Start Time 與 Executable 等資訊,降低錯誤終止程序的風險。
不過,資安事件的回應方式不只有 Process Termination(程序終止)。
當系統發現可疑的網路連線時,也可能需要透過防火牆阻擋特定 IP,降低攻擊者持續通訊或傳輸資料的機會。
因此,Day24 我們開始實作 Network Blocking(網路阻斷)。
今天主要完成三件事情:
今天使用的是本機 Loopback 位址 127.0.0.2,目的是驗證防火牆阻斷技術,不會直接封鎖真實外部伺服器。
Network Blocking 是指透過防火牆規則,限制特定網路封包的傳送或接收。
例如,某台 Linux 主機上的程序持續連線到可疑的外部 IP。
資安人員可能希望阻止主機繼續與該 IP 通訊。
Linux 可以透過防火牆機制,根據以下條件判斷封包:
這次我們使用的動作是 DROP。
DROP 的意思是直接丟棄符合條件的封包,不讓封包繼續通過該規則。
nftables 是 Linux 的封包過濾與防火牆管理機制,能夠透過規則控制網路流量。
它主要包含幾個概念:
| 名詞 | 說明 |
|---|---|
| Table | 用來組織防火牆規則 |
| Chain | 放置規則並指定封包處理位置 |
| Rule | 實際的封包比對與處置條件 |
| Hook | 指定規則介入封包處理流程的位置 |
| Counter | 統計符合規則的封包數量與位元組 |
| Drop | 丟棄符合條件的封包 |
今天我們會建立獨立的 nftables Table,避免清除或覆蓋 Kali Linux 原本的防火牆規則。
首先進入專案:
cd ~/behaviorguard
我們建立:
nano test_day24_block_ip.sh
這次使用的測試 IP 是:
127.0.0.2
它屬於 IPv4 Loopback 範圍,封包會在本機網路堆疊中處理,不需要真正送到外部網路。
測試流程:
Ping 127.0.0.2
↓
確認原本可以連通
↓
建立 nftables DROP Rule
↓
再次 Ping
↓
確認封包遭到阻擋
↓
移除防火牆規則
↓
再次 Ping
↓
確認連線恢復
nft add table ip bg_day24
這行會建立名為 bg_day24 的 IPv4 防火牆表格。
接著建立 Chain:
nft add chain ip bg_day24 output \
'{ type filter hook output priority 0; policy accept; }'
其中:
hook output 代表這條 Chain 會處理本機產生、準備送出的封包。
policy accept 代表這條 Chain 的預設策略為允許,只有符合特定 DROP 規則的流量才會被丟棄。
接著加入封鎖規則:
nft add rule ip bg_day24 output \
ip daddr 127.0.0.2 counter drop
這行才是真正的封包阻斷規則。
各個部分的意義:
| 指令內容 | 用途 |
|---|---|
ip daddr |
比對目的 IPv4 位址 |
127.0.0.2 |
指定測試目標 |
counter |
記錄符合規則的封包數量 |
drop |
丟棄符合規則的封包 |
這條規則沒有指定 Port 或傳輸層協定,因此會對符合目的 IPv4 條件的流量進行 DROP,而不只是限制 ICMP。
不過,今天實際驗證的流量只有 ICMP Ping,尚未進行 TCP 或 UDP 的阻斷測試。
完成 Shell Script 後執行:
sudo bash test_day24_block_ip.sh
這次實際取得:
========== Day24 Block IP Test ==========
[TEST 1] Before blocking
[PASS] Target reachable.
[INFO] Firewall rule installed.
[TEST 2] After blocking
[PASS] Connection blocked.
代表封鎖前可以成功 Ping 到測試 IP,但加入防火牆規則後,Ping 無法成功。
接著查看 nftables 規則:
table ip bg_day24 {
chain output {
type filter hook output priority filter; policy accept;
ip daddr 127.0.0.2 counter packets 1 bytes 84 drop
}
}
這次最重要的資訊是:
counter packets 1 bytes 84 drop
它代表有一個封包符合規則,命中的封包大小總計 84 bytes,且該規則的處置動作為 DROP。
因此,我們不只是看到 Ping 失敗,也能從防火牆 Counter 確認封包確實命中阻斷規則。
最後測試解除封鎖:
[INFO] Test firewall rules removed.
[TEST 3] After restoring
[PASS] Connection restored.
[INFO] Day24 test completed.
這代表移除本次防火牆規則後,測試 IP 可以重新連通。
雖然第一個 Shell Script 已經成功阻斷封包,但它仍然是一支獨立測試程式。
因此,接下來我們將功能改寫成 Python,放入 BehaviorGuard 原本的 response/ 目錄。
新增檔案:
behaviorguard/
└── response/
├── engine.py
├── policy.py
├── network_blocker.py
├── auto_response.py
└── audit_logger.py
新增:
nano response/network_blocker.py
這個模組負責呼叫 nftables 指令。
核心程式如下:
import subprocess
import ipaddress
TABLE = "bg_day24"
TEST_IP = "127.0.0.2"
def run_nft(*args):
return subprocess.run(
["nft", *args],
capture_output=True,
text=True,
check=True,
timeout=5
)
這裡利用 Python 的 subprocess.run() 執行 Linux 指令。
其中:
check=True:執行失敗時產生例外。capture_output=True:取得指令輸出。timeout=5:限制指令等待時間。接著建立 IP 驗證功能:
def validate_target(ip, authorized):
if not authorized:
raise PermissionError("Authorization required")
parsed = ipaddress.ip_address(ip)
if str(parsed) != TEST_IP:
raise ValueError("Only 127.0.0.2 is allowed")
return str(parsed)
這次只允許 127.0.0.2 進入測試流程。
如果輸入其他 IP,就拒絕執行。
這是為了避免測試過程中誤封正常使用的 DNS、Gateway 或外部服務。
Network Blocker 分別提供:
block_ip(ip, authorized=False)
以及:
unblock_ip(ip, authorized=False)
前者負責建立 nftables 阻斷規則,後者負責移除本次建立的測試表格。
另外,也建立:
is_reachable(ip)
利用 Ping 檢查目標是否可以連通。
需要注意,Ping 失敗不一定代表防火牆成功封鎖,因此仍然需要搭配規則與 Counter 進行確認。
完成 network_blocker.py 後,我們修改原本的:
response/engine.py
新增:
def handle_network_response(ip, action, authorized=False):
這個函式會根據 Action 呼叫不同的處置功能。
核心邏輯如下:
if action == "BLOCK":
result = block_ip(ip, authorized=authorized)
elif action == "UNBLOCK":
result = unblock_ip(ip, authorized=authorized)
else:
print("[DENIED] Unsupported action")
return False
這樣 Network Blocking 就不再只是獨立的 Shell Script,而是正式成為 BehaviorGuard Response Engine 可以呼叫的功能。
目前 Response Engine 已經包含:
handle_alert():根據 Severity 產生 Dry Run 建議。terminate_test_process():受控程序終止。handle_network_response():受控 IP 封鎖與解除。這些功能都在同一個 Response 模組架構內,但正式即時監控流程還沒有直接呼叫真正的阻斷功能。
接著建立:
nano test_day24_network.py
測試流程包含:
執行:
sudo env PYTHONPATH=. python3 test_day24_network.py
實際測試結果:
========== Day24 Integration Test ==========
[TEST 1] Before blocking
[PASS] Target reachable.
[TEST 2] Block IP
========== BehaviorGuard Network Response ==========
Target IP : 127.0.0.2
Action : BLOCK
Mode : CONTROLLED TEST
[BLOCK] 127.0.0.2
Executed : True
====================================================
[PASS] Connection blocked.
之後再次查看 nftables:
table ip bg_day24 {
chain output {
type filter hook output priority filter; policy accept;
ip daddr 127.0.0.2 counter packets 1 bytes 84 drop
}
}
接著解除阻斷:
[TEST 3] Unblock IP
========== BehaviorGuard Network Response ==========
Target IP : 127.0.0.2
Action : UNBLOCK
Mode : CONTROLLED TEST
[UNBLOCK] 127.0.0.2
Executed : True
====================================================
[TEST 4] Verify restoration
[PASS] Connection restored.
[INFO] Day24 integration test completed.
這次確認 Python Response Engine 可以透過 Network Blocker 真正執行 nftables 操作,並完成封鎖與解除。
最後使用:
sudo nft list table ip bg_day24
顯示:
Error: No such file or directory
因為本次測試的防火牆表格已被刪除,所以這個結果符合預期。
完成 Python Network Blocking 後,我們再加入兩個功能:
response/auto_response.py
response/audit_logger.py
這個模組負責接收測試 Alert,檢查規則和目標是否符合條件,再呼叫 Response Engine。
例如:
PROCESS_RULE = "BG-TEST-PROC-001"
NETWORK_RULE = "BG-TEST-NET-001"
TEST_IP = "127.0.0.2"
這裡刻意使用測試專用的 Rule ID,避免直接將真實 Detection Rule 與阻斷操作連接。
例如:
def auto_block_network(alert):
rule = alert.get("rule", "UNKNOWN")
ip = alert.get("dst_ip")
if rule != NETWORK_RULE or ip != TEST_IP:
log_response(
rule,
"BLOCK",
ip,
"DENIED",
"Unapproved test target"
)
return False
如果 Rule ID 或 IP 不符合測試條件,就不允許執行封鎖。
通過檢查後,才呼叫:
handle_network_response(
ip,
"BLOCK",
authorized=True
)
這裡的 authorized=True 仍然只是測試程式內部的授權參數,不是真正的使用者權限驗證。
之前的 Alert Logger 主要記錄 Detection Alert。
但如果 Response Engine 真正執行過終止或封鎖,就還需要另外保存處置紀錄。
因此我們建立:
logs/responses.jsonl
並使用 log_response() 儲存:
record = {
"timestamp": datetime.now(
timezone.utc
).isoformat(),
"rule": rule,
"action": action,
"target": str(target),
"status": status,
"reason": reason
}
這樣日後就能查詢系統曾經執行哪些處置、目標是誰,以及處置是否成功或遭到拒絕。
最後建立:
nano test_day24_auto_response.py
這次測試包含三個主要情境。
測試程式先建立真正的 sleep 60 子程序,再取得它的 PID 與程序身分。
如果符合測試規則,就產生一筆測試 Alert,交給 Auto Response Dispatcher。
實際結果:
[TEST 1] Automatic Process Response
[DETECTION] Test process PID: 2814072
========== BehaviorGuard Termination ==========
[POLICY] ALLOW: Policy and identity verified
PID : 2814072
Action : Process Termination
Mode : CONTROLLED TEST
Executed : True
Result : Process exited
[AUDIT] TERMINATE -> SUCCESS
[PASS] Automatic test process termination.
這次透過測試專用的事件判斷,成功呼叫 Day23 的 Response Policy,並真正終止測試程序。
但這筆事件不是由正式 Process Monitor 的惡意行為規則產生,因此還不能視為實際攻擊自動防禦。
接著建立測試專用 Network Alert:
network_alert = {
"rule": "BG-TEST-NET-001",
"severity": "HIGH",
"dst_ip": "127.0.0.2"
}
Dispatcher 檢查後,呼叫真正的 Network Response。
實際結果:
[TEST 2] Automatic Network Response
[DETECTION] Controlled network test event
========== BehaviorGuard Network Response ==========
Target IP : 127.0.0.2
Action : BLOCK
Mode : CONTROLLED TEST
[BLOCK] 127.0.0.2
Executed : True
[AUDIT] BLOCK -> SUCCESS
[PASS] Automatic test IP blocking.
之後測試解除:
[UNBLOCK] 127.0.0.2
Executed : True
[AUDIT] UNBLOCK -> SUCCESS
[PASS] Network connection restored.
代表受控測試事件已經能夠透過 Response Dispatcher,觸發實際的 nftables 封鎖及解除操作。
最後測試輸入:
{
"rule": "BG-TEST-NET-001",
"severity": "HIGH",
"dst_ip": "8.8.8.8"
}
實際結果:
[TEST 3] Unauthorized Target
[AUDIT] BLOCK -> DENIED
[PASS] Unapproved IP denied.
代表即使 Rule ID 符合測試規則,只要目標 IP 不在允許範圍內,系統仍然會拒絕封鎖。
這次並沒有真的封鎖 8.8.8.8。
完成測試後,執行:
sudo tail -n 5 logs/responses.jsonl
這次實際產生四筆處置紀錄:
| Action | Target | Status |
|---|---|---|
| TERMINATE | PID 2814072 | SUCCESS |
| BLOCK | 127.0.0.2 | SUCCESS |
| UNBLOCK | 127.0.0.2 | SUCCESS |
| BLOCK | 8.8.8.8 | DENIED |
其中一筆實際 JSONL:
{
"timestamp": "2026-10-15T03:28:07.541029+00:00",
"rule": "BG-TEST-NET-001",
"action": "BLOCK",
"target": "127.0.0.2",
"status": "SUCCESS",
"reason": "Connectivity blocked"
}
實際儲存時,每筆紀錄都是一行 JSON。
另外,我們再次確認:
sudo nft list table ip bg_day24
結果顯示:
Error: No such file or directory
這表示本次測試表格已經清除,沒有留下該表格的封鎖規則。
經過今天的實作,目前 BehaviorGuard 已經有以下受控 Response 功能:
| 功能 | 測試結果 |
|---|---|
| 使用 nftables 阻斷指定測試 IP | 成功 |
| 驗證 DROP 規則命中封包 | 成功 |
| 透過 Python Response Engine 執行 BLOCK | 成功 |
| 解除封鎖並恢復連線 | 成功 |
| 測試事件觸發 Process Termination | 成功 |
| 測試事件觸發 Network Blocking | 成功 |
| 拒絕未允許的目標 IP | 成功 |
| 保存 Response Audit Log | 成功 |
不過,目前還有幾個重要限制。
第一,尚未連接正式的即時 Network Detection。
今天使用的是測試專用事件,還沒有讓正式的 BG-NET 偵測規則自動觸發封鎖。
第二,目前只允許封鎖 127.0.0.2。
這是為了降低誤封正常網路服務的風險,尚未建立完整的外部 IP 白名單、Gateway 與 DNS 保護機制。
第三,尚未實作限時封鎖。
目前透過測試程式主動解除封鎖。如果程式在處置過程中異常終止,仍可能需要人工清理防火牆規則。
第四,尚未測試 TCP、UDP 與特定 Port 的阻斷效果。
今天主要透過 ICMP Ping 與 nftables Counter 驗證阻斷。
第五,Audit Log 仍是基本版本。
目前已能保存處置時間、對象、動作與結果,但尚未具備完整的事件 ID 關聯、防竄改與集中式管理。
Day24 讓我更了解 Network Blocking 並不是單純執行一條防火牆指令。
一開始,我們先透過 Shell Script,確認 Linux nftables 能夠真正阻斷 127.0.0.2 的測試封包。
但後來發現,雖然測試成功,功能卻還沒有成為 BehaviorGuard Response Engine 的一部分。
因此,我們進一步將 nftables 操作封裝成 Python 模組,讓 Response Engine 可以直接呼叫 Block IP 和 Unblock IP。
接著又加入 Auto Response Dispatcher 與 Response Audit Log,讓受控測試事件可以自動進入處置流程,並保存每次執行的結果。
這次比較重要的收穫,是了解到真正的 Response 不應該只有「執行阻斷」,還需要確認阻斷有沒有成功,以及如何安全解除。
例如,今天透過 nftables Counter 確認封包命中 DROP 規則,再透過解除封鎖後 Ping 恢復的結果,驗證網路連線已恢復。
另外,測試中也加入了目標 IP 限制,確認不允許的 IP 即使被傳入 Response Dispatcher,也不會直接遭到封鎖。
不過,目前的 BehaviorGuard 還沒有完成正式 Detection Pipeline 與實際自動阻斷的整合,因此不能宣稱已經具備完整的自動化網路防禦能力。
下一篇 Day25,我們預計整合正式的 Detection Pipeline 與 Response Dispatcher,讓 Detection、Correlation、Response Policy 和 Audit Log 能夠在同一條事件處理流程中運作。
未來也會持續加強 Network Response Policy,例如 IP 白名單、限時封鎖、Protocol / Port 過濾,以及更完整的處置紀錄。