cgproxy will transparent proxy anything running in specific cgroup. It resembles with proxychains and tsocks in default setting.
Main feature:
cgroup2
Both cgroup and cgroup2 are enabled in linux by default. So you don't have to do anything about this.
systemd-cgls
to see the cgroup hierarchical tree.TPROXY
A process listening on port (e.g. 12345) to accept iptables TPROXY, for example v2ray's dokodemo-door in tproxy mode.
Iptables
Iptables version should be at least 1.6.0, run iptables --version
to check.
ubuntu 16.04, debian 9, fedora 27 and later are desired
For debian and redhat series, download from Release page
For archlinux series, already in archlinuxcn repo, or see archlinux AUR
Tested on archlinux, fedora 32, ubuntu 18.04, ubuntu 20.04, deepin 15.11, deepin v20 beta
# ready build dir
mkdir build
cd build
# generate
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-Dbuild_execsnoop_dl=ON \
-Dbuild_static=OFF \
..
# compile
make
First enable and start service
sudo systemctl enable --now cgproxy.service
Then prefix with cgproxy with your command, just like proxychains
cgproxy [--debug] <CMD>
For example, test proxy
cgproxy curl -vI https://www.google.com
To completely stop
sudo systemctl disable --now cgproxy.service
Config file: /etc/cgproxy/config.json
{
"port": 12345,
"program_noproxy": ["v2ray", "qv2ray"],
"program_proxy": [],
"cgroup_noproxy": ["/system.slice/v2ray.service"],
"cgroup_proxy": [],
"enable_gateway": false,
"enable_dns": true,
"enable_udp": true,
"enable_tcp": true,
"enable_ipv4": true,
"enable_ipv6": true,
"table": 10007,
"fwmark": 39283
}
port tproxy listenning port
program level proxy control, need execsnoop enabled:
cgroup level proxy control:
/noproxy.slice
is preserved/proxy.slice
is preservedenable_gateway enable gateway proxy for local devices
enable_dns enable dns to go to proxy
enable_tcp
enable_udp
enable_ipv4
enable_ipv6
table, fwmark you can specify iptables and route table related parameter in case conflict.
options priority
program_noproxy > program_proxy > cgroup_noproxy > cgroup_proxy
enable_ipv6 = enable_ipv4 > enable_dns > enable_tcp = enable_udp
command cgproxy and cgnoproxy always have highest priority
Note: cgroup in configuration need to be exist, otherwise ignored
If you changed config, remember to restart service
sudo systemctl restart cgproxy.service
Set "cgroup_proxy":["/"]
in configuration, this will proxy all connection
Allow your proxy program (v2ray) direct to internet to avoid loop. Two ways:
example: cgnoproxy sudo v2ray -config config_file
example: cgnoproxy qv2ray
passive way, persistent config
example: "program_noproxy":["v2ray" ,"qv2ray"]
example: "cgroup_noproxy":["/system.slice/v2ray.service"]
Finally, restart cgproxy service, that's all
"enable_gateway":true
in configurationcgnoproxy
run program wihout proxy, very useful in global transparent proxy
cgnoproxy [--debug] <CMD>
cgnoproxy [--debug] --pid <PID>
For more detail command usage, see man cgproxyd
man cgproxy
man cgnoproxy
v2ray TPROXY need root or special permission, use service or
sudo setcap "cap_net_admin,cap_net_bind_service=ep" /usr/lib/v2ray/v2ray
Why not outbound mark solution, because in v2ray when "localhost"
is used, out-going DNS traffic is not controlled by V2Ray, so no mark at all, that's pity.
systemd-cgls
to see the cgroup hierarchical tree.findmnt -t cgroup2
docker breaks cgroup v2 path match, add kernel parameter cgroup_no_v1=net_cls,net_prio
to resolve, see issue #3 for detail
docker load br_netfilter
module due to hairpin nat, which is not a big deal, see commit.
It enables data link layer packet to go through iptables and only once. However TPROXY do not accept this kind of packets. So to get it working, set following parameter to disable this behavior or unload br_netfilter module manualy. see issue #10 for detail.
sudo sysctl -w net.bridge.bridge-nf-call-iptables=0
sudo sysctl -w net.bridge.bridge-nf-call-ip6tables=0
sudo sysctl -w net.bridge.bridge-nf-call-arptables = 0