Files
netbird-selfhosted/groups-and-policies.md
timmy d7a9fb55ec docs: add Groups and Access Control Policies guide
Explain what Groups are in NetBird, the four places they surface
(policies, setup keys auto_groups, network routes, DNS), and a
concrete segmentation plan for the current mesh:

- servers group: CT100, CT101
- personal group: mbp-13-pro, iphone-15-pro
- Replace default All->All with least-privilege policies
  (personal->servers, servers<->servers)

Includes UI and API workflows, a phased migration plan, rollback
strategy, and how to wire auto_groups into setup keys for future
deployments.
2026-04-18 15:27:23 +08:00

8.8 KiB
Raw Blame History

Groups 與 Access Control Policies

NetBird 的存取控管基本單位。本文用目前部署的 4 個 peermbp-13-pro、iphone-15-pro、CT100、CT101為例說明 Groups 怎麼用。

Groups 是什麼

Group 是 peer 的具名集合。NetBird 不直接管「peer A 能不能連 peer B」而是

  1. 把 peer 丟進 group
  2. Policy 定義「group X → group Y 的流量允許/禁止」

這讓存取控管的規模隨服務/角色擴展,而不是隨 peer 數量爆炸。

Groups 在 NetBird 裡出現的 4 個地方

地方 用途
Access Control → Policies 決定 group A 能不能連 group B、哪些 port/protocol
Setup Keys 的 auto_groups 用此 key 註冊的 peer 自動進指定 group
Network Routes 哪個 group 能透過某個 peer 走一條路由(例:透過 CT100 當 exit node
DNS / Nameservers 哪個 group 套用特定 DNS 設定

這四個功能都以 group 當接口,換句話說 — group 設計對了,整個存取模型就清楚了

預設:All group 與 Default policy

NetBird 初始化時自動建立:

  • All group — 所有 peer 自動加入
  • Default policy — All → Allallow all protocols

所以剛部署完,所有 peer 彼此互通(就像你目前的狀態)。這對起步階段方便,但不符合最小權限原則

Dashboard 的 Peers 頁面顯示 Add Groups 按鈕代表該 peer 沒有自訂 group(它仍然自動在 All 裡)。

何時要自訂 Group

典型情境

  1. 角色分離:個人裝置 vs 伺服器,不希望伺服器能主動戳個人裝置
  2. 最小權限iPhone 只需能連特定服務,不需連所有 peer
  3. 自動化註冊:用 setup key 部署新機時自動分類(ci-runnersedge-nodes 等)
  4. 分享給家人:一個 group 只給家人裝置policy 限制他們能看到的範圍
  5. Exit Node 授權:只有特定 group 能把流量導去某 peer

本部署的建議分組

以目前 4 個 peer

Group 成員 用途
servers CT100、CT101 家裡 headless 服務
personal mbp-13-pro、iphone-15-pro Timmy 的個人裝置

對應的 Policy

# From To 目的
1 personal servers 個人裝置能連伺服器
2 servers servers 伺服器彼此互連(例如未來備份、日誌集中)
3 All → All (Default) 刪除或停用

刻意建立 servers → personal 的 policy伺服器被入侵時攻擊者無法透過 NetBird 橫向移動到個人裝置。

(未來如果有多個使用者,可再拆 timmy-devicesfamily-devices 等。)

Peer 可以同時屬於多個 group

常見用法:

  • CT100: in both servers and jump-boxes(對不同 policy 都有效)
  • CT101: in both servers and rustdesk(另一條政策只開 rustdesk port 給某個子集)

Peer group 是集合運算policy 匹配時用 ORpeer 只要在 policy 的 source group 任一個裡就算命中。

怎麼建 Group

方式 AUI推薦起步

  1. Dashboard → Access Control → GroupsCreate Group
  2. Name(例 servers
  3. Peers 勾選要加入的 peer
  4. Create

建完後去 Access Control → PoliciesPeers 頁面都能再綁定 group。

方式 BAPI

TOKEN=<你的 PAT>

# 先查目前 peer 清單拿 ID
curl -sf -H "Authorization: Token $TOKEN" \
  https://netbird.timmy.us.kg/api/peers | jq '.[] | {id, name}'

# 建 servers group同時塞兩個 peer
curl -sf -X POST -H "Authorization: Token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "servers",
    "peers": ["<CT100-peer-id>", "<CT101-peer-id>"]
  }' \
  https://netbird.timmy.us.kg/api/groups | jq

# 建 personal group
curl -sf -X POST -H "Authorization: Token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "personal",
    "peers": ["<Mac-peer-id>", "<iPhone-peer-id>"]
  }' \
  https://netbird.timmy.us.kg/api/groups | jq

怎麼建 Policy

