13 Commits
v0.01 ... v0.04

Author SHA1 Message Date
fancy
daa68f20ea package deb rpm 2020-04-28 19:58:40 +08:00
fancy
836a34cdc8 also handle gateway dns 2020-04-28 13:49:26 +08:00
fancy
3c21882b88 more compact 2020-04-28 12:17:25 +08:00
fancy
71d924a303 more robust clean whem stop 2020-04-28 03:28:48 +08:00
fancy
5d0b137778 more robust
do not handle local device connection through tproxy if gateway is not enabled
2020-04-28 02:37:36 +08:00
fancy
8a29e88bab update clean iptables 2020-04-27 23:00:25 +08:00
fancy
dd234b08a0 typo fix 2020-04-27 21:50:09 +08:00
fancy
168779ea90 fix #1 2020-04-27 21:29:44 +08:00
fancy
5b65ac0ffd typo fix 2020-04-27 14:49:56 +08:00
fancy
6c77233e1e little fix, and update readme 2020-04-27 14:43:40 +08:00
fancy
6be14b9935 new feature: add gateway support 2020-04-27 00:40:39 +08:00
fancy
c1cd7e6e07 clean stuff 2020-04-26 03:43:18 +08:00
fancy
0848d1ddeb small update 2020-04-26 00:28:10 +08:00
9 changed files with 124 additions and 42 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,3 @@
build
.directory
.vscode
cgproxy2.sh

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.10)
project(cgproxy VERSION 1.0)
project(cgproxy VERSION 3.4)
add_executable(cgattach cgattach.cpp)
install(TARGETS cgattach DESTINATION /usr/bin
@@ -21,3 +21,28 @@ install(FILES cgproxy.conf
DESTINATION /etc/)
install(FILES cgroup-tproxy.sh
DESTINATION /usr/share/cgproxy/scripts/)
## deb pack
set(CPACK_GENERATOR "DEB;RPM")
set(CPACK_PACKAGE_NAME "cgproxy")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "cgproxy will transparent proxy anything running in specific cgroup.It aslo supports global transparent proxy and gateway proxy")
set(CPACK_DEBIAN_PACKAGE_NAME "cgproxy")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "x86_64")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "systemd")
set(CPACK_DEBIAN_PACKAGE_SECTION "network")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "Optional")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/springzfx/cgproxy")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "springzfx@gmail.com")
set(CONTROL_DIR ${CMAKE_SOURCE_DIR}/control)
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CONTROL_DIR}/postinst;${CONTROL_DIR}/prerm")
set(CPACK_RPM_PACKAGE_ARCHITECTURE, "x86_64")
set(CPACK_RPM_PACKAGE_REQUIRES "systemd")
set(CPACK_RPM_PACKAGE_GROUP "network")
set(CPACK_RPM_PACKAGE_URL "https://github.com/springzfx/cgproxy")
set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${CONTROL_DIR}/postinst")
set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE "${CONTROL_DIR}/prerm")
include(CPack)

View File

@@ -11,6 +11,6 @@ else
fi
# test attach success or not
[[ -z "$attached" ]] && echo "config error" && exit 1
[[ -z "$attached" ]] && echo "attach error" && exit 1
exec "$@"

View File

@@ -9,19 +9,22 @@
cgroup_proxy="/proxy.slice"
cgroup_noproxy="/noproxy.slice"
########################################################################
## allow as gateway for local network
enable_gateway=false
########################################################################
## listening port of another proxy process, for example v2ray
port=12345
## if you set to false, it's traffic won't go through proxy, but still can go direct to internet
########################################################################
## if you set to false, it's traffic won't go through proxy, but still can go direct to internet
enable_tcp=true
enable_udp=true
enable_ipv4=true
enable_ipv6=true
enable_dns=true
########################################################################
## do not modify this if you don't known what you are doing
table=100

View File

@@ -11,6 +11,6 @@ else
fi
# test attach success or not
[[ -z "$attached" ]] && echo "config error" && exit 1
[[ -z "$attached" ]] && echo "attach error" && exit 1
exec "$@"

View File

