cmos486/argos-edge
GitHub: cmos486/argos-edge
自托管边缘网关,整合反向代理、WAF、负载均衡与 SSO,解决家庭实验室多组件集成与安全管控痛点。
Stars: 0 | Forks: 0
# argos-edge
[](LICENSE)
[](https://github.com/cmos486/argos-edge/releases)
[](https://cmos486.github.io/argos-edge/)
自托管边缘网关,适用于家庭实验室。反向代理 + WAF + 负载均衡 + Let's Encrypt,统一网页面板。由 Caddy、Coraza 和 CrowdSec 提供支持。
**状态:** v1.0.0 — 首个稳定发布。家庭实验室级别:针对其目标用例的生产就绪版本,单人维护,尽力提供支持。请参阅 [文档门户](https://cmos486.github.io/argos-edge/) 获取安装与运维说明。
## 为什么
Nginx Proxy Manager 太简单。Zoraxy 缺乏 WAF。BunkerWeb 和 SafeLine 很棒,但不完全符合我的需求。Argos Edge 是一个个人家庭实验室项目,旨在解决我自己的痛点:提供一个集成了代理 + 真实 WAF + ALB 风格规则 + 优秀仪表板的单一面板。
## 技术栈
- [Caddy 2](https://caddyserver.com/) 作为代理(TLS、Let's Encrypt、HTTP/3)
- [Coraza](https://coraza.io/) + OWASP CRS 作为 WAF(阶段 4)
- [CrowdSec](https://www.crowdsec.net/) 用于社区威胁情报(阶段 6)
- Go 后端,React + TypeScript + Tailwind 前端,SQLite 存储
## 快速开始
```
git clone https://github.com/cmos486/argos-edge.git
cd argos-edge
cp .env.example .env
# edit .env: set ARGOS_SESSION_SECRET, ARGOS_MASTER_KEY, ARGOS_INITIAL_ADMIN_PASSWORD
docker compose up -d
```
然后打开 `http://:8080`,使用你在 `.env` 中设置的凭据登录。
## 面板访问模式
第 9b 阶段引入了两种访问模式,通过 `ARGOS_PANEL_MODE` 选择:
| 方面 | `lan`(默认) | `behind_caddy` |
|---|---|---|
| 如何访问面板 | `http://:8080` | `https://$ARGOS_PANEL_DOMAIN/` |
| `:8080` 是否在主机上发布 | 是 | 否(仅内部) |
| Cookie 的 `Secure` 标志 | 关闭 | 开启 |
| `SameSite` | 严格(两种模式) | 严格 |
| HSTS 头部 | 不发送 | `max-age=31536000; includeSubDomains` |
| 内容安全策略 | 不发送 | 发送(严格,不允许外部来源) |
| 浏览器推送 | 阻止(无 HTTPS) | 可用 |
| 首次启动引导 | - | 自动创建主机行 + 指向 `argos:8080` 的 TG |
### LAN 模式
无需操作:`docker compose up -d` 会在 `http://:8080` 启动面板。
### behind_caddy 模式
1. 在 `.env` 中设置:
ARGOS_PANEL_MODE=behind_caddy
ARGOS_PANEL_DOMAIN=panel.example.com
2. 使用覆盖文件启动堆栈:
docker compose -f docker-compose.yml -f docker-compose.behind-caddy.yml up -d
3. 面板在首次启动时自动注册为主机;Caddy 在约 30 秒内通过 DNS-01 获取证书。访问 `https://panel.example.com/`。
要求 Docker Compose v2.24+(用于覆盖文件中的 `!reset []` YAML 标签)。
**v0.9.0 的重大变更:** `ARGOS_COOKIE_SECURE` 已被移除。Cookie 安全标志现在从 `ARGOS_PANEL_MODE` 派生。
## CrowdSec(威胁情报)
第 7 阶段将 CrowdSec 作为 docker-compose 服务捆绑。CrowdSec 读取 Caddy 的访问日志,并将决策推送到面板的 UI(`/threats`)以及 Caddy 的 bouncer 以进行强制。在首次 `docker compose up -d` 后的一次性设置:
```
# 1. Issue a bouncer API key for Caddy's HTTP bouncer module
docker compose exec argos-crowdsec cscli bouncers add argos-caddy-bouncer
# copy the printed key
# 2. Register the panel as a CrowdSec "machine" so it can add / delete
# decisions from the UI (bouncer keys are read-only)
docker compose exec argos-crowdsec cscli machines add argos-panel -a -f /tmp/argos-panel.yaml
docker compose exec argos-crowdsec cat /tmp/argos-panel.yaml
# copy login + password
# 3. Put all three values in .env:
# CROWDSEC_BOUNCER_API_KEY=
# CROWDSEC_PANEL_MACHINE_USER=argos-panel
# CROWDSEC_PANEL_MACHINE_PASSWORD=
# 4. Rebuild so caddy picks up the bouncer key + panel reads new env
docker compose up -d --build
```
在第 4 步运行之前,面板会正常启动,并且 `/threats` 会显示一个带有上述命令的设置横幅。Caddy 在无强制的情况下服务流量。
要安装额外的 CrowdSec 集合:
```
docker compose exec argos-crowdsec cscli collections install crowdsecurity/
```
CrowdSec 的 LAPI 在 docker 网络中监听 `crowdsec:8081`(未发布到主机)。默认 LAPI 端口 8080 会与 argos-panel 冲突,因此我们将 `crowdsec/config.yaml.local` 挂载以覆盖它。
## OIDC SSO + ForwardAuth
Argos 支持通过任何符合 OIDC 标准的提供者
(Authentik、Authelia、Keycloak、Google、Okta、...)登录面板,并且可以保护 argos 代理的任何主机,通过到同一会话的 ForwardAuth 往返。
本地密码 + TOTP 路径在 IdP 不可用时仍完全可用,作为应急回退路线。
### 架构概览
```
browser ──▶ Caddy (argos-caddy) ──▶ upstream (huntlo, etc.)
│
│ [host.auth_required=1]
▼
forward_auth handler
│ GET /api/auth/forward
│ cookies forwarded
▼
argos panel
│
├─ cookie valid → 200 + X-Auth-{User,Email,Name,Provider}
│ (copied onto upstream request)
│
└─ cookie missing → 302 /login?rd=
user logs in (password+TOTP or SSO)
cookie Domain= → subdomains share it
```
关键点:
1. **一次仅一个提供者。** `/system` > SSO 保存发行者 URL、
客户端 ID/密钥、作用域、电子邮件/域名允许列表。
`client_secret` 使用 AES-GCM 的 `ARGOS_MASTER_KEY` 加密。
2. **PKCE 是强制性的。** Argos 永远不会发出非 PKCE 流程。
3. **OIDC 用户绕过本地 TOTP** — IdP 是 MFA 的权威来源。
本地用户继续使用 bcrypt + TOTP。
4. **应急回退:** 一个拥有本地用户名+密码及 TOTP 的用户
始终可用。`docker compose exec argos /argos disable-2fa
--user admin --yes` 仍可在管理员丢失手机和恢复码时重置 TOTP。
5. **父域 Cookie** 是将面板会话绑定到 ForwardAuth 保护子域的关键。配置一次后,每个
`*.parent-domain` 主机均可设置为 `auth_required=1`。
### 设置:Authentik
1. 提供者 → 创建 → OAuth2/OpenID 提供者
- 名称:argos
- 客户端类型:机密
- 重定向 URI:`https://argos.example.com/api/auth/oidc/callback`
- 作用域:openid profile email
2. 应用程序 → 创建 → 绑定到该提供者。
3. 复制客户端 ID + 客户端密钥。
4. argos **/system** → 单点登录:
- 发行者 URL:`https://auth.example.com/application/o/argos/`
(Authentik 在
`/.well-known/openid-configuration` 处公布发现;仅输入基础 URL)。
- 客户端 ID / 密钥:粘贴。
- 作用域:`openid email profile`
- Cookie 父域:`example.com`
- 保存。点击 *测试连接* 以确认发现。
### 设置:Authelia
1. `configuration.yml` → `identity_providers.oidc.clients`:
- id: argos
secret: "$pbkdf2-sha512$..."
redirect_uris:
- https://argos.example.com/api/auth/oidc/callback
scopes: [openid, email, profile]
grant_types: [authorization_code]
response_types: [code]
authorization_policy: one_factor
2. 重启 Authelia。
3. argos /system → 单点登录:发行者 `https://auth.example.com`,
客户端 ID `argos`,客户端密钥(明文 — Authelia 自行哈希),Cookie 父域 `example.com`。
### 设置:Keycloak
1. 创建 Realm(或重用现有 Realm)。
2. 客户端 → 创建客户端:
- 客户端类型:OpenID Connect
- 客户端 ID:argos
- 客户端认证:启用
- 有效重定向 URI:`https://argos.example.com/api/auth/oidc/callback`
3. 凭据选项卡 → 复制客户端密钥。
4. argos:发行者 `https://keycloak.example.com/realms/`,
客户端 ID `argos`,客户端密钥,Cookie 父域 `example.com`。
### 设置:Google OAuth
1. Google Cloud Console → API 与服务 → 凭据 →
创建凭据 → OAuth客户端 ID → Web 应用程序。
2. 授权重定向 URI:
`https://argos.example.com/api/auth/oidc/callback`
3. 复制客户端 ID + 密钥。
4. argos:发行者 `https://accounts.google.com`,客户端 ID/密钥,
作用域:`openid email profile`,并且**关键**是将 **allowed_domains** 设置为你的组织域名 —— 否则任何使用 Google 登录的 Google 用户都会自动被创建账户。
### 每个主机的 `auth_required` 切换
主机 → 表格行 → **Auth** 列 → 点击 🔓 / 🔒 徽章。该标志会持久化,Caddy 在 1 秒内协调,并且后续对该主机的每个请求都会先经过 `/api/auth/forward` 再到达上游。公共主机保持不变。
启用保护时:
- 未认证请求 → 302 重定向到面板的 `/login`,并携带 `rd=` 参数指向原始 URL。
- 已认证请求 → 200,并携带 `X-Auth-User`、`X-Auth-Email`、`X-Auth-Name`、`X-Auth-Provider` 头部,这些头部会被复制到上游请求(后端可读取它们以个性化响应)。
### 已知限制 / 注意事项
- **需要 Cookie 父域**:对于保护子域是必需的。若未设置,会话 Cookie 仅绑定到面板主机,因此任何不同子域上的受保护主机都无法获得 Cookie 并陷入 302 循环。
- **仅限子域**:每个受保护主机必须是所配置父域的子域。面板不支持“多租户”(即单个面板中配置两个独立的父域);Cookie 规范不允许单个 Cookie 覆盖两个同级域。
- **OIDC 用户绕过本地 TOTP**:在启用 OIDC 账户之前,请确认 IdP 已强制执行 MFA。
- **错误的 `ARGOS_MASTER_KEY` 会阻止面板启动**(VAPID 私钥和 OIDC 客户端密钥都无法解密)。
通过临时禁用 OIDC、清除客户端密钥、更新环境变量、重新保存配置来轮换密钥,以使加密重新生效。
- **用户名冲突:** 如果本地存在 `alice`,而新 OIDC 用户的 `preferred_username` 也是 `alice`,argos 会创建 `alice-oidc`。进一步的冲突会导致错误,提示操作员手动重命名。
### API 接口
- `GET /api/auth/oidc/available` — 公开探测 `{enabled: bool}`。
- `GET /api/auth/oidc/login?rd=` — 302 跳转到 IdP 并启用 PKCE。
- `GET /api/auth/oidc/callback` — 交换并更新会话。
- `GET /api/auth/oidc/status`(需认证) — 脱敏后的配置。
- `PUT /api/auth/oidc/config`(需认证) — 合并并重新验证。
- `POST /api/auth/oidc/test`(需认证) — 仅用于探测发现。
- `GET /api/auth/forward` — Caddy ForwardAuth 端点。
- `GET /api/auth/safe-redirect?rd=` — 防开放重定向的安全 URL。
## 架构
参见 [ARCHITECTURE.md](./ARCHITECTURE.md)。
## 路线图
参见 ARCHITECTURE.md 中的分阶段路线图。当前处于阶段 0。
## 许可证
argos-edge 根据 [商业源码许可证 1.1](LICENSE) 授权。
- **免费用于:** 个人使用、非商业使用、内部业务使用、社区贡献、自托管部署。
- **不允许:** 将 argos-edge 作为托管的商业反向代理、WAF 或应用网关服务提供给第三方。
- **将于 2030-04-20 转为 Apache 2.0 许可证。**
如需商业许可咨询,请打开议题或联系维护者。
标签:Caddy, Caddy 反向代理, Coraza, Coraza WAF, CrowdSec, CrowdSec 社区威胁情报, DNS通配符暴力破解, Edge Computing, EVTX分析, Go, HomeLab, Homelab Gateway, HTTP/3, Let's Encrypt, Load Balancer, React, Ruby工具, Self-hosted Proxy, Self-hosted WAF, SQLite, SSO, SSO 统一认证, Syscalls, Tailwind, TypeScript, WAF, 单面板, 反向代理, 反向代理+WAF+负载均衡, 威胁情报, 安全插件, 家庭实验室, 开发者工具, 开源网关, 日志审计, 生产就绪, 统一控制面板, 自托管, 负载均衡, 边缘网关