Commit Graph
98 Commits
Author SHA1 Message Date
Sam5440andnaiba/CloudCode 8721a15b12 feat(server): online session history with configurable stats window (#1243)
Add persisted online sessions, configurable retention and online history statistics with lifecycle, recovery, timezone and concurrency regression coverage.

Co-authored-by: naiba/CloudCode <hi+cloudcode@nai.ba>
2026-10-16 19:25:13 +08:00
naiba 1420dd450c fix(nat): bound dashboard credential classification 2026-10-01 11:48:23 +00:00
xvkong233 3ad985f36e fix(nat): scrub dashboard-issued credentials from all accepted token channels
The initial selective strip covered only the Authorization header, but the
dashboard also accepts its JWT via the ?token= query parameter and the
nz-jwt cookie (jwt.go TokenLookup channels). A dashboard credential arriving
through those channels would still reach a NAT backend.

Apply the same classify-then-strip rule to all three channels at NAT
ingress: values verified as dashboard-issued are removed, foreign values
are preserved byte-for-byte. Adds a ServeNAT flow test exercising the live
classifier and a wiring test pinning the gate injection in main().
2026-10-01 11:17:45 +00:00
xvkong233 40240ed02b fix(nat): strip only dashboard-issued Authorization credentials at NAT ingress
Since 2640b86 (v2.2.11, 2026-07-20) the NAT ingress deleted the entire
Authorization header, breaking self-hosted apps behind the tunnel that
authenticate with their own Bearer tokens (e.g. the Qinglong panel login
loop).

Strip only credentials issued by this dashboard and forward foreign ones:

- controller.IsDashboardCredential classifies an Authorization value as
  dashboard-issued via a signature-only JWT parser derived from the auth
  middleware (same key, HS256 pinned, claims validation deliberately
  skipped so an expired panel token is still recognized and kept out of
  the tunnel) or an api_tokens lookup for PAT-shaped values. Unknown PATs,
  foreign signatures, other schemes and missing values pass through. When
  classification cannot complete (parser not ready, DB nil or error) the
  verdict fails closed (strip) and the log carries a fixed reason only,
  never credential content.
- Both NAT capability variants (default, and agent-compat legacy /
  invalid-capability / post-consume paths) replace the unconditional
  Del("Authorization") with stripDashboardCredential. The rpc package
  receives the classifier through SetNATDashboardCredentialGate, the same
  injection pattern as SetMCPKillSwitchObserver; an unwired gate keeps the
  historical strip-everything behavior.

Tests: controller classification semantics (panel JWT, expired panel JWT
and panel PAT stripped; foreign-signed JWT, unknown nzp_ token, random
strings, non-Bearer schemes and missing header pass through; parser
unavailable, DB nil and DB error fail closed with credential-free logs)
plus rpc unit and flow coverage for both variants (dashboard credentials
never reach the forwarded bytes; foreign and missing Authorization are
forwarded untouched).

Compatibility: no API, database or frontend changes; NAT backends that do
not use Authorization behave exactly as before.
2026-10-01 11:17:45 +00:00
naiba 38824dbc11 fix(security): restrict service monitors to probe tasks 2026-08-15 05:00:28 +00:00
naibaandnaiba/CloudCode aee586baad feat(agentcompat): add dashboard listener hooks
Co-authored-by: naiba/CloudCode <hi+cloudcode@nai.ba>
2026-07-20 04:33:38 +00:00
naibaandcloudcode e8dabf5bc6 feat(auth): add PAT auth, scoped REST/MCP access, CSRF, and tenant isolation
Introduce Personal Access Tokens (nzp_*) as a stateless auth path alongside
JWT, gated per-endpoint by a scope middleware (nezha:{resource}:{verb}) with
fail-closed empty-scope defaults and a server-id whitelist. Self-management
endpoints (profile, api-tokens, oauth2 bind, refresh-token) explicitly reject
PATs to block privilege-escalation chains. A revoke registry tears down active
long-lived connections (terminal, fm, ws, transfer, mcp) the moment a PAT is
deleted, with a tombstone closing the revoke->register race.

Add an MCP endpoint that proxies tool calls (exec, fs read/write/delete,
transfer) to agents over gRPC, guarded by origin/DNS-rebinding checks, a
per-token rate limiter, audit logging, and a kill switch. Serialize all
sends through the IOStream wrapper to honour grpc-go's concurrency contract.

Add CSRF double-submit protection on unsafe cookie-authenticated methods,
exempting authenticated PAT requests by context identity (not a forgeable
Authorization header). Apply visibility/whitelist filtering consistently
across list, get-by-id, and mutate paths to enforce tenant isolation.

Migrate legacy mcp:* scopes: rewrite read/exec to nezha:* equivalents and
drop dangerous write/delete/wildcard grants.

Co-authored-by: cloudcode <cloudcode@users.noreply.github.com>
2026-05-30 15:56:44 +00:00
naibaandcloudcode e05700c2f0 feat(jwt): server-side session table with keyId + obfuscated uid claims
Replace the {user_id, ip} claim pair with {keyId, uid}:
- keyId is a 32-byte random id that points to a row in the new
  jwt_sessions table holding the real user id, bound IP, UA hash,
  TokenVersion and expiry.
- uid is the user id encoded through pkg/idcodec; mismatch between
  claim uid and session.UserID trips WAF block on the caller IP.
- identityHandler now rejects unknown/revoked/expired sessions, IP
  drift and stale TokenVersion. Refresh updates session.ExpiresAt.

User.TokenVersion bumps on password change and revokes outstanding
sessions, so a leaked JWT secret alone is no longer enough to forge
a token. JWTSession rows are GC'd every 10 minutes (expired + grace
or revoked >24h). OAuth2 callback shares the same issue path.