@@ -34,6 +34,9 @@ DOC
cgroup_proxy="/proxy.slice"
cgroup_noproxy="/noproxy.slice"
# allow as gateway for local network
enable_gateway=false
## some variables
port=12345
enable_tcp=true
@@ -60,18 +63,29 @@ for i in "$@"
do
case $i in
stop)
iptables -t mangle -F
iptables -t mangle -D PREROUTING -j TPROXY_PRE
iptables -t mangle -D OUTPUT -j TPROXY_OUT
iptables -t mangle -F TPROXY_PRE
iptables -t mangle -F TPROXY_OUT
iptables -t mangle -F TPROXY_ENT
iptables -t mangle -X TPROXY_PRE
iptables -t mangle -X TPROXY_OUT
ip6tables -t mangle -F
iptables -t mangle -X TPROXY_ENT
ip6tables -t mangle -D PREROUTING -j TPROXY_PRE
ip6tables -t mangle -D OUTPUT -j TPROXY_OUT
ip6tables -t mangle -F TPROXY_PRE
ip6tables -t mangle -F TPROXY_OUT
ip6tables -t mangle -F TPROXY_ENT
ip6tables -t mangle -X TPROXY_PRE
ip6tables -t mangle -X TPROXY_OUT
ip6tables -t mangle -X TPROXY_ENT
ip rule delete fwmark $mark_proxy lookup $table
ip route flush table $table
ip -6 rule delete fwmark $mark_proxy lookup $table
ip -6 route flush table $table
iptables -t nat -A OUTPUT -F
ip6tables -t nat -A OUTPUT -F
## may not exist, just ignore, and tracking their existence is reliable
iptables -t nat -D POSTROUTING -m addrtype ! --src-type LOCAL -j MASQUERADE &> /dev/null
ip6tables -t nat -D POSTROUTING -m addrtype ! --src-type LOCAL -j MASQUERADE &> /dev/null
exit 0
;;
--config=*)
@@ -94,17 +108,24 @@ test -d $cgroup_mount_point$cgroup_noproxy || mkdir $cgroup_mount_point$cgroup_
#ipv4#
ip rule add fwmark $mark_proxy table $table
ip route add local default dev lo table $table
iptables -t mangle -N TPROXY_ENT
iptables -t mangle -A TPROXY_ENT -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port $port --tproxy-mark $mark_proxy
iptables -t mangle -A TPROXY_ENT -p udp -j TPROXY --on-ip 127.0.0.1 --on-port $port --tproxy-mark $mark_proxy
iptables -t mangle -N TPROXY_PRE
iptables -t mangle -A TPROXY_PRE -p udp -m mark --mark $mark_proxy -j TPROXY --on-ip 127.0.0.1 --on-port $port --tproxy-mark $mark_proxy
iptables -t mangle -A TPROXY_PRE -p tcp -m mark --mark $mark_proxy -j TPROXY --on-ip 127.0.0.1 --on-port $port --tproxy-mark $mark_proxy
iptables -t mangle -A TPROXY_PRE -m conntrack --ctstate NEW -j CONNMARK --set-mark $make_newin
iptables -t mangle -A TPROXY_PRE -m conntrack --ctstate NEW -j CONNMARK --restore-mark
iptables -t mangle -A TPROXY_PRE -p udp --dport 53 -j TPROXY_ENT
iptables -t mangle -A TPROXY_PRE -p tcp --dport 53 -j TPROXY_ENT
iptables -t mangle -A TPROXY_PRE -p icmp -j RETURN
iptables -t mangle -A TPROXY_PRE -m addrtype --dst-type LOCAL -j RETURN
iptables -t mangle -A TPROXY_PRE -m pkttype --pkt-type broadcast -j RETURN
iptables -t mangle -A TPROXY_PRE -m pkttype --pkt-type multicast -j RETURN
iptables -t mangle -A TPROXY_PRE -j TPROXY_ENT
iptables -t mangle -A PREROUTING -j TPROXY_PRE
iptables -t mangle -N TPROXY_OUT
iptables -t mangle -A TPROXY_OUT -o lo -j RETURN
iptables -t mangle -A TPROXY_OUT -p icmp -j RETURN
iptables -t mangle -A TPROXY_OUT -m connmark --mark $make_newin -j RETURN # return incoming connection directly, v2ray tproxy not work for this situation, see this: https://github.com/Kr328/ClashForAndroid/issues/146
iptables -t mangle -A TPROXY_OUT -m connmark --mark $make_newin -j RETURN
iptables -t mangle -A TPROXY_OUT -m mark --mark $mark_noproxy -j RETURN
iptables -t mangle -A TPROXY_OUT -m cgroup --path $cgroup_noproxy -j RETURN
iptables -t mangle -A TPROXY_OUT -m cgroup --path $cgroup_proxy -j MARK --set-mark $mark_proxy
@@ -113,11 +134,18 @@ iptables -t mangle -A OUTPUT -j TPROXY_OUT
#ipv6#
ip -6 rule add fwmark $mark_proxy table $table
ip -6 route add local default dev lo table $table
ip6tables -t mangle -N TPROXY_ENT
ip6tables -t mangle -A TPROXY_ENT -p tcp -j TPROXY --on-ip ::1 --on-port $port --tproxy-mark $mark_proxy
ip6tables -t mangle -A TPROXY_ENT -p udp -j TPROXY --on-ip ::1 --on-port $port --tproxy-mark $mark_proxy
ip6tables -t mangle -N TPROXY_PRE
ip6tables -t mangle -A TPROXY_PRE -p udp -m mark --mark $mark_proxy -j TPROXY --on-ip ::1 --on-port $port --tproxy-mark $mark_proxy
ip6tables -t mangle -A TPROXY_PRE -p tcp -m mark --mark $mark_proxy -j TPROXY --on-ip ::1 --on-port $port --tproxy-mark $mark_proxy
ip6tables -t mangle -A TPROXY_PRE -m conntrack --ctstate NEW -j CONNMARK --set-mark $make_newin
ip6tables -t mangle -A TPROXY_PRE -m conntrack --ctstate NEW -j CONNMARK --restore-mark
ip6tables -t mangle -A TPROXY_PRE -p udp --dport 53 -j TPROXY_ENT
ip6tables -t mangle -A TPROXY_PRE -p tcp --dport 53 -j TPROXY_ENT
ip6tables -t mangle -A TPROXY_PRE -p icmp -j RETURN
ip6tables -t mangle -A TPROXY_PRE -m addrtype --dst-type LOCAL -j RETURN
ip6tables -t mangle -A TPROXY_PRE -m pkttype --pkt-type broadcast -j RETURN
ip6tables -t mangle -A TPROXY_PRE -m pkttype --pkt-type multicast -j RETURN
ip6tables -t mangle -A TPROXY_PRE -j TPROXY_ENT
ip6tables -t mangle -A PREROUTING -j TPROXY_PRE
ip6tables -t mangle -N TPROXY_OUT
@@ -129,11 +157,6 @@ ip6tables -t mangle -A TPROXY_OUT -m cgroup --path $cgroup_noproxy -j RETURN
ip6tables -t mangle -A TPROXY_OUT -m cgroup --path $cgroup_proxy -j MARK --set-mark $mark_proxy
ip6tables -t mangle -A OUTPUT -j TPROXY_OUT
## use REDIRECT
# iptables -t nat -A OUTPUT -p tcp -m cgroup --path $cgroup_proxy -j DNAT --to-destination 127.0.0.1:12345
# ip6tables -t nat -A OUTPUT -p tcp -m cgroup --path $cgroup_proxy -j DNAT --to-destination [::1]:12345
## allow to disable, order is important
$enable_dns || iptables -t mangle -I TPROXY_OUT -p udp --dport 53 -j RETURN
$enable_dns || ip6tables -t mangle -I TPROXY_OUT -p udp --dport 53 -j RETURN
@@ -144,19 +167,36 @@ $enable_tcp || ip6tables -t mangle -I TPROXY_OUT -p tcp -j RETURN
$enable_ipv4 || iptables -t mangle -I TPROXY_OUT -j RETURN
$enable_ipv6 || ip6tables -t mangle -I TPROXY_OUT -j RETURN
if $enable_gateway; then
$enable_dns || iptables -t mangle -I TPROXY_PRE -p udp --dport 53 -j RETURN
$enable_dns || ip6tables -t mangle -I TPROXY_PRE -p udp --dport 53 -j RETURN
$enable_udp || iptables -t mangle -I TPROXY_PRE -p udp -j RETURN
$enable_udp || ip6tables -t mangle -I TPROXY_PRE -p udp -j RETURN
$enable_tcp || iptables -t mangle -I TPROXY_PRE -p tcp -j RETURN
$enable_tcp || ip6tables -t mangle -I TPROXY_PRE -p tcp -j RETURN
$enable_ipv4 || iptables -t mangle -I TPROXY_PRE -j RETURN
$enable_ipv6 || ip6tables -t mangle -I TPROXY_PRE -j RETURN
fi
## create proxy prefix command for easy use
# cat << 'DOC' > /usr/bin/cgproxy
# !/usr/bin/bash
# systemd-run -q --slice proxy.slice --scope --user $@
# DOC
# chmod a+x /usr/bin/cgproxy
## do not handle local device connection through tproxy if gateway is not enabled
$enable_gateway || iptables -t mangle -I TPROXY_PRE -m addrtype ! --src-type LOCAL -m addrtype ! --dst-type LOCAL -j RETURN
$enable_gateway || ip6tables -t mangle -I TPROXY_PRE -m addrtype ! --src-type LOCAL -m addrtype ! --dst-type LOCAL -j RETURN
## make sure following rules are the first in chain TPROXY_PRE to mark new incoming connection or gateway proxy connection
## so must put at last to insert first
iptables -t mangle -I TPROXY_PRE -m addrtype ! --src-type LOCAL -m conntrack --ctstate NEW -j CONNMARK --set-mark $make_newin
ip6tables -t mangle -I TPROXY_PRE -m addrtype ! --src-type LOCAL -m conntrack --ctstate NEW -j CONNMARK --set-mark $make_newin
## message for user
cat << DOC
proxied cgroup: $cgroup_proxy
DOC
## tproxy need Root or cap_net_admin capability
# setcap cap_net_admin+ep /usr/lib/v2ray/v2ray
if $enable_gateway; then
iptables -t nat -A POSTROUTING -m addrtype ! --src-type LOCAL -j MASQUERADE
ip6tables -t nat -A POSTROUTING -m addrtype ! --src-type LOCAL -j MASQUERADE
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1
echo "gateway enabled"
fi

