NetCenter is a Linux desktop network-control project. It combines a privileged system daemon, a GTK4/Libadwaita UI, and a CLI to manage bandwidth limits for the active network connection.
The current focus is reliable traffic limiting plus a first outbound firewall MVP backed by nftables.
NetCenter is usable as an advanced prototype, not as a distribution-ready network manager. It changes kernel traffic-control state and should be tested from a local desktop session, not over a remote-only connection.
Implemented and manually verified:
- global upload limits
- global download limits
- per-application upload limits for supported cgroup-backed applications
- per-application download limits with the eBPF-assisted backend
- coexistence of global download and per-application download limits
- application discovery from
/proc, cgroups, sockets, and desktop metadata - live application traffic graphs in the UI
- persistent rules restored after daemon restart
- default-route/interface changes, including tested VPN scenarios
- cleanup of NetCenter-owned traffic-control and BPF state
- diagnostics view and
netcenterctl doctor - backend selection:
auto,ebpf, orlegacy - pause/resume of all enforcement, including optional pause when closing the UI
- installed systemd service, D-Bus policy, polkit policy, desktop file, and icon
- firewall UI with protocol selection (TCP, UDP, Both, ICMP, ICMPv6, Any), safety confirmations, and persisted rules
- global and per-application firewall rules for outbound, inbound, or both directions enforced via nftables
- background DNS refresh for hostname firewall rules with visible stale status
- live per-rule hit counters (packets/bytes) in the firewall monitor
- live rule-match activity feed (
netcenterctl firewall eventsand UI monitor) - eBPF socket-layer firewall backend (
netcenterctl firewall backend bpf;autoprefers it whennetcenter_firewall.bpf.ois installed โ built withjust build-bpf-firewall) - firewall diagnostics in
netcenterctl doctorand firewall management vianetcenterctl firewall
Not implemented yet:
- persistent firewall connection event history across daemon restarts
- stable packaged release workflow
NetCenter uses normal Linux kernel facilities:
tc, CAKE, HTB, IFB, and ingress redirect for shaping- nftables cgroup marking for application upload classification
- an eBPF socket/action backend for stable application download classification
- D-Bus on the system bus for UI/CLI to daemon communication
- polkit for privileged rule changes
Application download limiting has two backends:
ebpf: preferred backend. Marks sockets by cgroup and classifies packets in the IFB redirect path before shaping.legacy: compatibility fallback using reactive flower filters.auto: default. Tries eBPF first and falls back to legacy when unavailable.
The legacy backend is useful as a fallback, but it is less stable for modern high-churn traffic such as Steam downloads and QUIC/UDP-heavy clients.
Global upload shaping and per-application upload shaping are currently mutually exclusive because both need ownership of the default interface root qdisc. Global download shaping can run together with per-application download shaping under the shared IFB/HTB hierarchy.
| Path | Purpose |
|---|---|
crates/netcenter-core |
Pure domain types, parsing, formatting, diagnostics helpers |
crates/netcenter-system |
Shared Linux runtime helpers, currently cleanup logic |
crates/netcenterd |
Privileged daemon, persistence, D-Bus, enforcement |
crates/netcenterctl |
CLI diagnostics and administrative operations |
crates/netcenter-ui |
GTK4/Libadwaita desktop UI |
bpf/ |
eBPF source for download socket marking |
packaging/ |
systemd service, D-Bus policy, polkit policy, desktop entry, icon |
docs/ |
architecture, smoke tests, verification matrix, firewall plan |
Build/runtime tools:
- Rust toolchain
justclangwith BPF target supportllvm-objdumptcandipfrom iproute2nftbpftool- systemd, D-Bus, polkit
- GTK4 and Libadwaita development/runtime packages
Useful checks:
just build-bpf-mark
cargo check --workspace
cargo test --workspace
sudo ./target/debug/netcenterctl doctor capabilitiesInstall runtime files from a normal user shell. Do not run the recipe itself via
sudo; it elevates only the installation steps internally.
just install-runtime-files
sudo systemctl enable --now netcenterdThe recipe:
- builds the BPF object
- builds release binaries for daemon, CLI, and UI
- installs
netcenterd,netcenterctl, andnetcenter-ui - installs
/usr/lib/netcenter/netcenter_mark.bpf.o - installs the systemd unit
- installs D-Bus and polkit policy files
- installs the desktop entry and icon
The installed service defaults to:
NETCENTER_DOWNLOAD_BACKEND=auto
NETCENTER_BPF_OBJECT=/usr/lib/netcenter/netcenter_mark.bpf.o
Start the UI from the app launcher or directly:
netcenter-uiCommon checks:
just check
just test
just lint
just build-bpf-markRun the development daemon in the foreground:
just install-dev-policy
just run-daemon-devRun the UI:
just run-uiRun the CLI:
just run-ctl status
just run-ctl applications
just run-ctl doctor
just run-ctl doctor --verbose
just run-ctl doctor capabilitiesExamples for global rules:
just run-ctl rules list
just run-ctl rules set-global-download "25 Mbit/s"
just run-ctl rules clear-global-download
just run-ctl rules set-global-upload "5 Mbit/s"
just run-ctl rules clear-global-uploadIf development traffic-control state gets stuck, remove only NetCenter-owned artifacts:
sudo ./target/debug/netcenterctl doctor cleanup-netcenterEquivalent manual daemon start without just run-daemon-dev:
just build-bpf-mark
cargo build -p netcenterd -p netcenterctl -p netcenter-ui
sudo env \
NETCENTER_STATE_DIR=/var/tmp/netcenter-dev \
NETCENTER_DOWNLOAD_BACKEND=auto \
NETCENTER_BPF_OBJECT=target/bpf/netcenter_mark.bpf.o \
./target/debug/netcenterdImportant daemon environment variables:
| Variable | Values / Example | Meaning |
|---|---|---|
NETCENTER_DOWNLOAD_BACKEND |
auto, ebpf, legacy |
Select application download backend |
NETCENTER_BPF_OBJECT |
/usr/lib/netcenter/netcenter_mark.bpf.o |
BPF object path |
NETCENTER_STATE_DIR |
/var/lib/netcenter |
Directory for daemon state |
NETCENTER_BPF_PIN_DIR |
/sys/fs/bpf/netcenter |
BPF pin directory |
NETCENTER_BPF_CGROUP_ROOT |
/sys/fs/cgroup |
cgroup root used by BPF attachment |
The old NETCENTER_EXPERIMENTAL_BPF_DOWNLOAD=1 switch is kept as a
compatibility alias for requiring the eBPF backend.
netcenterctl status
netcenterctl applications
netcenterctl rules list
netcenterctl rules set-global-download "25 Mbit/s"
netcenterctl rules clear-global-download
netcenterctl rules set-global-upload "5 Mbit/s"
netcenterctl rules clear-global-upload
netcenterctl doctor
netcenterctl doctor --verbose
netcenterctl doctor capabilities
netcenterctl doctor cleanup-netcenterApplication rules are currently managed through the UI.
The UI currently provides:
- global upload/download limit controls
- application list with per-app upload/download limit popovers
- enable/disable/remove behavior for saved app rules
- live network graph drawer
- settings for exit behavior, backend selection, restart/apply, diagnostics, and cleanup
- pause/resume banner when enforcement is paused
- firewall tab supporting outbound, inbound, and both-direction rules for TCP, UDP, ICMP, ICMPv6, and Any (global and per-application targets)
- live rule hit counters, rule-match activity feed, and hostname refresh status in the firewall monitor
The firewall tab does not show simulated live events. Use the built-in rule
counters, netcenterctl firewall status, netcenterctl doctor --verbose, and
nft list table inet netcenter_firewall to inspect enforcement.
Relevant documentation:
- manual smoke tests
- manual download limit tests
- network verification matrix
- eBPF download backend notes
- crash recovery test
Standard developer gate:
cargo fmt --all -- --check
git diff --check
cargo check --workspace
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warningsThe firewall implementation plan is documented in docs/firewall-implementation-plan.md.
The intended direction is:
- move the firewall domain model into
netcenter-core - add daemon persistence and D-Bus API without enforcement
- connect the UI to persisted daemon rules
- add an nftables dry-run planner
- add enforcement using a NetCenter-owned
inet netcenter_firewalltable - add ICMP/ICMPv6/Any support
- add diagnostics, cleanup, doctor output, and CLI commands
Implemented CLI examples:
netcenterctl firewall list
netcenterctl firewall status
netcenterctl firewall add --target global --action block --protocol udp --host 8.8.8.8 --port 53
netcenterctl firewall add --app "Google Chrome" --action block --protocol icmp --host 8.8.8.8
netcenterctl firewall enable-enforcement
netcenterctl firewall disable-enforcement
netcenterctl firewall events
netcenterctl firewall remove <rule-id>
netcenterctl firewall enable <rule-id>
netcenterctl firewall disable <rule-id>
netcenterctl firewall preview- architecture
- implementation roadmap
- refactoring verification
- refactor follow-up plan
- firewall implementation plan
The older broad product plan remains in PLAN_REVIEWED_V3.md.
- Do not test over a remote-only network session.
- Cleanup removes only NetCenter-owned artifacts, but always inspect doctor output before and after kernel-facing changes.
- Global upload and per-application upload cannot be active at the same time.
- The eBPF backend needs kernel/BPF support; use
doctor capabilitiesto inspect host support. - Firewall rules for global targets enforce outbound, inbound, and both directions. Per-application firewall rules are outbound-only because inbound traffic cannot be attributed to an application reliably.
- Hostname firewall rules are resolved when applied and refreshed in the
background every ~5 minutes. If a refresh fails, the rule stays enforced on
the last known addresses and is reported as stale in the UI,
doctor, and diagnostics.
NetCenter is licensed under GPL-3.0-or-later. See LICENSE.