iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
自我挑戰組

一鍵完成六套開源防禦系統整合系列 第 29 篇

主機層與整合腳本:容器之外,安裝包還在這台主機上放了什麼

  • 分享至 

  • xImage
  •  

前面十篇談的都是容器裡的東西:八個別人寫的系統、一支自己寫的橋。但 install.sh 跑完之後,主機 B 上多出來的不只容器。這一篇把容器之外的全部列出來:安裝腳本本身、Docker 引擎與它管的網路和資料卷、一個 systemd 服務、一個每小時跑的 cron、一支建 Cloudflare tunnel 的工具,以及由兩個容器組成的歡迎頁。這些東西各自撐不起一篇,但重裝、搬機、排錯時都會碰到,所以合在一起講。 主機與位址沿用防禦節點那一套:主機 A(192.168.0.111)是 BeakPlatform,主機 B(192.168.0.112)是防禦節點。

先講結論。 安裝包在主機 B 上留下的東西,容器之外一共六樣:一個目錄(/opt/integrated-waf,裡面的 .env 是整台節點唯一的設定來源)、Docker 引擎連同它管的一個網路與九個資料卷、一個開機時關掉網卡卸載的 systemd 服務、一個每小時清一次紀錄檔的 cron、一張主機防火牆表(第 8 篇已經整篇講過,本篇只講它與其他東西的關係),以及選用的 Cloudflare 那一側:tunnel 設定與 DNS 記錄不在主機 B 上,在你的 Cloudflare 帳號裡。它們沒有一樣在事件或決策的資料流上,但有兩樣會影響資料流看到什麼:卸載關不乾淨,Suricata 看到的是被合併過的封包;輪替的那一秒,Vector 讀不到正在被清空的幾行。

還有一件值得先知道的事:這些東西裡,只有容器與資料卷是「解除安裝會收走」的範圍。--uninstall 會停容器、刪防火牆表、刪 cron、刪 systemd 服務,但資料卷要加 --purge 才刪,安裝目錄與 .env 永遠留著,升級換掉的舊映像檔也永遠留著。第七節有一張「什麼留、什麼走」的表。

一、install.sh:八個步驟,四種進入方式

安裝腳本 887 行 bash,是整個安裝包裡最大的一支程式。它做的事可以用它自己印出來的八個步驟概括:

步驟 做什麼 要知道的事
1 安裝套件 Docker、Compose、nftables、git、python3、curl、rsync、ethtool,全部用 Ubuntu 自己的 apt 套件庫(docker.io、docker-compose-v2),不加 Docker 官方的套件來源。所以版本跟著 Ubuntu 走,本文寫作時 24.04 給的是 Docker 29.1、Compose 2.40。Portainer 篇講的那個版本問題,就是這個選擇的結果
2 準備安裝目錄 從 GitHub 以 sparse checkout 只抓 Integrated-WAF/ 這個子目錄(不抓整個平台的 repo),rsync 進 /opt/integrated-waf,排除 .env、generated/、od-bridge/state/、suricata/rules/、waf/log/ 五樣:它們是這台主機自己的,程式更新不會蓋掉。如果找不到 .env(上一次的安裝目錄被直接刪掉),會先把殘留的舊容器與資料卷清掉再裝,因為舊資料卷裡的密碼已經無從得知
3 寫入 .env 從 .env.example 複製一份(0600),命令列參數寫進去,開通字串解開寫進去,隨機產生四個密碼與一個 token(只在空值時產生,重跑不會換),再依「有沒有 tunnel token、有沒有歡迎頁網址、有沒有 --no-ui」算出 COMPOSE_PROFILES。.env 之後就是唯一的設定來源:改它,跑 --reconfigure
4 產生 generated/ 由樣板加上 .env 的值產生五樣主機專屬的檔案:Suricata 的設定(網卡名、內網範圍)、ClickHouse 的帳號層網路白名單、Portainer 的管理員密碼檔、歡迎頁的 HTML、紀錄輪替腳本。這個目錄不要手改,下次 --reconfigure 整個重產
5 主機防火牆與網卡卸載 寫 systemd 服務(第四節)、跑 nftables.sh(第 8 篇)。主機上若開著 ufw,補幾條放行規則讓兩套防火牆不打架
6 Suricata 規則集 用 Suricata 容器跑一次 suricata-update 下載 Emerging Threats Open(約 40 MB)。有個戳記記著「上次產生規則時的設定內容」,設定沒變就跳過;變了才重產,而且戳記要等 Suricata 真的以新規則重啟後才定案,中途失敗下次會重做
7 docker compose up -d --build 啟動全部容器;od-bridge 的映像檔在這一步現場建。接著做幾件只能在容器起來之後做的事:建 ClickHouse 的表、把 od-bridge 註冊成 CrowdSec 的機器、替 Portainer 登記本機 Docker、EveBox 換版後重建索引。還有一個「設定檔比對」:單檔掛進容器的設定(CrowdSec 的 profile 等),程式更新是換一個新檔而不是原地改寫,沒被重建的容器會繼續讀舊的,所以比對主機與容器內的檔案內容,不同就重啟那個服務
8 完成與驗證 印出各服務入口與密碼(密碼會印在終端機上,輸出要落地的話自己遮),然後跑 --verify 那一套健康檢查

