13 Commits
v0.06 ... v0.08

Author SHA1 Message Date
fancy
2838ffbb70 bump version 2020-05-14 14:28:08 +08:00
fancy
749fe38ca8 add local aur build 2020-05-14 14:21:40 +08:00
fancy
c0668fd8d2 use macro 2020-05-14 13:57:39 +08:00
fancy
06ae0b9fc5 update readme 2020-05-14 12:07:12 +08:00
fancy
4e04dcf84a update readme 2020-05-14 04:53:23 +08:00
fancy
c0e9ea24c1 allow array input for cgroup_proxy and cgroup_noproxy 2020-05-14 04:47:29 +08:00
fancy
f8e0abbb55 check root, and check iptables before clean 2020-05-13 23:42:05 +08:00
fancy
6c24c68831 only masquerade ipv6 private address 2020-05-08 11:47:51 +08:00
fancy
d3b2dc0465 small fix 2020-05-07 00:22:08 +08:00
fancy
4be7be2083 example: rename to keep order 2020-05-06 02:42:44 +08:00
fancy
25f94968ae install readme.md to doc 2020-05-05 20:14:26 +08:00
fancy
3b4b67df33 small change 2020-05-05 19:30:35 +08:00
fancy
31ae519193 v2ray.service without root 2020-05-05 00:32:09 +08:00
22 changed files with 162 additions and 69 deletions

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(cgproxy VERSION 3.6) project(cgproxy VERSION 3.8)
add_executable(cgattach cgattach.cpp) add_executable(cgattach cgattach.cpp)
install(TARGETS cgattach DESTINATION /usr/bin install(TARGETS cgattach DESTINATION /usr/bin
@@ -21,6 +21,9 @@ install(FILES cgproxy.conf
DESTINATION /etc/) DESTINATION /etc/)
install(FILES cgroup-tproxy.sh install(FILES cgroup-tproxy.sh
DESTINATION /usr/share/cgproxy/scripts/) DESTINATION /usr/share/cgproxy/scripts/)
install(FILES readme.md
DESTINATION /share/doc/cgproxy/)
## package for deb and rpm ## package for deb and rpm

View File

@@ -0,0 +1,40 @@
# Maintainer: Fancy Zhang <springzfx@gmail.com>
pkgname=cgproxy-git
pkgver=v3.8.r1.gc0668fd
pkgrel=1
pkgdesc="A transparent proxy program with cgroup2, like proxychains"
arch=('x86_64')
url="https://github.com/springzfx/cgproxy"
license=('')
groups=('')
makedepends=('cmake')
depends=('systemd')
provides=('cgproxy')
conflicts=('cgproxy')
curr_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source=("${pkgname}::git+file://${curr_dir}/../.git")
# source=("${pkgname}::git+file:///home/fancy/workspace/cgproxy/.git")
md5sums=('SKIP')
pkgver() {
cd "$pkgname"
( set -o pipefail
git describe --long --tags 2>/dev/null | sed 's/\([^-]*-g\)/r\1/;s/-/./g' ||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
)
}
backup=('etc/cgproxy.conf')
install="cgproxy.install"
build(){
cd "$pkgname"
mkdir -p build && cd build && cmake .. && make
}
package_cgproxy-git(){
cd "$pkgname"/build
make DESTDIR=$pkgdir install
}

View File

@@ -0,0 +1,8 @@
#!/bin/sh
post_install(){
cat <<'DOC'
to start service:
systemctl enable --now cgproxy.service
DOC
}

View File

@@ -10,6 +10,10 @@
#include <unistd.h> #include <unistd.h>
using namespace std; using namespace std;
#define error(...) {fprintf(stderr, __VA_ARGS__);fprintf(stderr, "\n");}
#define debug(...) {fprintf(stdout, __VA_ARGS__);fprintf(stdout, "\n");}
void print_usage() { fprintf(stdout, "usage: cgattach <pid> <cgroup>\n"); } void print_usage() { fprintf(stdout, "usage: cgattach <pid> <cgroup>\n"); }
bool exist(string path) { bool exist(string path) {
@@ -26,7 +30,7 @@ bool validate(string pid, string cgroup) {
if (pid_v && cg_v) if (pid_v && cg_v)
return true; return true;
fprintf(stderr, "paramater validate error\n"); error("paramater validate error");
print_usage(); print_usage();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -37,22 +41,21 @@ string get_cgroup2_mount_point(){
int count=fscanf(fp,"%s",&cgroup2_mount_point); int count=fscanf(fp,"%s",&cgroup2_mount_point);
fclose(fp); fclose(fp);
if (count=0){ if (count=0){
fprintf(stderr, "cgroup2 not supported\n"); error("cgroup2 not supported");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
return cgroup2_mount_point; return cgroup2_mount_point;
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
setuid(0); int flag=setuid(0);
setgid(0); if (flag!=0) {
if (getuid() != 0 || getgid() != 0) { perror("cgattach setuid");
fprintf(stderr, "cgattach need suid sticky bit or run with root\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (argc != 3) { if (argc != 3) {
fprintf(stderr, "only need 2 paramaters\n"); error("only need 2 paramaters");
print_usage(); print_usage();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -69,20 +72,19 @@ int main(int argc, char *argv[]) {
if (!exist(cgroup_target_path)) { if (!exist(cgroup_target_path)) {
if (mkdir(cgroup_target_path.c_str(), if (mkdir(cgroup_target_path.c_str(),
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) { S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) {
fprintf(stdout, "created cgroup %s success\n", cgroup_target.c_str()); debug("created cgroup %s success", cgroup_target.c_str());
} else { } else {
fprintf(stderr, "created cgroup %s failed, errno %d\n", error("created cgroup %s failed, errno %d", cgroup_target.c_str(), errno);
cgroup_target.c_str(), errno);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// fprintf(stderr, "cgroup %s not exist\n",cgroup_target.c_str()); // error("cgroup %s not exist",cgroup_target.c_str());
// exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} }
// put pid to target cgroup // put pid to target cgroup
ofstream procs(cgroup_target_procs, ofstream::app); ofstream procs(cgroup_target_procs, ofstream::app);
if (!procs.is_open()) { if (!procs.is_open()) {
fprintf(stderr, "open file %s failed\n", cgroup_target_procs.c_str()); error("open file %s failed", cgroup_target_procs.c_str());
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
procs << pid.c_str() << endl; procs << pid.c_str() << endl;
@@ -90,7 +92,7 @@ int main(int argc, char *argv[]) {
// maybe there some write error, for example process pid may not exist // maybe there some write error, for example process pid may not exist
if (!procs) { if (!procs) {
fprintf(stderr, "write %s to %s failed, maybe process %s not exist\n", error("write %s to %s failed, maybe process %s not exist",
pid.c_str(), cgroup_target_procs.c_str(), pid.c_str()); pid.c_str(), cgroup_target_procs.c_str(), pid.c_str());
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@@ -1,32 +1,47 @@
# see how to configure
# https://github.com/springzfx/cgproxy
########################################################################
## cgroup transparent proxy ## cgroup transparent proxy
## see how to configure, https://github.com/springzfx/cgproxy
###################################################################################
## any process in cgroup_proxy will be proxied, and cgroup_noproxy the opposite ## any process in cgroup_proxy will be proxied, and cgroup_noproxy the opposite
## cgroup must start with slash '/' ## note, cgroup must start with slash '/'
## the value can be string or bash array
## for array, only the first element will be created if not exist
## and the rest elements will not, so won't be applied
### global proxy with v2ray service
# cgroup_proxy="/" # cgroup_proxy="/"
# cgroup_noproxy=("/noproxy.slice" "/system.slice/v2ray.service")
### global proxy with manual `cgnoporxy qv2ray`
# cgroup_proxy="/"
# cgroup_noproxy="/noproxy.slice"
### default
cgroup_proxy="/proxy.slice" cgroup_proxy="/proxy.slice"
cgroup_noproxy="/noproxy.slice" cgroup_noproxy="/noproxy.slice"
# cgroup_noproxy="/system.slice/v2ray.service"
########################################################################
###################################################################################
## allow as gateway for local network ## allow as gateway for local network
enable_gateway=false enable_gateway=false
########################################################################
###################################################################################
## listening port of another proxy process, for example v2ray ## listening port of another proxy process, for example v2ray
port=12345 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_dns=true enable_dns=true
enable_tcp=true enable_tcp=true
enable_udp=true enable_udp=true
enable_ipv4=true enable_ipv4=true
enable_ipv6=true enable_ipv6=true
########################################################################
###################################################################################
## do not modify this if you don't known what you are doing ## do not modify this if you don't known what you are doing
table=100 table=100
fwmark=0x01 fwmark=0x01

View File

@@ -30,6 +30,13 @@ cat << 'DOC'
DOC DOC
} }
check_root(){
uid=$(id -u)
[ ! $uid -eq 0 ] && { >&2 echo "permission denied, need root";exit 0; }
}
check_root
## any process in this cgroup will be proxied ## any process in this cgroup will be proxied
cgroup_proxy="/proxy.slice" cgroup_proxy="/proxy.slice"
cgroup_noproxy="/noproxy.slice" cgroup_noproxy="/noproxy.slice"
@@ -53,9 +60,7 @@ fwmark=0x01
make_newin=0x02 make_newin=0x02
## cgroup things ## cgroup things
# cgroup_mount_point=$(findmnt -t cgroup,cgroup2 -n -J|jq '.filesystems[0].target') cgroup_mount_point=$(findmnt -t cgroup2 -n -o TARGET)
# cgroup_type=$(findmnt -t cgroup,cgroup2 -n -J|jq '.filesystems[0].fstype')
cgroup_mount_point=$(findmnt -t cgroup2 -n |cut -d' ' -f 1)
cgroup_type="cgroup2" cgroup_type="cgroup2"
cgroup_procs_file="cgroup.procs" cgroup_procs_file="cgroup.procs"
@@ -64,6 +69,7 @@ for i in "$@"
do do
case $i in case $i in
stop) stop)
echo "stopping tproxy iptables"
iptables -t mangle -D PREROUTING -j TPROXY_PRE iptables -t mangle -D PREROUTING -j TPROXY_PRE
iptables -t mangle -D OUTPUT -j TPROXY_OUT iptables -t mangle -D OUTPUT -j TPROXY_OUT
iptables -t mangle -F TPROXY_PRE iptables -t mangle -F TPROXY_PRE
@@ -86,13 +92,12 @@ case $i in
ip -6 route flush table $table ip -6 route flush table $table
## may not exist, just ignore, and tracking their existence is not reliable ## may not exist, just ignore, and tracking their existence is not reliable
iptables -t nat -D POSTROUTING -m owner ! --socket-exists -j MASQUERADE &> /dev/null iptables -t nat -D POSTROUTING -m owner ! --socket-exists -j MASQUERADE &> /dev/null
ip6tables -t nat -D POSTROUTING -m owner ! --socket-exists -j MASQUERADE &> /dev/null ip6tables -t nat -D POSTROUTING -m owner ! --socket-exists -s fc00::/7 -j MASQUERADE &> /dev/null
exit 0 exit 0
;; ;;
--config=*) --config=*)
config=${i#*=} config=${i#*=}
source $config source $config
shift
;; ;;
--help) --help)
print_help print_help
@@ -127,10 +132,14 @@ iptables -t mangle -A PREROUTING -j TPROXY_PRE
iptables -t mangle -N TPROXY_OUT iptables -t mangle -N TPROXY_OUT
iptables -t mangle -A TPROXY_OUT -p icmp -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 iptables -t mangle -A TPROXY_OUT -m connmark --mark $make_newin -j RETURN
iptables -t mangle -A TPROXY_PRE -m addrtype --dst-type LOCAL -j RETURN iptables -t mangle -A TPROXY_OUT -m addrtype --dst-type LOCAL -j RETURN
iptables -t mangle -A TPROXY_PRE -m addrtype ! --dst-type UNICAST -j RETURN iptables -t mangle -A TPROXY_OUT -m addrtype ! --dst-type UNICAST -j RETURN
iptables -t mangle -A TPROXY_OUT -m cgroup --path $cgroup_noproxy -j RETURN for cg in ${cgroup_noproxy[@]}; do
iptables -t mangle -A TPROXY_OUT -m cgroup --path $cgroup_proxy -j MARK --set-mark $fwmark iptables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j RETURN
done
for cg in ${cgroup_proxy[@]}; do
iptables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j MARK --set-mark $fwmark
done
iptables -t mangle -A OUTPUT -j TPROXY_OUT iptables -t mangle -A OUTPUT -j TPROXY_OUT
#ipv6# #ipv6#
@@ -154,10 +163,14 @@ ip6tables -t mangle -A PREROUTING -j TPROXY_PRE
ip6tables -t mangle -N TPROXY_OUT ip6tables -t mangle -N TPROXY_OUT
ip6tables -t mangle -A TPROXY_OUT -p icmpv6 -j RETURN ip6tables -t mangle -A TPROXY_OUT -p icmpv6 -j RETURN
ip6tables -t mangle -A TPROXY_OUT -m connmark --mark $make_newin -j RETURN ip6tables -t mangle -A TPROXY_OUT -m connmark --mark $make_newin -j RETURN
ip6tables -t mangle -A TPROXY_PRE -m addrtype --dst-type LOCAL -j RETURN ip6tables -t mangle -A TPROXY_OUT -m addrtype --dst-type LOCAL -j RETURN
ip6tables -t mangle -A TPROXY_PRE -m addrtype ! --dst-type UNICAST -j RETURN ip6tables -t mangle -A TPROXY_OUT -m addrtype ! --dst-type UNICAST -j RETURN
ip6tables -t mangle -A TPROXY_OUT -m cgroup --path $cgroup_noproxy -j RETURN for cg in ${cgroup_noproxy[@]}; do
ip6tables -t mangle -A TPROXY_OUT -m cgroup --path $cgroup_proxy -j MARK --set-mark $fwmark ip6tables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j RETURN
done
for cg in ${cgroup_proxy[@]}; do
ip6tables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j MARK --set-mark $fwmark
done
ip6tables -t mangle -A OUTPUT -j TPROXY_OUT ip6tables -t mangle -A OUTPUT -j TPROXY_OUT
## allow to disable, order is important ## allow to disable, order is important
@@ -192,14 +205,14 @@ ip6tables -t mangle -I TPROXY_PRE -m addrtype ! --src-type LOCAL -m conntrack --
## message for user ## message for user
cat << DOC cat << DOC
noproxy cgroup: $cgroup_noproxy noproxy cgroup: ${cgroup_noproxy[@]}
proxied cgroup: $cgroup_proxy proxied cgroup: ${cgroup_proxy[@]}
DOC DOC
if $enable_gateway; then if $enable_gateway; then
iptables -t nat -A POSTROUTING -m owner ! --socket-exists -j MASQUERADE iptables -t nat -A POSTROUTING -m owner ! --socket-exists -j MASQUERADE
ip6tables -t nat -A POSTROUTING -m owner ! --socket-exists -j MASQUERADE ip6tables -t nat -A POSTROUTING -m owner ! --socket-exists -s fc00::/7 -j MASQUERADE # only masquerade ipv6 private address
sysctl -w net.ipv4.ip_forward=1 sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1 sysctl -w net.ipv6.conf.all.forwarding=1
echo "gateway enabled" echo "gateway enabled"

View File

@@ -8,7 +8,7 @@
cgproxy will transparent proxy anything running in specific cgroup. It resembles with *proxychains* and *tsock*, but without their disadvantages, and more powerfull. 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 and gateway proxy. See [Global transparent proxy](#global-transparent-proxy) and [Gateway proxy](#gateway-proxy) It aslo supports global transparent proxy and gateway proxy. See [Global transparent proxy](#global-transparent-proxy) and [Gateway proxy](#gateway-proxy).
<!--ts--> <!--ts-->
@@ -46,7 +46,7 @@ It aslo supports global transparent proxy and gateway proxy. See [Global transpa
mkdir build && cd build && cmake .. && make && sudo make install mkdir build && cd build && cmake .. && make && sudo make install
``` ```
- It is alreay in [archlinux AUR](https://aur.archlinux.org/packages/cgproxy/). - It is alreay in [archlinux AUR](https://aur.archlinux.org/packages/?K=cgproxy).
- DEB and RPM are packaged in [release page](https://github.com/springzfx/cgproxy/releases). - DEB and RPM are packaged in [release page](https://github.com/springzfx/cgproxy/releases).
@@ -79,32 +79,47 @@ mkdir build && cd build && cmake .. && make && sudo make install
<summary>More config in <i>/etc/cgproxy.conf</i> (click to expand)</summary> <summary>More config in <i>/etc/cgproxy.conf</i> (click to expand)</summary>
```bash ```bash
######################################################################## ###################################################################################
## cgroup transparent proxy
## any process in cgroup_proxy will be proxied, and cgroup_noproxy the opposite ## any process in cgroup_proxy will be proxied, and cgroup_noproxy the opposite
## cgroup must start with slash '/' ## note, cgroup must start with slash '/'
## the value can be string or bash array
## for array, only the first element will be created if not exist
## and the rest elements will not, so won't be applied
### global proxy with v2ray service
# cgroup_proxy="/" # cgroup_proxy="/"
# cgroup_noproxy="/system.slice/v2ray.service" # cgroup_noproxy=("/noproxy.slice" "/system.slice/v2ray.service")
### global proxy with manual `cgnoporxy qv2ray`
# cgroup_proxy="/"
# cgroup_noproxy="/noproxy.slice"
### default
cgroup_proxy="/proxy.slice" cgroup_proxy="/proxy.slice"
cgroup_noproxy="/noproxy.slice" cgroup_noproxy="/noproxy.slice"
########################################################################
###################################################################################
## allow as gateway for local network ## allow as gateway for local network
enable_gateway=false enable_gateway=false
########################################################################
###################################################################################
## listening port of another proxy process, for example v2ray ## listening port of another proxy process, for example v2ray
port=12345 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_dns=true enable_dns=true
enable_tcp=true enable_tcp=true
enable_udp=true enable_udp=true
enable_ipv4=true enable_ipv4=true
enable_ipv6=true enable_ipv6=true
########################################################################
###################################################################################
## do not modify this if you don't known what you are doing ## do not modify this if you don't known what you are doing
table=100 table=100
fwmark=0x01 fwmark=0x01
@@ -128,11 +143,13 @@ sudo systemctl restart cgproxy.service
example: `cgnoproxy sudo v2ray -config config_file` example: `cgnoproxy sudo v2ray -config config_file`
- passive way example: `cgnoproxy qv2ray`
- passive way, useful if you run v2ray as service
set `cgroup_noproxy="<PROXY PROGRAM's CGROUP>"` set `cgroup_noproxy="<PROXY PROGRAM's CGROUP>"`
example: `cgroup_noproxy="/system.slice/v2ray.service"` example: `cgroup_noproxy=("/noproxy.slice" "/system.slice/v2ray.service")`
- Finally, restart cgproxy service, that's all - Finally, restart cgproxy service, that's all

View File

@@ -1,5 +1,5 @@
{ {
"log": { "log": {
"loglevel": "error" "loglevel": "none"
} }
} }

View File

@@ -1,7 +1,10 @@
{ {
"dns": { "dns": {
"hosts": {
"geosite:category-ads": "127.0.0.1"
},
"servers": [ "servers": [
"https://223.5.5.5/dns-query", "https+local://223.5.5.5/dns-query",
"https://1.1.1.1/dns-query", "https://1.1.1.1/dns-query",
{ {
"address": "localhost", "address": "localhost",

View File

@@ -21,13 +21,6 @@
"port": "53", "port": "53",
"type": "field" "type": "field"
}, },
{
"inboundTag": [
"dns_inbound"
],
"outboundTag": "outBound_DIRECT",
"type": "field"
},
{ {
"domain": [ "domain": [
"geosite:google", "geosite:google",

View File

@@ -1,2 +1,2 @@
#!/bin/bash #!/bin/bash
jq -rs 'reduce .[] as $item ({}; . + $item + {inbounds: (.inbounds + $item.inbounds)} + {outbounds: ($item.outbounds + .outbounds)})' *.json |sudo tee /etc/v2ray/config.json jq -rs 'reduce .[] as $item ({}; . + $item + {inbounds: (.inbounds + $item.inbounds)} + {outbounds: ($item.outbounds + .outbounds)})' *.json |sudo tee /etc/v2ray/config.json > /dev/null

View File

@@ -5,15 +5,14 @@ After=network.target nss-lookup.target
Wants=network-online.target Wants=network-online.target
[Service] [Service]
Type=simple Type=exec
ExecStart=/usr/lib/v2ray/v2ray -config /etc/v2ray/config.json
User=nobody User=nobody
#AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
NoNewPrivileges=yes NoNewPrivileges=yes
ExecStart=+/usr/lib/v2ray/v2ray -config /etc/v2ray/config.json
Restart=on-failure Restart=on-failure
# Don't restart in the case of configuration error # Don't restart in the case of configuration error
RestartPreventExitStatus=23 RestartPreventExitStatus=23
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target