Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .planning/STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ milestone: v4.2.0
milestone_name: 容器合并 · SQLite 迁移 · 配置统一
status: Awaiting next milestone
stopped_at: Phase 58 context gathered
last_updated: "2026-06-01T08:05:26.830Z"
last_activity: 2026-06-01Milestone v4.2.0 completed and archived
last_updated: "2026-06-02T00:00:00.000Z"
last_activity: 2026-06-02Completed quick task 260602: 规则导入导出按钮
progress:
total_phases: 5
completed_phases: 1
Expand All @@ -28,7 +28,7 @@ See: .planning/PROJECT.md (updated 2026-05-14)
Phase: Milestone v4.2.0 complete
Plan: —
Status: Awaiting next milestone
Last activity: 2026-06-01Milestone v4.2.0 completed and archived
Last activity: 2026-06-02Completed quick task 260602: 规则导入导出按钮

## Accumulated Context

Expand Down Expand Up @@ -78,6 +78,7 @@ v3.6 关键技术决策(已落地,可作为后续里程碑参考):
| 260513-fjd | 修复 SubnetThirdOctet 碰撞测试阈值(10 → 40,匹配生日悖论期望) | 2026-05-13 | 0def841 | [260513-fjd-subnetthirdoctet](./quick/260513-fjd-subnetthirdoctet/) |
| 260513-gii | 修复 UpsertHost SQL 占位符不匹配(移除孤立的 $13,POST /v1/admin/hosts 500) | 2026-05-13 | 04636fd | [260513-gii-upserthost-sql](./quick/260513-gii-upserthost-sql/) |
| 260513-kru | 修复 worker netns 获取失败(增加重试 + 容器状态检查 + 延迟) | 2026-05-13 | f1c3a35 | [260513-kru-worker-netns](./quick/260513-kru-worker-netns/) |
| 260602 | 规则导入导出按钮 | 2026-06-02 | pending | [260602-rules-import-export](./quick/260602-rules-import-export/) |

### Roadmap Evolution

Expand Down
23 changes: 23 additions & 0 deletions .planning/quick/260602-rules-import-export/260602-PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
status: complete
---

# Quick Task 260602: 规则导入导出按钮

## 目标

在主机详情页代理白名单的规则区域,在「添加规则」按钮后新增「规则导出」和「规则导入」按钮。

## 任务

1. 在 `web/admin/src/components/bypass/custom-rules-table.tsx` 中新增导出/导入交互。
2. 导出当前展示规则为本地 JSON 文件。
3. 导入 JSON 文件并通过现有创建规则 API 追加为自定义规则。
4. 补充 `custom-rules-table` 相关单元测试。

## 验收

- 规则区域按钮顺序为「添加规则」「规则导出」「规则导入」。
- 导出文件为 JSON,包含 `version`、`exported_at`、`rules`。
- 导入支持上述对象格式,也支持直接上传规则数组。
- 导入成功后提示点击「应用」生效。
28 changes: 28 additions & 0 deletions .planning/quick/260602-rules-import-export/260602-SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
status: complete
---

# Quick Task 260602: 规则导入导出按钮 - Summary

## 完成内容

- 在主机详情页代理白名单规则区新增「规则导出」和「规则导入」按钮。
- 导出当前规则为本地 JSON 文件,格式包含 `version`、`exported_at`、`rules`。
- 导入支持上传导出文件或直接上传规则数组,并通过现有创建规则 API 追加为自定义规则。
- 导入规则使用 `confirm_risky: true`,成功后提示用户点击「应用」生效。
- 补充按钮展示和 JSON 上传导入的单元测试。

## 修改文件

- `web/admin/src/components/bypass/custom-rules-table.tsx`
- `web/admin/src/components/bypass/__tests__/custom-rules-table.test.tsx`
- `.planning/STATE.md`

## 验证

- `corepack pnpm --dir web/admin typecheck`:未通过运行,原因是 `web/admin/node_modules` 缺失,`tsc` 命令不可用。
- `corepack pnpm --dir web/admin test:unit -- src/components/bypass/__tests__/custom-rules-table.test.tsx`:未通过运行,原因是 `web/admin/node_modules` 缺失,`vitest` 命令不可用。

## 后续