四種進入方式走的是同一條路的不同起點:--pair … --backend …(全新安裝)跑完整八步;--reconfigure 跳過取得程式,從第 3 步開始;--update 強制從 GitHub 重抓程式再走第 3 步起;--update-rules 只重做第 6 步。另有不改東西的 --status、--verify、--test-event,和反向的 --uninstall。

有一個細節值得記:全新安裝時,腳本會比對「正在執行的這一支」與「剛從 GitHub 抓下來的那一支」,不同就改用新的重新執行一次。原因是曾經發生過「舊腳本配新的 compose 檔」:舊腳本不會產生 Portainer 的密碼檔,新的 compose 卻要掛它,容器起不來。--update 模式沒有這個保護,bash 讀的是執行當下的舊檔;改了 install.sh 本身的更新,要跑兩次才完整生效。

二、它們在主機上的樣子

https://ithelp.ithome.com.tw/upload/images/20261013/20184261UJNln2S78P.png
(圖01:容器之外的東西。左欄是安裝目錄與兩支腳本,中間是 Docker 引擎管的那一包,右欄是寫進主機的三樣:一個 systemd 服務、一張防火牆表、一個 cron。灰線是 cf_tunnel.py 寫到 Cloudflare 帳號與 cron 清空容器內紀錄檔的方向。)

圖上有三件事要看。

  • 只有 .env 一份設定。 容器的環境變數、Vector 的門檻、od-bridge 的憑證、nftables 的白名單、Suricata 的網卡名,全部從它來;generated/ 裡的檔案是它的衍生物,可以隨時重產。備份主機 B 只需要備份 .env 與 od-bridge/state/(CrowdSec 的機器憑證),其餘都能從 GitHub 與 .env 長回來。
  • Docker 管的那一包是一個整體,叫 secstack。 十二個容器、一個網路、九個資料卷都掛著這個專案名稱,docker compose 的所有指令都要在安裝目錄裡下(或帶 -f),否則它找不到專案。右欄三樣不在這個整體裡,是直接寫進主機的。
  • 右欄三樣是「主機層」,容器全停了它們還在。 防火牆表會繼續擋、卸載會繼續關、cron 會繼續跑(找不到檔案就記一行 SKIP)。反過來,重灌主機卻沒重跑 install.sh,容器都在、這三樣都不在。

三、Docker 引擎、網路與資料卷

安裝包選擇用容器跑九個系統,但不用容器跑 od-bridge 以外的任何自寫程式,也不碰 Docker 的進階功能:沒有 swarm、沒有自訂 daemon 設定(/etc/docker/daemon.json 不存在)、沒有私有 registry。它用到的只有三樣:Compose 的 profile、一個固定網段的 bridge 網路、具名資料卷。

Profile:三個開關決定起幾個容器

profile 容器 由什麼決定
(無) clickhouse、od-bridge、vector、suricata、crowdsec、waf-nginx 一定起,六個。這是「基本版」:WAF、兩個偵測、管線、事件庫、橋
ui grafana、evebox、portainer 預設起;--no-ui 不起。三個都不在資料流上,第 5、6、7 篇
tunnel cloudflared .env 的 CLOUDFLARE_TUNNEL_TOKEN 有值就加
welcome welcome、waf-welcome WELCOME_HOSTNAME 有值就加。第六節

