From 1c16f57193b6c996cf0f8c802bfd250e79246809 Mon Sep 17 00:00:00 2001 From: fancy Date: Sat, 16 May 2020 00:45:38 +0800 Subject: [PATCH] now based on unix socket and json config --- CMakeLists.txt | 35 ++++++++++++-------------- aur-cgproxy-local/PKGBUILD | 6 ++--- cgnoproxy.cpp | 34 ++++++++++++++++++++++++++ cgproxy.cpp | 31 +++++++++++++++++++++++ cgproxy.service | 7 +++--- main.cpp => cgproxyd.cpp | 11 ++++++--- cgroup-tproxy.sh | 36 +++++++++++++++------------ cgroup_attach.h | 11 +++++++-- common.h | 50 +++++++++++++++++++++++++++++--------- config.h | 8 +++--- config.json | 2 +- socket_server.h | 8 ++++-- 12 files changed, 173 insertions(+), 66 deletions(-) create mode 100644 cgnoproxy.cpp create mode 100644 cgproxy.cpp rename main.cpp => cgproxyd.cpp (92%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 51401e2..fa7eb45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,33 +1,32 @@ cmake_minimum_required(VERSION 3.10) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -# set(CMAKE_BUILD_TYPE DEBUG) -set(CMAKE_BUILD_TYPE RELEASE) - -project(cgproxy VERSION 3.7) +set(CMAKE_BUILD_TYPE DEBUG) +# set(CMAKE_BUILD_TYPE RELEASE) +project(cgproxy VERSION 4.0) find_package(Threads REQUIRED) find_package(nlohmann_json REQUIRED) include_directories(${PROJECT_SOURCE_DIR}) add_executable(cgattach cgattach.cpp) +add_executable(cgproxyd cgproxyd.cpp) +add_executable(cgproxy cgproxy.cpp) +add_executable(cgnoproxy cgnoproxy.cpp) +target_link_libraries(cgproxyd Threads::Threads nlohmann_json::nlohmann_json) +target_link_libraries(cgproxy nlohmann_json::nlohmann_json) +target_link_libraries(cgnoproxy nlohmann_json::nlohmann_json) -add_executable(main main.cpp) -target_link_libraries(main Threads::Threads nlohmann_json::nlohmann_json) +# add_executable(client_test socket_client_test.cpp) +# target_link_libraries(client_test nlohmann_json::nlohmann_json) -add_executable(client_test socket_client_test.cpp) -target_link_libraries(client_test nlohmann_json::nlohmann_json) +set(basic_permission OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - -install(TARGETS cgattach DESTINATION /usr/bin - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE SETUID) -install(FILES cgproxy.sh DESTINATION /usr/bin - RENAME cgproxy - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) -install(FILES cgnoproxy.sh DESTINATION /usr/bin - RENAME cgnoproxy - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +install(TARGETS cgattach DESTINATION /usr/bin PERMISSIONS ${basic_permission}) +install(TARGETS cgproxyd DESTINATION /usr/bin PERMISSIONS ${basic_permission}) +install(TARGETS cgproxy DESTINATION /usr/bin PERMISSIONS ${basic_permission}) +install(TARGETS cgnoproxy DESTINATION /usr/bin PERMISSIONS ${basic_permission}) install(FILES cgproxy.service DESTINATION /usr/lib/systemd/system/) @@ -40,8 +39,6 @@ install(FILES readme.md DESTINATION /share/doc/cgproxy/) - - ## package for deb and rpm set(CPACK_GENERATOR "DEB;RPM") set(CPACK_PACKAGE_NAME "cgproxy") diff --git a/aur-cgproxy-local/PKGBUILD b/aur-cgproxy-local/PKGBUILD index 0208cec..6a86b39 100644 --- a/aur-cgproxy-local/PKGBUILD +++ b/aur-cgproxy-local/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Fancy Zhang pkgname=cgproxy-git -pkgver=v3.8.r1.gc0668fd +pkgver=v4.0.r1.g3fde647 pkgrel=1 pkgdesc="A transparent proxy program with cgroup2, like proxychains" arch=('x86_64') @@ -13,8 +13,8 @@ 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") +# source=("${pkgname}::git+file://${curr_dir}/../.git") +source=("${pkgname}::git+file:///home/fancy/workspace/cgproxy#branch=dev") md5sums=('SKIP') pkgver() { diff --git a/cgnoproxy.cpp b/cgnoproxy.cpp new file mode 100644 index 0000000..f41ee84 --- /dev/null +++ b/cgnoproxy.cpp @@ -0,0 +1,34 @@ +#include +#include "socket_client.h" +using json = nlohmann::json; +using namespace CGPROXY; + +bool attach2cgproxy(){ + pid_t pid=getpid(); + json j; + j["type"] = MSG_TYPE_NOPROXY_PID; + j["data"] = pid; + int status; + SOCKET::send(j.dump(), status); + return status==0; +} + +int main(int argc, char *argv[]){ + int shift=1; + if (argc==1){ + error("usage: cgnoproxy [--debug] \nexample: cgnoproxy curl -I https://www.google.com"); + exit(EXIT_FAILURE); + } + if (argv[1]=="--debug"){ + enable_debug=true; + shift+=1; + } + + if (!attach2cgproxy()){ + error("attach process failed"); + exit(EXIT_FAILURE); + } + + string s=join2str(argc-shift,argv+shift,' '); + return system(s.c_str()); +} \ No newline at end of file diff --git a/cgproxy.cpp b/cgproxy.cpp new file mode 100644 index 0000000..aba4ba2 --- /dev/null +++ b/cgproxy.cpp @@ -0,0 +1,31 @@ +#include +#include "socket_client.h" +using json = nlohmann::json; +using namespace CGPROXY; + +bool attach2cgproxy(){ + pid_t pid=getpid(); + json j; + j["type"] = MSG_TYPE_PROXY_PID; + j["data"] = pid; + int status; + SOCKET::send(j.dump(), status); + return status==0; +} + +int main(int argc, char *argv[]){ + int shift=1; + // if (argc==1){ + // error("usage: cgproxy [--debug] \nexample: cgroxy curl -I https://www.google.com"); + // exit(EXIT_FAILURE); + // } + processArgs(argc,argv,shift); + + if (!attach2cgproxy()){ + error("attach process failed"); + exit(EXIT_FAILURE); + } + + string s=join2str(argc-shift,argv+shift,' '); + return system(s.c_str()); +} \ No newline at end of file diff --git a/cgproxy.service b/cgproxy.service index 521e857..fb040ec 100644 --- a/cgproxy.service +++ b/cgproxy.service @@ -1,11 +1,10 @@ [Unit] -Description=proxy cgroup +Description=cgproxy service After=network.target [Service] -ExecStart=sh /usr/share/cgproxy/scripts/cgroup-tproxy.sh --config=/etc/cgproxy.conf -ExecStop= sh /usr/share/cgproxy/scripts/cgroup-tproxy.sh stop -RemainAfterExit=1 +Type=simple +ExecStart=/usr/bin/cgproxyd [Install] WantedBy=multi-user.target diff --git a/main.cpp b/cgproxyd.cpp similarity index 92% rename from main.cpp rename to cgproxyd.cpp index 838874d..8664321 100644 --- a/main.cpp +++ b/cgproxyd.cpp @@ -36,7 +36,7 @@ int handle_msg(char *msg) { try{ j = json::parse(msg); }catch(exception& e){debug("msg paser error");return MSG_ERROR;} int type, status; - string pid, cgroup_target; + int pid, cgroup_target; try { type = j.at("type").get(); switch (type) @@ -52,12 +52,12 @@ int handle_msg(char *msg) { return status; break; case MSG_TYPE_PROXY_PID: - pid=j.at("data").get(); + pid=j.at("data").get(); status=attach(pid, config.cgroup_proxy_preserved); return status; break; case MSG_TYPE_NOPROXY_PID: - pid=j.at("data").get(); + pid=j.at("data").get(); status=attach(pid, config.cgroup_noproxy_preserved); return status; break; @@ -83,7 +83,10 @@ pthread_t startSocketListeningThread() { return thread_id; } -int main() { +int main(int argc, char* argv[]) { + int shift=1; + processArgs(argc,argv,shift); + bool enable_socket = true; string config_path = DEFAULT_CONFIG_FILE; config.loadFromFile(config_path); diff --git a/cgroup-tproxy.sh b/cgroup-tproxy.sh index f419b89..4fba5d3 100644 --- a/cgroup-tproxy.sh +++ b/cgroup-tproxy.sh @@ -30,29 +30,35 @@ cat << 'DOC' DOC } -check_root(){ - uid=$(id -u) - [ ! $uid -eq 0 ] && { >&2 echo "permission denied, need root";exit 0; } -} - -check_root +## check root +[ ! $(id -u) -eq 0 ] && { >&2 echo "need root to modify iptables";exit -1; } ## any process in this cgroup will be proxied -cgroup_proxy="/proxy.slice" -cgroup_noproxy="/noproxy.slice" +if [ -z ${cgroup_proxy+x} ]; then + cgroup_proxy="/proxy.slice" +else + IFS=':' read -r -a cgroup_proxy <<< "$cgroup_proxy" +fi + +## any process in this cgroup will not be proxied +if [ -z ${cgroup_noproxy+x} ]; then + cgroup_noproxy="/noproxy.slice" +else + IFS=':' read -r -a cgroup_noproxy <<< "$cgroup_noproxy" +fi # allow as gateway for local network -enable_gateway=false +[ -z ${enable_gateway+x} ] && enable_gateway=false ## some variables -port=12345 +[ -z ${port+x} ] && port=12345 ## some options -enable_dns=true -enable_tcp=true -enable_udp=true -enable_ipv4=true -enable_ipv6=true +[ -z ${enable_dns+x} ] && enable_dns=true +[ -z ${enable_tcp+x} ] && enable_tcp=true +[ -z ${enable_udp+x} ] && enable_udp=true +[ -z ${enable_ipv4+x} ] && enable_ipv4=true +[ -z ${enable_ipv6+x} ] && enable_ipv6=true ## do not modify this if you don't known what you are doing table=100 diff --git a/cgroup_attach.h b/cgroup_attach.h index b254611..c1c94f4 100644 --- a/cgroup_attach.h +++ b/cgroup_attach.h @@ -30,7 +30,7 @@ bool validate(string pid, string cgroup) { if (pid_v && cg_v) return true; - error("paramater validate error"); + error("attach paramater validate error"); return_error } @@ -53,8 +53,11 @@ int attach(const string pid, const string cgroup_target) { error("need root to attach cgroup"); return_error } + + debug("attaching %s to %s",pid.c_str(),cgroup_target.c_str()); + int status; - validate(pid, cgroup_target); + if (!validate(pid, cgroup_target)) return_error string cgroup_mount_point = get_cgroup2_mount_point(status); if (status!=0) return_error string cgroup_target_path = cgroup_mount_point + cgroup_target; @@ -91,6 +94,10 @@ int attach(const string pid, const string cgroup_target) { return_success } +int attach(const int pid, const string cgroup_target){ + return attach(to_str(pid), cgroup_target); +} + } #endif \ No newline at end of file diff --git a/common.h b/common.h index 22a66cf..4a43ecd 100644 --- a/common.h +++ b/common.h @@ -1,9 +1,9 @@ #ifndef COMMON_H -#define COMMON_H +#define COMMON_H 1 -#define SOCKET_PATH "/tmp/unix_socket" +#define SOCKET_PATH "/tmp/cgproxy_unix_socket" #define LISTEN_BACKLOG 64 -#define DEFAULT_CONFIG_FILE "/etc/cgproxy.conf" +#define DEFAULT_CONFIG_FILE "/etc/cgproxy/config.json" #define CGROUP_PROXY_PRESVERED "/proxy.slice" #define CGROUP_NOPROXY_PRESVERED "/noproxy.slice" @@ -31,27 +31,53 @@ #include using namespace std; +extern bool enable_debug=false; +extern bool print_help=false; + #define error(...) {fprintf(stderr, __VA_ARGS__);fprintf(stderr, "\n");} -#define debug(...) {fprintf(stdout, __VA_ARGS__);fprintf(stdout, "\n");} +#define debug(...) if (enable_debug) {fprintf(stdout, __VA_ARGS__);fprintf(stdout, "\n");} #define return_error return -1; #define return_success return 0; +void processArgs(const int argc, char *argv[], int &shift){ + for (int i=1;i string to_str(T... args) { stringstream ss; ss.clear(); - (ss << ... << args) << endl; + ss << std::boolalpha; + (ss << ... << args); return ss.str(); } -template -string join2str(const T t){ +string join2str(const vector t, const char delm=' '){ string s; - string delm=" ", prefix="(", tail=")", wrap="\""; for (const auto &e : t) - e!=*(t.end()-1)?s+=wrap+e+wrap+delm:s+=wrap+e+wrap; - return prefix+s+tail; + e!=*(t.end()-1)?s+=e+delm:s+=e; + return s; +} + +string join2str(const int argc,char** argv, const char delm=' '){ + string s; + for (int i=0;i0; } #endif \ No newline at end of file diff --git a/config.h b/config.h index 9f00a5d..824d787 100644 --- a/config.h +++ b/config.h @@ -36,8 +36,8 @@ struct Config { public: void toEnv() { mergeReserved(); - setenv("cgroup_proxy", join2str(cgroup_proxy).c_str(), 1); - setenv("cgroup_noproxy", join2str(cgroup_noproxy).c_str(), 1); + setenv("cgroup_proxy", join2str(cgroup_proxy,':').c_str(), 1); + setenv("cgroup_noproxy", join2str(cgroup_noproxy, ':').c_str(), 1); setenv("enable_gateway", to_str(enable_gateway).c_str(), 1); setenv("port", to_str(port).c_str(), 1); setenv("enable_dns", to_str(enable_dns).c_str(), 1); @@ -122,9 +122,9 @@ public: if (value.is_array()&&!validCgroup((vector)value)) status=false; if (!value.is_string()&&!value.is_array()) status=false; }else if (key=="port"){ - if (validPort(value)) status=false; + if (!validPort(value)) status=false; }else if (boolset.find(key)!=boolset.end()){ - if (value.is_boolean()) status=false; + if (!value.is_boolean()) status=false; }else{ error("unknown key: %s", key.c_str()); return false; diff --git a/config.json b/config.json index 383d3c1..5fd161b 100644 --- a/config.json +++ b/config.json @@ -1,5 +1,5 @@ { - "cgroup_noproxy": [], + "cgroup_noproxy": ["/system.slice/v2ray.service"], "cgroup_proxy": [], "enable_dns": true, "enable_gateway": false, diff --git a/socket_server.h b/socket_server.h index dc08593..8e91086 100644 --- a/socket_server.h +++ b/socket_server.h @@ -12,8 +12,10 @@ #include #include #include +#include #include "common.h" using namespace std; +namespace fs = std::filesystem; namespace CGPROXY::SOCKET{ @@ -38,8 +40,10 @@ public: debug("starting socket listening"); sfd = socket(AF_UNIX, SOCK_STREAM, 0); - flag=unlink(SOCKET_PATH); - if (flag==-1) {error("%s exist, and can't unlink",SOCKET_PATH); exit(EXIT_FAILURE);} + if (fs::exists(SOCKET_PATH)&&unlink(SOCKET_PATH)==-1){ + error("%s exist, and can't unlink",SOCKET_PATH); + exit(EXIT_FAILURE); + } memset(&unix_socket, '\0', sizeof(struct sockaddr_un)); unix_socket.sun_family = AF_UNIX; strncpy(unix_socket.sun_path, SOCKET_PATH,