Skip to content

feat: add per-Linux-user proxy traffic accounting dashboard - #609

Open
BFlameSwift wants to merge 5 commits into
nelvko:masterfrom
BFlameSwift:feat/traffic-accounting-dashboard
Open

feat: add per-Linux-user proxy traffic accounting dashboard#609
BFlameSwift wants to merge 5 commits into
nelvko:masterfrom
BFlameSwift:feat/traffic-accounting-dashboard

Conversation

@BFlameSwift

Copy link
Copy Markdown

Background

clashctl can manage the Mihomo service, subscriptions, and dashboards, but it cannot currently answer which local Linux users are consuming proxy traffic or how much traffic each user consumes.

This change adds persistent traffic accounting by Linux UID, CLI reporting and export, and a Web dashboard. It combines per-connection byte counters from Mihomo's /connections endpoint with Linux socket ownership information from /proc/net/*.

Changes

  • Add a Python standard-library-only collector backed by SQLite:

    • sample connection byte counters every 5 seconds by default;
    • establish a baseline on the first observation and count only subsequent deltas;
    • handle counter resets, stale connection cleanup, and sampling gaps.
  • Add Linux UID attribution for local proxy clients:

    • read /proc/net/{tcp,tcp6,udp,udp6} once per successful sample;
    • match Mihomo's loopback sourcePort to the client socket's local port;
    • use the UID only when port ownership is unambiguous;
    • fall back for ambiguous, remote, or unresolved connections;
    • never persist ports, inodes, process paths, or raw connection destinations.
  • Define separate identity fields:

    • user_id: a numeric Linux UID, or null when the connection cannot be mapped to a local Linux user;
    • identity_key: a generic attribution key such as uid:<UID>, account:<user>, source-ip:<IP>, or unknown.
  • Add clashctl traffic commands:

    • start, stop, status, and ui;
    • today, top, and live;
    • CSV export with export --since ....
  • Add a loopback-only Web dashboard:

    • total traffic, download/upload ratio, active and tracked identities, and sample count;
    • separate download and upload curves with visible sampling gaps;
    • active connections and an identity traffic ledger;
    • explicit Linux user_id and generic identity_key display;
    • responsive desktop/mobile layouts and security response headers.
  • Integrate collector lifecycle with installation and removal:

    • install scripts/traffic with the rest of clashctl;
    • validate Python 3.10+, the dashboard port, and the sampling interval before startup;
    • verify startup through a protected PID file and /api/health;
    • stop the collector precisely before uninstalling clashctl.
  • Update the README with commands, identity semantics, permissions, SSH tunneling, privacy boundaries, and sampling limitations.

Privacy and security

  • The product dashboard listens on loopback by default.
  • Wildcard Mihomo controller addresses are coerced to loopback for collector access.
  • The browser never receives the Mihomo controller secret or raw connection destinations.
  • SQLite stores only identity information, attribution type, confidence, and byte deltas. It does not store destination domains or IPs, process paths, ports, inodes, traffic contents, or raw controller responses.
  • The state directory, database, and PID file use permissions 700, 600, and 600, respectively.

Accuracy limitations

This feature provides sampled telemetry, not billing-grade accounting:

  • the first observation establishes a baseline only;
  • short-lived connections that complete between samples may be missed;
  • traffic transferred after the final successful sample and before a connection disappears cannot be recovered;
  • traffic during collector downtime or controller failures is not backfilled;
  • non-loopback or ambiguously owned connections fall back to an authenticated account, a positive UID reported by Mihomo, a source IP, or unknown.

Verification

  • PYTHONWARNINGS=error::ResourceWarning python3 -m unittest -q tests/test_traffic.py
  • bash tests/test_traffic_shell.sh
  • python3 -m py_compile scripts/traffic/*.py
  • bash -n scripts/cmd/traffic.sh scripts/preflight.sh uninstall.sh
  • git diff --check
  • 37 Python tests pass.
  • Branch coverage: 83.05% across 627 statements and 134 branches.
  • Sensitive-information scan across 14 changed files: 0 findings.
  • Playwright desktop and mobile verification reports no console errors or page-level horizontal overflow.
  • Live verification attributes the Hugging Face download traffic to Linux UID 1009; the API exposes numeric user_id: 1009 and identity_key: "uid:1009".

@codacy-production

codacy-production Bot commented Aug 10, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 353 complexity · 8 duplication

Metric Results
Complexity 353
Duplication 8

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant