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

269 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 → All`allow all protocols
所以剛部署完,所有 peer 彼此互通(就像你目前的狀態)。這對起步階段方便,但**不符合最小權限原則**。
Dashboard 的 Peers 頁面顯示 `Add Groups` 按鈕代表該 peer **沒有自訂 group**(它仍然自動在 `All` 裡)。
## 何時要自訂 Group
### 典型情境
1. **角色分離**:個人裝置 vs 伺服器,不希望伺服器能主動戳個人裝置
2. **最小權限**iPhone 只需能連特定服務,不需連所有 peer
3. **自動化註冊**:用 setup key 部署新機時自動分類(`ci-runners``edge-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-devices``family-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 → Groups****Create Group**
2.**Name**(例 `servers`
3.**Peers** 勾選要加入的 peer
4. **Create**
建完後去 **Access Control → Policies****Peers** 頁面都能再綁定 group。
### 方式 BAPI
```bash
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 → Policies****Add Policy**
2. **Name**:例 `personal-to-servers`
3. **Source Groups**:選 `personal`
4. **Destination Groups**:選 `servers`
5. **Protocol**`All`(或 TCP/UDP/ICMP
6. **Ports**:留空代表全部
7. **Bidirectional**:看需求
- 勾了 → 來回都允許(大多數家用場景這樣方便)
- 不勾 → 只允許 source 主動連 destination
8. **Create**
### 方式 BAPI
```bash
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-servers``servers-to-servers` 等 policy 後,才關掉預設的 `All → All`,不然會暫時中斷連線。
UI**Access Control → Policies → Default** → 右邊三點 → **Delete** 或 toggle **Disabled**
API
```bash
# 先找 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**
```bash
# 建一把 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 限制
```yaml
# 只允許 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 端測試
```bash
# 從 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 用法