mirror of
https://github.com/springzfx/cgproxy.git
synced 2026-02-09 21:14:57 +08:00
now based on unix socket and json config
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Maintainer: Fancy Zhang <springzfx@gmail.com>
|
||||
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() {
|
||||
|
||||
34
cgnoproxy.cpp
Normal file
34
cgnoproxy.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
#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] <CMD>\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());
|
||||
}
|
||||
31
cgproxy.cpp
Normal file
31
cgproxy.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
#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] <CMD>\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());
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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<int>();
|
||||
switch (type)
|
||||
@@ -52,12 +52,12 @@ int handle_msg(char *msg) {
|
||||
return status;
|
||||
break;
|
||||
case MSG_TYPE_PROXY_PID:
|
||||
pid=j.at("data").get<string>();
|
||||
pid=j.at("data").get<int>();
|
||||
status=attach(pid, config.cgroup_proxy_preserved);
|
||||
return status;
|
||||
break;
|
||||
case MSG_TYPE_NOPROXY_PID:
|
||||
pid=j.at("data").get<string>();
|
||||
pid=j.at("data").get<int>();
|
||||
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);
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
50
common.h
50
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 <regex>
|
||||
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<argc;i++){
|
||||
if (strcmp(argv[i], "--debug")==0){
|
||||
enable_debug=true;
|
||||
}
|
||||
if (strcmp(argv[i], "--help")==0){
|
||||
print_help=true;
|
||||
}
|
||||
if (argv[i][0]!='-') {
|
||||
break;
|
||||
}
|
||||
shift+=1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
string to_str(T... args) {
|
||||
stringstream ss;
|
||||
ss.clear();
|
||||
(ss << ... << args) << endl;
|
||||
ss << std::boolalpha;
|
||||
(ss << ... << args);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
string join2str(const T t){
|
||||
string join2str(const vector<string> 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;i<argc;i++){
|
||||
s+=argv[i];
|
||||
if (i!=argc-1) s+=delm;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
bool validCgroup(const string cgroup){
|
||||
@@ -71,8 +97,8 @@ bool validPid(const string pid){
|
||||
return regex_match(pid, regex("^[0-9]+$"));
|
||||
}
|
||||
|
||||
bool validPort(const string port){
|
||||
return regex_match(port, regex("^[0-9]+$"));
|
||||
bool validPort(const int port){
|
||||
return port>0;
|
||||
}
|
||||
|
||||
#endif
|
||||
8
config.h
8
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<string>)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;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"cgroup_noproxy": [],
|
||||
"cgroup_noproxy": ["/system.slice/v2ray.service"],
|
||||
"cgroup_proxy": [],
|
||||
"enable_dns": true,
|
||||
"enable_gateway": false,
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <filesystem>
|
||||
#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,
|
||||
|
||||
Reference in New Issue
Block a user