diff --git a/server/internal/agentd/acl_test.go b/server/internal/agentd/acl_test.go index 390f53e..7100b9a 100644 --- a/server/internal/agentd/acl_test.go +++ b/server/internal/agentd/acl_test.go @@ -416,3 +416,49 @@ func TestACL_NeverConfiguredYieldsNoRoute(t *testing.T) { t.Error("未配置 ACL 也未启用 WARP,不应产出 route 块") } } + +// acl.json 被删除 → 规则不能消失(内存 last-good 兜底)。 +func TestACL_DeletedFileKeepsInMemoryLastGood(t *testing.T) { + cfg := testConfig(t) + writeACL(t, cfg.ACLConfigPath, validACL) + sb := NewSingBox(cfg, nil) + sb.ApplyConfig(sampleSnapshot(&agentv1.Credential{DpUUID: "aaaa", Protocol: agentv1.ProtocolBoth}), true) + if _, err := sb.RenderConfig(); err != nil { + t.Fatal(err) + } + + if err := os.Remove(cfg.ACLConfigPath); err != nil { + t.Fatalf("failed to remove acl.json: %v", err) + } + data, err := sb.RenderConfig() + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(data), "reject") { + t.Fatal("acl.json 被删除后拒绝规则消失了 —— 这是 fail-open,私有服务已敞开") + } +} + +// 新 agent 实例(模拟进程重启) + 被删的 acl.json → 磁盘 last-good 兜底,规则仍在。 +func TestACL_ColdStartAfterDeletedFileFallsBackToDisk(t *testing.T) { + cfg := testConfig(t) + writeACL(t, cfg.ACLConfigPath, validACL) + sb1 := NewSingBox(cfg, nil) + sb1.ApplyConfig(sampleSnapshot(&agentv1.Credential{DpUUID: "aaaa", Protocol: agentv1.ProtocolBoth}), true) + if _, err := sb1.RenderConfig(); err != nil { + t.Fatal(err) + } + + if err := os.Remove(cfg.ACLConfigPath); err != nil { + t.Fatalf("failed to remove acl.json: %v", err) + } + sb2 := NewSingBox(cfg, nil) // 全新实例,内存 last-good 为空 + sb2.ApplyConfig(sampleSnapshot(&agentv1.Credential{DpUUID: "aaaa", Protocol: agentv1.ProtocolBoth}), true) + data, err := sb2.RenderConfig() + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(data), "reject") { + t.Fatal("冷启动(acl.json 删除)未回退到磁盘 last-good,私有服务已敞开") + } +}