方式 AUI

  1. Access Control → PoliciesAdd Policy
  2. Name:例 personal-to-servers
  3. Source Groups:選 personal
  4. Destination Groups:選 servers
  5. ProtocolAll(或 TCP/UDP/ICMP
  6. Ports:留空代表全部
  7. Bidirectional:看需求
    • 勾了 → 來回都允許(大多數家用場景這樣方便)
    • 不勾 → 只允許 source 主動連 destination
  8. Create

方式 BAPI

curl -sf -X POST -H "Authorization: Token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "personal-to-servers",
    "enabled": true,
    "description": "Personal devices can access servers",
    "rules": [{
      "name": "personal-to-servers",
      "enabled": true,
      "action": "accept",
      "protocol": "all",
      "sources": ["<personal-group-id>"],
      "destinations": ["<servers-group-id>"],
      "bidirectional": false
    }]
  }' \
  https://netbird.timmy.us.kg/api/policies | jq

刪除預設 Default policy

當你建立好新的 personal-to-serversservers-to-servers 等 policy 後,才關掉預設的 All → All,不然會暫時中斷連線。

UIAccess Control → Policies → Default → 右邊三點 → Delete 或 toggle Disabled

API

# 先找 policy ID
curl -sf -H "Authorization: Token $TOKEN" \
  https://netbird.timmy.us.kg/api/policies | jq '.[] | {id, name, enabled}'

# 停用(較安全,出問題可立刻打開)
curl -sf -X PUT -H "Authorization: Token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '<GET 出來的內容,改 "enabled": false>' \
  https://netbird.timmy.us.kg/api/policies/<POLICY_ID>

# 或直接刪除
curl -X DELETE -H "Authorization: Token $TOKEN" \
  https://netbird.timmy.us.kg/api/policies/<POLICY_ID>

Setup Key 搭配 auto_groups

部署新 peer 時可以一步到位自動加 group

# 建一把 key註冊進來的 peer 自動進 servers group
curl -sf -X POST -H "Authorization: Token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CT102-whatever",
    "type": "one-off",
    "expires_in": 86400,
    "usage_limit": 1,
    "ephemeral": false,
    "auto_groups": ["<servers-group-id>"]
  }' \
  https://netbird.timmy.us.kg/api/setup-keys | jq

如此 CT100/CT101 這類部署可以省掉「註冊完再手動加 group」的步驟。

(之前 CT100/CT101 的 setup key 我建的時候 auto_groups 是空的 — 未來部署時記得帶上)

Policy 細節補充

Port / Protocol 限制

# 只允許 SSH (TCP/22) 從 personal 連到 servers
rules:
  - protocol: tcp
    ports: ["22"]
    sources: [<personal-group-id>]
    destinations: [<servers-group-id>]

Bidirectional 的真正含義

  • bidirectional: true — A → B 與 B → A 都允許
  • bidirectional: false — 只允許 source 端主動 initiate但回應封包 NetBird 會自動放行stateful不用特別設

家用場景建議預設 false,只在真的需要雙向 initiate 時才開。

Posture Checks進階

Policy 可綁 Posture Check — 要求 peer 滿足某些條件OS 版本、地理位置、已登入 SSO 等)才能走這條 policy。進階情境可參考 NetBird docs。

驗證 Policy 生效

方式 A從 peer 端測試

# 從 Mac ping iPhone (現在可以) → 建立 personal-only policy 後,應該還是可以
ping 100.71.63.111

# 從 CT100 ping Mac (現在可以) → 刪掉 All→All 後,應該不通
ssh root@192.168.42.100 'docker exec netbird netbird status --detail | grep mbp-13-pro -A 3'

方式 BDashboard → Control Center

視覺化顯示每個 peer 的 policy 連線關係,可以一眼看出誰能連誰。

整套搬遷步驟建議

漸進式,不中斷當前連線

Phase 1: 建 groups
  - Create group "servers" with CT100, CT101
  - Create group "personal" with Mac, iPhone

Phase 2: 建新 policies先不刪預設
  - Policy "personal-to-servers": personal → servers
  - Policy "servers-to-servers": servers → servers (bidirectional)
  - 此時 All→All 跟新 policy 並存,功能不變

Phase 3: 驗證新 policy 生效
  - 關掉 All→All先 disable 不 delete
  - 實測Mac→CT100 通、iPhone→CT101 通、CT100→Mac **不通**

Phase 4: 確認無誤
  - 刪除 Default policy如果想
  - 日後新 peer 記得 setup key 的 auto_groups 要填對

出問題 rollback把 Default policy 重新啟用即可恢復原狀。

相關檔案與文件

  • setup-keys-and-pat.md — PAT 與 setup key 建立(建 group 需要 PAT
  • client-troubleshooting.md — 如果改 policy 後 peer 突然連不到,先查這裡
  • peer-deployment-ops.md — 新部署 peer 時的 setup key + auto_groups 用法