cgtproxy
is a transparent proxy RULE manager written in Go,
inspired by cgproxy.
It makes it easier to set per-app transparent proxy dynamically
by automatically updating your nft ruleset according to your configuration,
redirecting network traffic in each cgroup to a specific target.
Currently supported targets are:
- DIRECT
- DROP
- TPROXY
-
Install cgtproxy
-
Enable and start the systemd service:
# Run this if you have old cgtproxy running as systemd service # systemctl daemon-reload systemctl enable --now cgtproxy.service
Check the nft rules generated with the default configuration:
sudo nft list ruleset
-
Create your own configuration:
- Write your configuration following the configuration guide
- Place it at
/etc/cgtproxy/config.yaml
- Restart the service:
systemctl restart cgtproxy.service
You can create a bash function for convenient process management:
function cgtproxy-exec() {
local slice="cgtproxy-$1.slice"
shift 1
systemd-run --user --slice "$slice" -P "$@"
}
Use it like this:
# Run without proxy
cgtproxy-exec direct /some/command
# Run without network
cgtproxy-exec drop /some/command
# Run with proxy
cgtproxy-exec proxy /some/command
Check the example configuration for details about
cgtproxy-direct.slice
, cgtproxy-drop.slice
,
and cgtproxy-proxy.slice
.
Netfilter can be configured to:
Systemd's XDG integration documentation suggests that XDG applications should be launched in a systemd managed unit. For example, Telegram from Flatpak launched by desktop environment will run in a cgroup like:
/user.slice/user-1000.slice/user@1000.service/app.slice/app-flatpak-org.telegram.desktop@12345.service
This means each application instance's cgroup path follows a pattern
that can be matched by regex.
cgtproxy
monitors cgroupfs changes with inotify
and updates nftable rules when new cgroup hierarchies are created.
Common approaches to app-level proxy configuration on Linux have limitations:
-
Environment Variables:
- Not elegant to configure
- Some applications ignore them
-
Process-Name-Based Routing (e.g., Clash):
- Uses procfs scanning for new connections
- Performance issues with many processes
- Configuration changes require restart
-
TPROXY with cgproxy:
- Only updates iptables for existing cgroups
- Uses BPF for new processes
- Has serious issues:
- Removes processes from original cgroups
- Easy unauthorized cgroup escape
- Breaks systemd's single-writer rule
cgtproxy
provides flexible user-level per-app transparent proxy
without these issues.
Key differences:
-
Technology:
- cgproxy: iptables
- cgtproxy: nftables (differences)
-
Cgroup Handling:
- cgproxy: Only existing cgroups
- cgtproxy: Dynamic updates for new cgroups
-
Process Management:
- cgproxy: Uses BPF to move processes
- cgtproxy: Leaves processes in original cgroups
-
Permissions:
- cgproxy: Needs CAP_NETWORK_ADMIN and CAP_BPF
- cgtproxy: Only needs CAP_NETWORK_ADMIN
Check the systemd service file for details.
Project Documentation:
Netfilter Documentation:
-
optional cgroup monitor implementation listening on D-Bus instead of filesystem;notify makes the filesystem monitor much more stable, there is no need to implement another monitor for my person usage.
-
DNS hijack for fake-ip;
-
ipv4;
-
ipv6;I don't have any ipv6 only device, so I don't need this feature.
-
-
builtin TPROXY server.ClashClash.MetaMetaCubeX/mihomo is good enough for me.
If you need any feature above, PR is welcome.