From 87bcf050434c52c2149677f4b01b3ae5cfa6366e Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 17 Sep 2026 13:11:52 +0000 Subject: [PATCH] feat(control-center): allow LAN bind with mandatory fixed console token (serve-lan) --- .../02-control-center-design.md | 4 ++-- cmd/control-center/main.go | 23 +++++++++++++++++++ scripts/control-center.sh | 12 +++++++++- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/.doc/system-design/project-control-center/02-control-center-design.md b/.doc/system-design/project-control-center/02-control-center-design.md index bb2cf490..7279d9e6 100644 --- a/.doc/system-design/project-control-center/02-control-center-design.md +++ b/.doc/system-design/project-control-center/02-control-center-design.md @@ -222,9 +222,9 @@ proposal → analysis → design → review → implementation → testing → e | Key | 默认 | 说明 | |-----|------|------| -| `CC_HTTP_ADDR` | `127.0.0.1:8790` | 监听地址 | +| `CC_HTTP_ADDR` | `127.0.0.1:8790` | 监听地址;设为 `0.0.0.0:8790` 或 `scripts/control-center.sh serve-lan` 对外开放 | | `CC_DB_DSN` | `postgres://cc:cc@127.0.0.1:5440/control_center?sslmode=disable` | 独立库 DSN | -| `CC_CONSOLE_TOKEN` | 空(启动时生成临时 token 并打印告警) | console bearer token | +| `CC_CONSOLE_TOKEN` | 空(loopback 时生成临时 token 并打印告警) | console bearer token;**绑定非 loopback 地址时强制要求显式设置固定 token,否则拒绝启动** | | `CC_REPO_ROOT` | `.` | 仓库根(.doc 扫描/git 审查基准) | | `CC_ENV_FILE` | `/.env` | 借用配置来源 | | `CC_MIGRATIONS_DIR` | `/deploy/control-center/goose` | goose 迁移目录 | diff --git a/cmd/control-center/main.go b/cmd/control-center/main.go index e99275b3..e6934cac 100644 --- a/cmd/control-center/main.go +++ b/cmd/control-center/main.go @@ -11,6 +11,7 @@ import ( "flag" "fmt" "log/slog" + "net" "net/http" "os" "os/signal" @@ -112,10 +113,17 @@ func cmdServe(args []string) error { } defer st.Close() + loopback := isLoopbackAddr(cfg.HTTPAddr) if cfg.ConsoleToken == "" { + if !loopback { + return fmt.Errorf("refusing to bind %s without a fixed console token: set CC_CONSOLE_TOKEN", cfg.HTTPAddr) + } cfg.ConsoleToken = randomToken() slog.Warn("CC_CONSOLE_TOKEN not set; generated ephemeral console token") } + if !loopback { + slog.Warn("control-center is reachable from the network; all /api routes require tokens") + } srv := server.New(cfg, st) var emb *embed.HTTPClient @@ -245,3 +253,18 @@ func randomToken() string { } return hex.EncodeToString(b) } + +// isLoopbackAddr reports whether addr ("host:port") binds only to loopback. +func isLoopbackAddr(addr string) bool { + host, _, err := net.SplitHostPort(addr) + if err != nil { + host = addr + } + if host == "" { + return false // ":8790" listens on all interfaces + } + if ip := net.ParseIP(host); ip != nil { + return ip.IsLoopback() + } + return host == "localhost" +} diff --git a/scripts/control-center.sh b/scripts/control-center.sh index ec95b2cd..96f49ed2 100755 --- a/scripts/control-center.sh +++ b/scripts/control-center.sh @@ -17,6 +17,16 @@ case "$cmd" in serve) exec go run ./cmd/control-center serve "$@" ;; + serve-lan) + # Bind all interfaces for LAN/remote access. A fixed console token is + # mandatory (the server refuses otherwise). + export CC_HTTP_ADDR="${CC_HTTP_ADDR:-0.0.0.0:8790}" + if [ -z "${CC_CONSOLE_TOKEN:-}" ]; then + echo "serve-lan requires CC_CONSOLE_TOKEN to be set" >&2 + exit 2 + fi + exec go run ./cmd/control-center serve "$@" + ;; migrate) exec go run ./cmd/control-center migrate "$@" ;; @@ -24,7 +34,7 @@ case "$cmd" in exec go run ./cmd/control-center register-agent "$@" ;; *) - echo "usage: $0 {db-start|db-stop|serve|migrate|register-agent} [args...]" >&2 + echo "usage: $0 {db-start|db-stop|serve|serve-lan|migrate|register-agent} [args...]" >&2 exit 2 ;; esac