安装前端依赖后重新运行类型检查和相关单元测试。
8 changes: 4 additions & 4 deletions deploy/docker/managed-user/default-deny.nft
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ table inet cloud_proxy_v4 {
# 放行 tun0(sing-box 接管)
oifname "tun0" counter accept

# 放行 sing-box (uid=9000) 通过 eth0 直连代理服务器
meta skuid 9000 oifname "eth0" counter accept comment "singbox-direct-egress"
# 放行 sing-box (uid=9000) 直连代理服务器;外联网卡名由 Docker 当前路由决定
meta skuid 9000 counter accept comment "singbox-direct-egress"

# 显式 drop 外部 DNS(防止用户 dig @8.8.8.8 旁路)
meta l4proto udp udp dport 53 ip daddr != 127.0.0.0/8 counter drop comment "extdns-udp-drop"
Expand All @@ -44,8 +44,8 @@ table inet cloud_proxy_v4 {
# 反向连接放行
ct state established,related counter accept

# 白名单 set:ApplyBypassRuleSet 动态填充,仅 eth0 生效(tun0 已在前面放行)
oifname "eth0" ip daddr @whitelist_v4 counter accept comment "bypass-whitelist"
# 白名单 set:ApplyBypassRuleSet 动态填充;不依赖 Docker 外联网卡名
oifname != "lo" oifname != "tun0" ip daddr @whitelist_v4 counter accept comment "bypass-whitelist"

# 兜底(policy drop 已覆盖,这条 counter 用于可观测)
counter drop comment "default-deny-tail"
Expand Down
10 changes: 5 additions & 5 deletions deploy/docker/managed-user/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ assert_tmux_version() {
# ===== v4.0 (Phase 53): sing-box 同容器化启动序列 — fail-closed =====
# D-V4-1..4 + D-53-2/3/4/5/6 集中实现:
# - start_singbox_or_die:runuser → uid=9000 + 文件 cap + tun0 waitFor
# - lock_resolv_conf:DNS 强制走 sing-box direct inbound (127.0.0.1:53)
# - lock_resolv_conf:DNS 强制走 sing-box DNS inbound (127.0.0.1:53)
# - apply_nft_or_die:容器内 nft default-deny ruleset
# - remove_singbox_config:sing-box load 后 shred config 从 fs
# - monitor_singbox_fail_closed:sing-box 死 → kill PID 1 → 容器死
Expand Down Expand Up @@ -272,11 +272,11 @@ start_singbox_or_die() {
}

lock_resolv_conf() {
# v4.0: DNS 指向 127.0.0.1,由 sing-box direct inbound (dns-direct) 接管。
# v4.0: DNS 指向 127.0.0.1,由 sing-box DNS inbound 接管。
# 不能用 tun0 IP (172.19.0.1) —— 内核本地处理该地址的包,tun 设备收不到。
echo "[entrypoint] locking /etc/resolv.conf to sing-box dns-direct (127.0.0.1)"
echo "[entrypoint] locking /etc/resolv.conf to sing-box DNS inbound (127.0.0.1)"
cat > /etc/resolv.conf <<'EOF'
# v4.0: DNS 强制走 sing-box direct inbound (D-V4-3)
# v4.0: DNS 强制走 sing-box DNS inbound (D-V4-3)
nameserver 127.0.0.1
options edns0 trust-ad
EOF
Expand Down Expand Up @@ -428,7 +428,7 @@ fi
fix_singbox_routing() {
# v4.0 (Phase 54): sing-box auto_route 默认在规则 9001 上设置
# suppress_prefixlength 0,该选项会压制 table 2022 中的默认路由,
# 导致用户流量回退到 main 表走 eth0 → 被 nft default-deny 丢弃。
# 导致用户流量回退到 main 表走 Docker 外联路由 → 被 nft default-deny 丢弃。
#
# 修复分三步:
# 1. 为 sing-box 自身 (uid=9000) 添加优先规则走 main 表,
Expand Down
1 change: 1 addition & 0 deletions internal/agentapi/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type HostActionRequest struct {
Hostname string `json:"hostname"`
MemoryLimitMB int `json:"memory_limit_mb,omitempty"`
CPULimit float64 `json:"cpu_limit,omitempty"`
PidsLimit *int `json:"pids_limit,omitempty"`
Username string `json:"username,omitempty"`
EntryPassword string `json:"entry_password,omitempty"`
SSHPublicKey string `json:"ssh_public_key,omitempty"`
Expand Down
Loading