Profile 的值寫在 .env 的 COMPOSE_PROFILES,由 install.sh 第 3 步算出來。手動下 docker compose up 時這個變數也要在,Compose 會自己讀同目錄的 .env,所以在安裝目錄裡下指令沒事;在別的目錄用 -f 指定 compose 檔,profile 就全部不見,只起六個。

網路:一個固定網段,兩個例外

容器之間走一個名為 secstack 的 bridge 網路,網段寫死 172.18.0.0/16(可在 .env 改),cloudflared 固定拿 172.18.0.250。固定的原因在 Vector 篇講過:WAF 的紀錄裡「直連它的對象」是不是這個位址,決定了 CF-Connecting-IP 可不可信。兩個例外不在這個網路裡:Suricata 要聽實體網卡,od-bridge 要改主機防火牆,都用主機網路。所以 od-bridge 連 CrowdSec 得走主機的 127.0.0.1:8081,Vector 連 od-bridge 得走 host.docker.internal。

發布到主機的埠,compose 檔裡每一條都明寫 0.0.0.0:,不是省略。省略的話 Docker 會同時在 IPv6 的 [::] 上監聽,而 IPv6 的連線走的是 input hook,完全繞過第 8 篇那套掛在 forward hook 的來源管制,2026 年 9 月 15 日實測 Grafana、Vector API、Portainer、WAF 都能從非白名單的 IPv6 來源連上。寫成 0.0.0.0 之後只綁 IPv4,實機上 ss -tln 看到的 [::] 只剩 sshd 自己的 22 埠。這是一行很容易在整理 compose 檔時被「簡化」掉的東西。

資料卷:九個,三種性質

資料卷 裡面是什麼 性質/實測大小(一台跑了三週的低流量節點)
clickhouse-data 事件表 事件資料。事件留 90 天;實測 1.5 MB,事件本身很小
clickhouse-logs ClickHouse 自己的 log ClickHouse 篇講過 10 月 5 日之前它會長到 GB;關掉之後新的不長了,但之前輪替出來的兩個 .gz(68 MB、92 MB)還在,ClickHouse 自己不會刪。要空間就進去刪
suricata-logs eve.json 與輪替檔 紀錄檔。由第五節的 cron 管,留 48 小時;實測 2.8 MB
vector-data 讀檔位置的 checkpoint 幾百 bytes。刪掉它 Vector 會從檔尾重新開始,不會重讀整檔
crowdsec-config、crowdsec-data CrowdSec 的設定、本機 API 資料庫、hub 下載的情境 設定與狀態。od-bridge 的機器身分登記在這裡,state/crowdsec_machine.json 是它的另一半;兩者要一起留或一起丟
grafana-data Grafana 的資料庫、外掛 57 MB,其中大半是安裝時下載的 ClickHouse 外掛。自建的儀表板在這裡
evebox-data EveBox 的 SQLite 事件留 7 天;流量大的節點會長到幾百 MB(EveBox 篇實測 386 MB)
portainer-data Portainer 的帳號與環境清單 788 KB

兩件和「空間」有關的事:第一,升級不會刪舊映像檔。EveBox 從 0.18.2 換到 0.28.0、Portainer 從 2.21.4 換到 2.45.2 之後,舊的兩個(164 MB 與 398 MB)還在主機上,docker image prune -a 才會清;安裝包刻意不替讀者做這件事,因為它分不出哪些映像檔是讀者自己的。第二,刪安裝目錄不等於解除安裝。直接 rm -rf /opt/integrated-waf 之後容器還在跑、資料卷還在;下次全新安裝時腳本會偵測到「有 secstack 的殘留但沒有 .env」而把它們清掉,但這是補救,不是正規路徑。實機上還看得到幾個 0 bytes 的 integrated-waf_* 資料卷,是更早之前專案名稱還不叫 secstack 時留下的,這種殘留腳本認不得,只能手動 docker volume rm。

四、網卡卸載:一個 systemd 服務

這是整個安裝包裡最短的一個「服務」,但它決定了 Suricata 看到的封包長什麼樣。install.sh 第 5 步寫出這個檔案並啟用:

# /etc/systemd/system/integrated-waf-offload.service
[Unit]
Description=Integrated-WAF: disable NIC offload on ens18 for Suricata capture
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/sbin/ethtool -K ens18 gro off lro off tso off gso off
ExecStart=-/usr/sbin/ethtool -K ens18 rx-gro-hw off
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

