Skip to content

A transparent proxy RULE manager written in go inspired by cgproxy.

License

Notifications You must be signed in to change notification settings

black-desk/cgtproxy

Repository files navigation

cgtproxy

license checks go report card codecov commit activity contributors release date commits since release

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

Quick Start

  1. Install cgtproxy

  2. 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
  3. 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

Usage Tips

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.

How It Works

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.

Why Use cgtproxy?

Common approaches to app-level proxy configuration on Linux have limitations:

  1. Environment Variables:

    • Not elegant to configure
    • Some applications ignore them
  2. Process-Name-Based Routing (e.g., Clash):

    • Uses procfs scanning for new connections
    • Performance issues with many processes
    • Configuration changes require restart
  3. 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.

Comparison with cgproxy

Key differences:

  1. Technology:

  2. Cgroup Handling:

    • cgproxy: Only existing cgroups
    • cgtproxy: Dynamic updates for new cgroups
  3. Process Management:

    • cgproxy: Uses BPF to move processes
    • cgtproxy: Leaves processes in original cgroups
  4. Permissions:

    • cgproxy: Needs CAP_NETWORK_ADMIN and CAP_BPF
    • cgtproxy: Only needs CAP_NETWORK_ADMIN

Check the systemd service file for details.

Documentation

Project Documentation:

Netfilter Documentation:

Development Status

  • 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.

    Clash Clash.Meta MetaCubeX/mihomo is good enough for me.

If you need any feature above, PR is welcome.


Star History Chart