Includes regression tests for happy path, mismatched claim uid,
revoked session, TokenVersion bump, IP drift and unknown keyId.

Co-authored-by: cloudcode <cloudcode@users.noreply.github.com>
2026-05-26 03:51:05 +00:00
3d0c9b963c feat(v2.0.0): tsdb (#1162)
* feat: tsdb

* fix(ci): remove --parseGoList=false from swag init to fix dependency resolution

* fix(ci): fix swag init directory and temporary remove s390x support due to cgo issues

* fix(ci): fix swag init output directory to cmd/dashboard/docs

* fix(ci): set GOTOOLCHAIN=auto for gosec

* feat: add system storage maintenance for SQLite and TSDB

* shit

* feat: add s390x support and improve service monitoring

* ci: upgrade goreleaser-cross image to v1.25

* ci: add libzstd-dev:s390x for cross-compilation

* ci: build libzstd for s390x from source

* ci: add libzstd_linux_s390x.go for gozstd linking

* ci: use vendor mode for s390x gozstd build

* ci: clone zstd source for s390x build

* refactor(tsdb): rename MaxDiskUsageGB to MinFreeDiskSpaceGB and optimize queries

- Rename config to accurately reflect VictoriaMetrics behavior: minimum free disk space threshold
- Add QueryServiceHistoryByServerID for batch query optimization
- Fix hasStatus to avoid false status counting when only delay data exists
- Fix service aggregation boundary: use successCount*2 >= count
- Fix serviceID parsing with strconv.ParseUint error handling
- Add TagFiltersCacheSize for better query performance

* feat(api): add server metrics endpoint and simplify service history response

- Add /server/:id/metrics API for querying TSDB server metrics
- Simplify getServiceHistory by removing redundant data conversion
- Change AvgDelay type from float32 to float64
- Remove generated swagger docs (to be regenerated)
- Update TSDB query, writer and tests

* chore: 临时禁用不支持前端

* ci: cache zstd build for s390x to speed up CI

* fix(tsdb): fix race conditions, data correctness and optimize performance

- Fix TOCTOU race between IsClosed() and write/query by holding RLock
- Fix delay=0 excluded from stats by using hasDelay flag instead of value > 0
- Fix fmt.Sscanf -> strconv.ParseUint for server_id parsing with error logging
- Fix buffer unbounded growth by flushing inside lock when over maxSize
- Split makeMetricRow into makeServerMetricRow/makeServiceMetricRow
- Extract InitGlobalSettings() from Open() for VictoriaMetrics globals
- Remove redundant instance/GetInstance/SetInstance singleton
- Add error logging for silently skipped block decode errors
- Optimize WriteBatch* to build all rows in single write call
- Optimize downsample to use linear scan instead of map for sorted data
- Optimize query slice reuse across block iterations

* 服务添加DisplayIndex (#1166)

* 服务添加DisplayIndex

* 根据ai建议修改

---------

Co-authored-by: huYang <306061454@qq.com>

* fix(tsdb): restore SQLite fallback and monthly status reload on restart

- Restore ServiceHistory model and SQLite write fallback when TSDB is disabled
- Reload monthlyStatus (30-day) and serviceStatusToday from TSDB/SQLite on startup
- Add SQLite fallback query for /service/:id/history and /server/:id/service
- Remove breaking GET /service/:id endpoint, keep /service/:id/history only
- Add QueryServiceDailyStats to TSDB for per-day aggregation
- Add tests for monthly status and today stats loading from both TSDB and SQLite
- Migrate ServiceHistory table only when TSDB is disabled

* ci: exclude false-positive gosec rules G117, G703, G704

* feat(api): expose tsdb_enabled in setting response

* ci: restore G115 exclusion accidentally dropped in previous commit

* fix: update version numbers for OfficialAdmin and Official templates

* chore: upgrade frontend

* chore: upgrade frontend

---------

Co-authored-by: 胡说丷刂 <34758853+laosan-xx@users.noreply.github.com>
Co-authored-by: huYang <306061454@qq.com>
2026-02-15 13:13:33 +08:00
UUBulb 227a6a0cb3 fix search by id (#1047)
* fix search by id

* make SearchByID Public
2025-03-27 19:17:00 +08:00
UUBulb f34b263b69 improve transfer record logic (#1033)
* improve transfer record logic

* refactor

* modernize loops

* remove unused type conversions

* update dependencies

* script: keep .gitkeep files

* fix

* remove clear
2025-03-19 22:21:21 +08:00
UUBulb d0f69c424e generate agent_secret for old users (#1021) 2025-03-08 18:47:42 +08:00
UUBulb af55fae652 improve check for offline rules (#1013)
* improve check for offline rules

* bug fixes

* update dependencies

* fix error wrap

* fix offline check

* improve readability
2025-03-02 15:37:21 +08:00
UUBulb 043d6c4097 feat: update to go1.24 & support listening https (#1002)
* feat: support listening https

* refactor

* modernize

* support snake case in config

* more precise control of config fields

* update goreleaser config

* remove kubeyaml

* fix: expose agent_secret

* chore
2025-02-28 22:02:54 +08:00
UUBulb ea068d4db1 refactor: simplify server & service manipulation (#993)
* refactor: simplify server & service manipulation

* update

* fix

* update for nat, ddns & notification

* chore

* update cron

* update dependencies

* use of function iterators

* update default dns servers
2025-02-21 23:08:12 +08:00
naiba 22d7a88318 feat: disable nat 2025-01-21 22:23:15 +08:00
igophperandigophper 3f89f6a4c8 fix: fix typo in database variable name (#939)
Co-authored-by: igophper <jianghanghui@k.app>
2025-01-03 22:39:55 +08:00
Moraxyc 67190459f8 Refactor: Load UserTemplates from embedded yaml file (#575)
* Refactor: Load UserTemplates from embedded yaml file

* feat: add version field to UserTemplates

* refactor: use shell script to fetch frontends

* chore: add *-dist to .gitignore

* refactor: rename to FrontendTemplates

BREAKING CHANGE: This commit changes the `user_templates` filed
in the communication json between backend and the admin-frontend.

Keep user config.yml `user_template` filed.
2024-12-10 21:57:20 +08:00
naiba 29d0d2eb3c feat: 优化 GeoIP 更新逻辑 2024-12-07 11:06:42 +08:00
naiba 55a867d077 feat: v1.1 2024-12-07 01:18:34 +08:00
Moraxyc 5a706b05c7 feat: add listen_host (#550) 2024-12-05 17:01:21 +08:00
naiba 4861b3e013 feat: refactor grpc keepalive 2024-12-05 00:11:34 +08:00
naiba b59094fd19 Revert "feat: grpc keepalive"
This reverts commit b484fe53f0.
2024-12-04 22:46:02 +08:00
naiba 30df69d72d feat: grpc keepalive 2024-12-04 21:08:28 +08:00
naiba 9ba3a4fb2b feat: embed dist 2024-11-29 21:31:39 +08:00
naiba a7e4fe0909 rename repo 2024-11-28 19:38:54 +08:00
naiba 5846c682d3 refactor: replace pflag with standard flag package in main.go 2024-11-25 22:03:11 +08:00
UUBulb 35126fa700 allow cors from loopback addresses in debug mode (#9) 2024-11-18 13:26:41 +08:00
uubulb 1c308929ee merge upstream, improve geoip pkg 2024-10-31 03:34:25 +08:00
Moraxyc b6d9038a11 fix(cli): display version before init app (#463) 2024-10-31 00:15:41 +08:00
naiba 868c242eb3 refactor: rename monitor -> service 2024-10-25 00:13:45 +08:00
naiba fa14043cbe refactor nat 2024-10-23 20:37:29 +08:00
UUBulb 1eaf70782a add path check for multiplexer (#451) 2024-10-23 12:55:10 +08:00
naiba 6615505ab9 fix ci 2024-10-23 00:03:19 +08:00
naiba c5bacf3e84 fix agent connect 2024-10-22 23:44:50 +08:00
naiba 71891b2d61 refactor: login & refresh token 2024-10-20 14:05:43 +08:00
naiba 56d3936797 refactor graceful shutdown 2024-10-20 11:50:02 +08:00
naiba 542f06551e refactor: remove pages, combine grpc http port 2024-10-20 11:47:45 +08:00
naiba 8849cb51e6 init jwt 2024-10-20 00:09:16 +08:00
naiba 37c87bbc07 🎉 init swaggo 2024-10-19 23:14:53 +08:00
UUBulb 8424c4e756 [ci][docker]: use matrix to reduce build time & change base image to busybox (#417)
* ci: use matrix to reduce build time

* docker: change base image to busybox

* reuse workflows

* only download ipinfo db on tag pushes

* goreleaser
2024-09-02 22:13:13 +08:00
naiba 322132c26b feat: 在面板重启时通知agent更新信息 2024-08-02 19:41:39 +08:00
naiba 2a35a6f0e5 feat: 去除 webTerminal 的 websocket 依赖 2024-07-14 12:47:36 +08:00
卖女孩的小火柴 5ab46b9ebb Feat: Add some parameters (#294) 2023-11-02 21:06:34 +08:00
naiba 360d30681e 🐛 fix service stats 2022-10-12 23:06:25 +08:00
naiba 53b6b9fcea 🌐 localization [skip ci] 2022-04-27 23:51:45 +08:00
Akkia 09d3607cee refactor: 优化代码组织结构 2022-04-12 13:16:33 +08:00
Akkia b648550595 optimize: 移除两处冗余的代码 (初始化后未使用|重复初始化) 2022-04-12 00:01:38 +08:00
Akkia 9776cf6182 添加代码注释+修正一个typo 2022-04-11 22:51:02 +08:00
naiba 83e4e2a195 🐛 修复 Windows time.LoadLocation 2022-03-18 23:57:30 +08:00