為什麼要關:網卡(或虛擬機的宿主)會把連續的 TCP 封包合併成一個大的再交給作業系統,這對吞吐量是好事,對旁路偵測是壞事。Suricata 的擷取長度照 MTU 1500 算,收到一個 60 KB 的「封包」只能截掉尾巴,記一筆 IPv4 truncated packet,裡面的內容就沒有比對到。Suricata 官方文件建議監聽介面關掉這四項(GRO、LRO、TSO、GSO),安裝包照做。

為什麼有第二行、而且前面多一個減號:虛擬機的 virtio 網卡另有一項 rx-gro-hw,合併動作在宿主機做,關掉上面四項關不到它。EveBox 篇第四節就是這個:四項都關了,一次 200 MB 的檔案傳輸還是出現一萬兩千多筆 truncated 告警,再關 rx-gro-hw 才歸零。但實體網卡多半沒有這一項,ethtool 會回錯,所以另起一行、前面加 -,systemd 遇到這一行失敗不算服務失敗。Type=oneshot 加 RemainAfterExit=yes 的意思是「跑一次就好,跑完算啟動成功」,所以 systemctl status 看到的狀態是 active (exited),那是正常的,不是掛了。

它只在開機後跑一次。網卡名稱寫死在檔案裡(安裝時從預設路由偵測),換了網卡或網卡改名,要改 .env 的 NODE_IFACE 再 --reconfigure,腳本會重寫這個檔案。另外,這五項開關是整張網卡的,不是 Suricata 專屬:關掉之後這台主機自己收發大量資料時 CPU 會多做一點事。防禦節點本來就不該是檔案伺服器,這個代價可以接受。

五、紀錄輪替:一個每小時跑的 cron

兩個偵測引擎各寫一個檔案:Suricata 的 eve.json 在資料卷裡,WAF 的 audit.log(歡迎頁另有 audit-welcome.log)在安裝目錄的 waf/log/。它們都只會長,沒有人清就長到磁碟滿。安裝包用一支 50 行的 bash 放在 /etc/cron.hourly/,Ubuntu 的 cron 每小時 17 分跑這個目錄裡的全部腳本。它做的事:

動作 細節
複製後清空 把 eve.json 複製成 eve.json.20261011-16(UTC 的日期與小時),再把原檔清成 0 bytes。不是搬走再建新檔:寫入端(Suricata、WAF)握著的檔案描述子還是同一個,不必通知它們重開檔案;讀取端(Vector)認的是檔案開頭的檢查碼,清空後寫進來的新內容對它是一個新檔,從頭讀起,不會重讀舊內容
壓縮 五分鐘前輪替出來的檔案 gzip。實測這台節點每小時 740 KB 的 eve.json 壓完 27 KB
保留 eve.json 的輪替檔留 48 小時,兩個 WAF 的留 6 小時。理由在 Suricata 篇講過:告警都進了 ClickHouse(留 90 天),檔案裡多的是連線、DNS、TLS 這些沒進 ClickHouse 的紀錄,兩天是「事後回頭看那個來源當時還連了哪裡」的窗口
空檔不動 WAF 只記有問題的交易,低流量節點大部分的小時 audit.log 是 0 bytes,記一行 SKIP empty 就過
留紀錄與心跳 每次跑完寫 /opt/tmp/secstack-rotate-logs.log;全部成功時更新 /opt/tmp/heartbeat/secstack-rotate-logs 的時間戳。要知道它有沒有在跑,看後者的時間是不是一小時內

為什麼不用 logrotate:logrotate 預設會降權去動檔案,而這些檔案的擁有者是容器裡的使用者(在主機上顯示成不相干的帳號名),路徑又穿過權限 750 的目錄,降權後穿不過去,靜默失敗,什麼都不會印。用 root 直接 copy 加 truncate 繞開這整件事,代價是自己寫保留與壓縮,50 行。

兩個已知的限制,腳本註解裡自己寫了:第一,清空的那一瞬間還沒被 Vector 讀走的幾行會不見,每小時一次、約一秒,Vector 篇第三節提過。第二,Vector 不讀輪替出來的檔案;Vector 停機超過一小時,那一小時的紀錄被搬進 .gz,Vector 回來後只會從清空後的檔案接著讀,那一小時的事件只剩 gz 裡的原始紀錄,不會進 ClickHouse 也不會到主機 A。這條在 WAF 篇的營運那一篇也列了。