2
control/postinst Normal file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
systemctl enable --now cgproxy.service

2
control/prerm Normal file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
systemctl disable --now cgproxy.service

View File

@@ -6,16 +6,17 @@
cgproxy will transparent proxy anything running in specific cgroup. It resembles with *proxychains* and *tsock*, but without their disadvantages, and more powerfull.
It aslo supports global transparent proxy. See [Global transparent proxy](#global-transparent-proxy)
It aslo supports global transparent proxy and gateway proxy. See [Global transparent proxy](#global-transparent-proxy) and [Gateway proxy](#gateway-proxy)
<!--ts-->
* [Transparent Proxy with cgroup v2](#transparent-proxy-with-cgroup-v2)
* [Introduction](#introduction)
* [Prerequest](#prerequest)
* [How to install](#how-to-install)
* [How to use](#how-to-use)
* [Global transparent proxy](#global-transparent-proxy)
* [Gateway proxy](#gateway-proxy)
* [Other useful tools provided in this project](#other-useful-tools-provided-in-this-project)
* [NOTES](#notes)
* [TIPS](#tips)
@@ -29,14 +30,13 @@ It aslo supports global transparent proxy. See [Global transparent proxy](#globa
- cgroup2
Both cgroup and cgroup2 are enable in linux by default. So you don't have to do anything about this.
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.
- Why cgroup v2? Because simple, elegant and intuitive.
- TPROXY
A process listening on port (e.g. 12345) to accept iptables TPROXY, for example v2ray's dokodemo-door in tproxy mode.
- Why not REDIRECT? Because REDIRECT only supports tcp and ipv4.
## How to install
@@ -67,9 +67,12 @@ It is alreay in [archlinux AUR](https://aur.archlinux.org/packages/cgproxy/).
cgproxy curl -vIs https://www.google.com
```
More config in `/etc/cgproxy.conf`:
<details>
<summary>More config in `/etc/cgproxy.conf` (click to expand)</summary>
```bash
# see how to configure
# https://github.com/springzfx/cgproxy
########################################################################
## cgroup transparent proxy
## any process in cgroup_proxy will be proxied, and cgroup_noproxy the opposite
@@ -78,19 +81,22 @@ More config in `/etc/cgproxy.conf`:
cgroup_proxy="/proxy.slice"
cgroup_noproxy="/noproxy.slice"
########################################################################
## allow as gateway for local network
enable_gateway=false
########################################################################
## listening port of another proxy process, for example v2ray
port=12345
## if you set to false, it's traffic won't go through proxy, but still can go direct to internet
########################################################################
## if you set to false, it's traffic won't go through proxy, but still can go direct to internet
enable_tcp=true
enable_udp=true
enable_ipv4=true
enable_ipv6=true
enable_dns=true
########################################################################
## do not modify this if you don't known what you are doing
table=100
@@ -98,7 +104,7 @@ mark_proxy=0x01
mark_noproxy=0xff
mark_newin=0x02
```
</details>
If you changed config, remember to restart service
```bash
@@ -121,6 +127,11 @@ sudo systemctl restart cgproxy.service
- Finally, restart service `sudo systemctl restart cgproxy.service`, that's all
## Gateway proxy
- set **enable_gateway=true** in `/etc/cgproxy.conf` and restart service
- other device set this host as gateway, and set public dns if necessary
## Other useful tools provided in this project
- `cgnoproxy` run program wihout proxy, very useful in global transparent proxy
@@ -149,10 +160,10 @@ sudo systemctl restart cgproxy.service
- `cgattach` attach pid to specific cgroup, and has *suid* bit set by default, be careful to use on multi-user server for securiry. To avoid this situation, you can remove the *suid* bit , then it will fallback to use *sudo*, with *visudo* you can restrict permission or set NOPASSWD for youself.
- v2ray TPROXY need root or special permiassion
- v2ray TPROXY need root or special permission
```bash
sudo setcap "cap_net_bind_service=+ep cap_net_admin=+ep" /usr/lib/v2ray/v2ray
sudo setcap "cap_net_admin,cap_net_bind_service=ep" /usr/lib/v2ray/v2ray
```
## TIPS