這支 cron 只管兩個偵測引擎的檔案。ClickHouse 的 log 由 ClickHouse 自己輪替(第三節提到的那兩個 gz 就是它輪的),Docker 容器的 stdout(docker compose logs 看到的那些)由 Docker 的 json-file 驅動管,安裝包沒有設上限,依 Docker 預設不設限。實測三週的低流量節點十二個容器合計 32 MB,其中一個就佔 27 MB:主機 A 不通的那三十個小時,每 30 秒一行的重試紀錄全在裡面。要限制就在 compose 檔加 logging.options.max-size。

六、cf_tunnel.py 與歡迎頁

cf_tunnel.py:把 Zero Trust 後台要手點的三件事變成一條指令

cloudflared 篇講的是 tunnel 跑起來之後的事;tunnel 本身怎麼來,有兩條路。一條是到 Cloudflare 的 Zero Trust 後台手點:建 tunnel、設 Public Hostname(哪個網址轉到 http://waf-nginx:8080)、DNS 會自動加一筆 CNAME,然後把 connector token 貼進 .env。另一條是給腳本一個 API Token,讓 cf_tunnel.py 做同樣三件事。安裝時加 --cf-api-token 與 --cf-hostname 走的就是第二條;它不是必要的,第一條路的結果完全相同。

項目 內容
相依 只用 Python 標準函式庫,297 行。API Token 從參數或環境變數 CF_API_TOKEN 進來,後者不會留在 shell 歷史
Token 要的權限 三項:Account 的 Cloudflare Tunnel 編輯、Zone 的 DNS 編輯、Zone 的讀取。沒有 Account 層的讀取權限時,它會從 zone 反查 account 編號;一個 Token 看得到多個 account 就要用 --account-id 指定
setup 做什麼 依網址逐段往上找出它屬於哪個 zone → 找同名 tunnel,沒有就建(預設名 integrated-waf)→ 把這個網址的 ingress 規則加進 tunnel 設定(同名既有的先移除再加,最後一條固定是「其餘回 404」)→ 建或更新 CNAME 指到 <tunnel id>.cfargotunnel.com、開 proxied → 取 connector token,印出或直接寫進 .env(寫完把檔案設成 0600)
可重跑 每一步都是「有就沿用、不同才改」:tunnel 同名沿用、ingress 同網址同路徑取代、CNAME 已指向正確目標就回 unchanged。網址已經有一筆不是 CNAME 的記錄(例如 A 記錄)時它會停下來要你手動處理,不會蓋掉
同一網址分路徑 --path '^/beakplatform(/|$)' 只把符合的路徑導到被保護網站;同網址沒有 path 的那一條接其餘路徑。規則排序是帶 path 的在前,這是 cloudflared 比對的順序。安裝腳本的 --welcome-hostname 與 --cf-hostname 同名時就是這樣用的
remove/status/token 移除某個網址的全部 ingress 與 CNAME(不刪 tunnel);列出 tunnel 的連線(在哪個機房、從哪個來源 IP 連上)與全部 ingress;只印 token

要記住的一件事:這支腳本寫的東西都不在主機 B 上。tunnel、ingress 規則、DNS 記錄住在 Cloudflare 的帳號裡,主機 B 只拿到一個 token。重裝主機 B、換一台主機 B,只要把同一個 token 貼進去,對外網址就接回來;反過來,要改網址或路徑,改主機 B 的任何東西都沒用,得改 Cloudflare 那一側,用後台或用這支腳本。

歡迎頁:兩個容器,一行字

歡迎頁是安裝包裡最小的一個功能:一個 nginx 容器(nginx:1.27-alpine)放一頁靜態 HTML,內容只有「歡迎到 <網址>」一行字與一個 favicon,由樣板加上 .env 的 WELCOME_HOSTNAME 產生在 generated/welcome/。它的前面有自己獨立的一個 WAF 容器(waf-welcome,與主站的 waf-nginx 同一個映像檔、同一套規則、同一個偏執等級),紀錄寫到 audit-welcome.log,Vector 讀進來時 target.service 標成 waf-welcome。

它存在的理由有兩個。第一是給對外網址一個「根路徑」:讀者的被保護網站多半掛在某個路徑前綴下(例如 /beakplatform),同一個網址的根路徑總得回點什麼,歡迎頁就是那個東西,cloudflared 的分路徑規則把前綴導到主站、其餘導到它。第二是多一個被刺探的面:掃描器對一個網域的根路徑做的事(找 /.env、/wp-login.php、打 SQL 注入)會撞上 waf-welcome,產生和主站同格式的事件、走同一條路到主機 A。它不是蜜罐:沒有互動、不假裝成任何系統、不記錄攻擊者的後續行為,它只是一面牆,牆前面有 WAF。

不設 WELCOME_HOSTNAME 時這兩個容器不存在,docker compose ps 看不到它們,cloudflared 的規則也只有一條。內網驗證走主機 B 的 8082 埠,與主站的 8080 同樣受第 8 篇的來源管制。

七、什麼留、什麼走;怎麼確認

先是三種「拆掉」各自會留下什麼,這張表是本篇最實用的部分:

東西 --uninstall --uninstall --purge 直接 rm -rf 安裝目錄
十二個容器 停並移除 停並移除 還在跑
九個資料卷 留 刪 留
映像檔(含升級換下的舊版) 留 留 留
inet secstack 防火牆表 刪,/etc/nftables.conf 清成空檔 同左 還在擋
systemd 卸載服務 停用並刪檔 同左 還在
cron 輪替 刪 刪 還在(每小時記一行 SKIP missing)
安裝目錄與 .env 留(腳本會告訴你怎麼刪) 留 沒了,密碼一起沒了
Cloudflare 的 tunnel、DNS 留 留 留。要收用 cf_tunnel.py remove 或後台
主機 A 上的金鑰與執行帳號 留 留 留。節點沒了它們還有效,要在主機 A 停用

再來是確認這些東西都在、都在做事的指令。這幾條 install.sh --verify 沒有全部涵蓋,因為它們不影響服務健康,只影響「下次重開機之後」:

# 主機 B:卸載服務。active (exited) 是正常的;五項都該是 off
systemctl is-active integrated-waf-offload.service
sudo ethtool -k ens18 | grep -E '^(generic-receive|large-receive|tcp-segmentation|generic-segmentation)-offload|^rx-gro-hw'
generic-receive-offload: off
large-receive-offload: off [fixed]
tcp-segmentation-offload: off
generic-segmentation-offload: off
rx-gro-hw: off

# 輪替:心跳在一小時內、最近一輪是 OK
cat /opt/tmp/heartbeat/secstack-rotate-logs
tail -4 /opt/tmp/secstack-rotate-logs.log

# Docker 這一包:profile、容器、資料卷、映像檔佔多少
cd /opt/integrated-waf
sudo docker compose config --profiles
sudo docker compose ps --format 'table {{.Service}}\t{{.Status}}'
sudo docker system df

# 防火牆表還在、開機會還原
sudo nft list table inet secstack | head -5
systemctl is-enabled nftables.service

# tunnel 那一側(要 API Token)
CF_API_TOKEN=… python3 cf_tunnel.py status

最後一個常見的疑問:重開機之後會自己好嗎。會,而且這件事由四個互不相干的機制各自保證:容器靠 Docker 的 restart: unless-stopped 與 docker.service 開機啟動;防火牆表靠 nftables.service 讀 /etc/nftables.conf 還原(但 blocklist 裡的元素不會還原,那些是 kernel 的狀態,重開機就沒了,主機 A 那邊的決策仍然是 applied);卸載靠上面那個 oneshot 服務;輪替靠 cron。四個裡面壞掉最不容易察覺的是第三個:服務在、但網卡改了名,ethtool 對不存在的網卡回錯,服務狀態是 failed,Suricata 照常跑,只是告警裡多了一堆 truncated。

主機層到此說完,搭配元件篇、專篇與合篇到這裡一共29篇,整個系列也到這裡結束。回頭看,安裝包在主機 B 上放的東西分三層:Docker 管的一包(九個別人的系統加一支自己的橋)、直接寫進主機的三樣(防火牆表、一個 systemd 服務、一個 cron)、以及不在主機上的一樣(Cloudflare 帳號裡的 tunnel)。讀者要把這套東西搬進自己的環境時,容器那一層最不用擔心,照著 compose 檔就能重現;真正要照顧的是中間那三樣,它們不在任何 docker compose ps 的輸出裡,壞了也不會有容器變紅。這也是整個系列的最後一句:看得見的元件都有人替你顧,看不見的那幾樣才是你的。


上一篇
od-bridge:事件從這裡出去,決策從這裡回來
系列文
一鍵完成六套開源防禦系統整合 共 29 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言