mirror of
https://github.com/springzfx/cgproxy.git
synced 2026-04-23 10:11:04 +08:00
robust detect already in correspond cgroup
This commit is contained in:
@@ -31,7 +31,7 @@ DOC
|
|||||||
}
|
}
|
||||||
|
|
||||||
## check root
|
## check root
|
||||||
[ ! $(id -u) -eq 0 ] && { >&2 echo "need root to modify iptables";exit -1; }
|
[ ! $(id -u) -eq 0 ] && { >&2 echo "iptables: need root to modify iptables";exit -1; }
|
||||||
|
|
||||||
## any process in this cgroup will be proxied
|
## any process in this cgroup will be proxied
|
||||||
if [ -z ${cgroup_proxy+x} ]; then
|
if [ -z ${cgroup_proxy+x} ]; then
|
||||||
@@ -150,10 +150,10 @@ iptables -t mangle -A TPROXY_OUT -m connmark --mark $make_newin -j RETURN
|
|||||||
iptables -t mangle -A TPROXY_OUT -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_OUT -m addrtype ! --dst-type UNICAST -j RETURN
|
iptables -t mangle -A TPROXY_OUT -m addrtype ! --dst-type UNICAST -j RETURN
|
||||||
for cg in ${cgroup_noproxy[@]}; do
|
for cg in ${cgroup_noproxy[@]}; do
|
||||||
iptables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j RETURN
|
iptables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j RETURN || { >&2 echo "iptables: $cg not exist, won't apply"; }
|
||||||
done
|
done
|
||||||
for cg in ${cgroup_proxy[@]}; do
|
for cg in ${cgroup_proxy[@]}; do
|
||||||
iptables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j MARK --set-mark $fwmark
|
iptables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j MARK --set-mark $fwmark || { >&2 echo "iptables: $cg not exist, won't apply"; }
|
||||||
done
|
done
|
||||||
iptables -t mangle -A OUTPUT -j TPROXY_OUT
|
iptables -t mangle -A OUTPUT -j TPROXY_OUT
|
||||||
|
|
||||||
@@ -181,10 +181,10 @@ ip6tables -t mangle -A TPROXY_OUT -m connmark --mark $make_newin -j RETURN
|
|||||||
ip6tables -t mangle -A TPROXY_OUT -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_OUT -m addrtype ! --dst-type UNICAST -j RETURN
|
ip6tables -t mangle -A TPROXY_OUT -m addrtype ! --dst-type UNICAST -j RETURN
|
||||||
for cg in ${cgroup_noproxy[@]}; do
|
for cg in ${cgroup_noproxy[@]}; do
|
||||||
ip6tables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j RETURN
|
ip6tables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j RETURN || { >&2 echo "iptables: $cg not exist, won't apply"; }
|
||||||
done
|
done
|
||||||
for cg in ${cgroup_proxy[@]}; do
|
for cg in ${cgroup_proxy[@]}; do
|
||||||
ip6tables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j MARK --set-mark $fwmark
|
ip6tables -t mangle -A TPROXY_OUT -m cgroup --path $cg -j MARK --set-mark $fwmark || { >&2 echo "iptables: $cg not exist, won't apply"; }
|
||||||
done
|
done
|
||||||
ip6tables -t mangle -A OUTPUT -j TPROXY_OUT
|
ip6tables -t mangle -A OUTPUT -j TPROXY_OUT
|
||||||
|
|
||||||
|
|||||||
@@ -92,15 +92,16 @@ class cgproxyd {
|
|||||||
|
|
||||||
v = config.program_noproxy;
|
v = config.program_noproxy;
|
||||||
if (find(v.begin(), v.end(), path) != v.end()) {
|
if (find(v.begin(), v.end(), path) != v.end()) {
|
||||||
if (CGROUP::getCgroup(pid) != config.cgroup_noproxy_preserved) {
|
if (!belongToCgroup(getCgroup(pid), config.cgroup_noproxy)) {
|
||||||
info("execsnoop noproxy: %d %s", pid, path);
|
info("execsnoop noproxy: %d %s", pid, path);
|
||||||
free(path);
|
free(path);
|
||||||
return attach(pid, config.cgroup_noproxy_preserved);
|
return attach(pid, config.cgroup_noproxy_preserved);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v = config.program_proxy;
|
v = config.program_proxy;
|
||||||
if (find(v.begin(), v.end(), path) != v.end()) {
|
if (find(v.begin(), v.end(), path) != v.end()) {
|
||||||
if (CGROUP::getCgroup(pid) != config.cgroup_proxy_preserved) {
|
if (!belongToCgroup(getCgroup(pid), config.cgroup_proxy)) {
|
||||||
info("execsnoop proxied: %d %s", pid, path);
|
info("execsnoop proxied: %d %s", pid, path);
|
||||||
free(path);
|
free(path);
|
||||||
return attach(pid, config.cgroup_proxy_preserved);
|
return attach(pid, config.cgroup_proxy_preserved);
|
||||||
@@ -215,14 +216,14 @@ class cgproxyd {
|
|||||||
debug("process running program");
|
debug("process running program");
|
||||||
for (auto &path : config.program_noproxy)
|
for (auto &path : config.program_noproxy)
|
||||||
for (auto &pid : bash_pidof(path)) {
|
for (auto &pid : bash_pidof(path)) {
|
||||||
if (CGROUP::getCgroup(pid) != config.cgroup_noproxy_preserved) {
|
if (!belongToCgroup(getCgroup(pid), config.cgroup_noproxy)) {
|
||||||
int status = attach(pid, config.cgroup_noproxy_preserved);
|
int status = attach(pid, config.cgroup_noproxy_preserved);
|
||||||
if (status == 0) info("noproxy running process %d %s", pid, path.c_str());
|
if (status == 0) info("noproxy running process %d %s", pid, path.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto &path : config.program_proxy)
|
for (auto &path : config.program_proxy)
|
||||||
for (auto &pid : bash_pidof(path)) {
|
for (auto &pid : bash_pidof(path)) {
|
||||||
if (CGROUP::getCgroup(pid) != config.cgroup_proxy_preserved) {
|
if (!belongToCgroup(getCgroup(pid), config.cgroup_proxy)) {
|
||||||
int status = attach(pid, config.cgroup_proxy_preserved);
|
int status = attach(pid, config.cgroup_proxy_preserved);
|
||||||
if (status == 0) info("proxied running process %d %s", pid, path.c_str());
|
if (status == 0) info("proxied running process %d %s", pid, path.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,34 +27,6 @@ string get_cgroup2_mount_point() {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
string getCgroup(const pid_t &pid) { return getCgroup(to_str(pid)); }
|
|
||||||
|
|
||||||
string getCgroup(const string &pid) {
|
|
||||||
string cgroup_f = to_str("/proc/", pid, "/cgroup");
|
|
||||||
if (!fileExist(cgroup_f)) return "";
|
|
||||||
|
|
||||||
stringstream buffer;
|
|
||||||
string cgroup;
|
|
||||||
FILE *f = fopen(cgroup_f.c_str(), "r");
|
|
||||||
char buf[READ_SIZE_MAX] = "";
|
|
||||||
char *flag = buf;
|
|
||||||
while (flag != NULL) {
|
|
||||||
buffer.clear();
|
|
||||||
while (!flag || buf[strlen(buf) - 1] != '\n') {
|
|
||||||
flag = fgets(buf, READ_SIZE_MAX, f);
|
|
||||||
if (flag) buffer << buf;
|
|
||||||
}
|
|
||||||
string line = buffer.str();
|
|
||||||
if (line[0] == '0') { // 0::/user.slice/user-1000.slice
|
|
||||||
cgroup = (*(line.end() - 1) == '\n') ? line.substr(3, line.length() - 4)
|
|
||||||
: line.substr(3);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
return cgroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool validate(string pid, string cgroup) {
|
bool validate(string pid, string cgroup) {
|
||||||
bool pid_v = validPid(pid);
|
bool pid_v = validPid(pid);
|
||||||
bool cg_v = validCgroup(cgroup);
|
bool cg_v = validCgroup(cgroup);
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ namespace CGPROXY::CGROUP {
|
|||||||
extern string cgroup2_mount_point;
|
extern string cgroup2_mount_point;
|
||||||
bool validate(string pid, string cgroup);
|
bool validate(string pid, string cgroup);
|
||||||
string get_cgroup2_mount_point();
|
string get_cgroup2_mount_point();
|
||||||
string getCgroup(const pid_t &pid);
|
|
||||||
string getCgroup(const string &pid);
|
|
||||||
int attach(const string pid, const string cgroup_target);
|
int attach(const string pid, const string cgroup_target);
|
||||||
int attach(const int pid, const string cgroup_target);
|
int attach(const int pid, const string cgroup_target);
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ string join2str(const int argc, char **argv, const char delm) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool startWith(string s, string prefix) { return s.rfind(prefix, 0) == 0; }
|
||||||
|
|
||||||
bool validCgroup(const string cgroup) {
|
bool validCgroup(const string cgroup) {
|
||||||
return regex_match(cgroup, regex("^/[a-zA-Z0-9\\-_./@]*$"));
|
return regex_match(cgroup, regex("^/[a-zA-Z0-9\\-_./@]*$"));
|
||||||
}
|
}
|
||||||
@@ -89,4 +91,41 @@ string getRealExistPath(const string &name) {
|
|||||||
path = bash_readlink(path);
|
path = bash_readlink(path);
|
||||||
if (!fileExist(path)) return "";
|
if (!fileExist(path)) return "";
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool belongToCgroup(string cg1, string cg2) { return startWith(cg1 + '/', cg2 + '/'); }
|
||||||
|
|
||||||
|
bool belongToCgroup(string cg1, vector<string> cg2) {
|
||||||
|
for (const auto &s : cg2) {
|
||||||
|
if (startWith(cg1 + '/', s + '/')) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string getCgroup(const pid_t &pid) { return getCgroup(to_str(pid)); }
|
||||||
|
|
||||||
|
string getCgroup(const string &pid) {
|
||||||
|
string cgroup_f = to_str("/proc/", pid, "/cgroup");
|
||||||
|
if (!fileExist(cgroup_f)) return "";
|
||||||
|
|
||||||
|
stringstream buffer;
|
||||||
|
string cgroup;
|
||||||
|
FILE *f = fopen(cgroup_f.c_str(), "r");
|
||||||
|
char buf[READ_SIZE_MAX] = "";
|
||||||
|
char *flag = buf;
|
||||||
|
while (flag != NULL) {
|
||||||
|
buffer.clear();
|
||||||
|
while (!flag || buf[strlen(buf) - 1] != '\n') {
|
||||||
|
flag = fgets(buf, READ_SIZE_MAX, f);
|
||||||
|
if (flag) buffer << buf;
|
||||||
|
}
|
||||||
|
string line = buffer.str();
|
||||||
|
if (line[0] == '0') { // 0::/user.slice/user-1000.slice
|
||||||
|
cgroup = (*(line.end() - 1) == '\n') ? line.substr(3, line.length() - 4)
|
||||||
|
: line.substr(3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return cgroup;
|
||||||
|
}
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ template <typename... T> string to_str(T... args) {
|
|||||||
|
|
||||||
string join2str(const vector<string> t, const char delm = ' ');
|
string join2str(const vector<string> t, const char delm = ' ');
|
||||||
string join2str(const int argc, char **argv, const char delm = ' ');
|
string join2str(const int argc, char **argv, const char delm = ' ');
|
||||||
|
bool startWith(string prefix);
|
||||||
|
|
||||||
bool validCgroup(const string cgroup);
|
bool validCgroup(const string cgroup);
|
||||||
bool validCgroup(const vector<string> cgroup);
|
bool validCgroup(const vector<string> cgroup);
|
||||||
@@ -88,4 +89,12 @@ string bash_which(const string &name);
|
|||||||
string bash_readlink(const string &path);
|
string bash_readlink(const string &path);
|
||||||
string getRealExistPath(const string &name);
|
string getRealExistPath(const string &name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* whether cg1 belongs to cg2
|
||||||
|
*/
|
||||||
|
bool belongToCgroup(string cg1, string cg2);
|
||||||
|
bool belongToCgroup(string cg1, vector<string> cg2);
|
||||||
|
string getCgroup(const pid_t &pid);
|
||||||
|
string getCgroup(const string &pid);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ using json = nlohmann::json;
|
|||||||
namespace CGPROXY::CONFIG {
|
namespace CGPROXY::CONFIG {
|
||||||
|
|
||||||
void Config::toEnv() {
|
void Config::toEnv() {
|
||||||
mergeReserved();
|
|
||||||
setenv("program_proxy", join2str(program_proxy, ':').c_str(), 1);
|
setenv("program_proxy", join2str(program_proxy, ':').c_str(), 1);
|
||||||
setenv("program_noproxy", join2str(program_noproxy, ':').c_str(), 1);
|
setenv("program_noproxy", join2str(program_noproxy, ':').c_str(), 1);
|
||||||
setenv("cgroup_proxy", join2str(cgroup_proxy, ':').c_str(), 1);
|
setenv("cgroup_proxy", join2str(cgroup_proxy, ':').c_str(), 1);
|
||||||
@@ -95,6 +94,8 @@ int Config::loadFromJsonStr(const string js) {
|
|||||||
toRealProgramPath(program_noproxy);
|
toRealProgramPath(program_noproxy);
|
||||||
toRealProgramPath(program_proxy);
|
toRealProgramPath(program_proxy);
|
||||||
|
|
||||||
|
mergeReserved();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,4 +152,8 @@ void Config::toRealProgramPath(vector<string> &v) {
|
|||||||
v = tmp;
|
v = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef tryassign
|
||||||
|
#undef add2json
|
||||||
|
#undef merge
|
||||||
|
|
||||||
} // namespace CGPROXY::CONFIG
|
} // namespace CGPROXY::CONFIG
|
||||||
@@ -13,8 +13,8 @@ public:
|
|||||||
const string cgroup_proxy_preserved = CGROUP_PROXY_PRESVERED;
|
const string cgroup_proxy_preserved = CGROUP_PROXY_PRESVERED;
|
||||||
const string cgroup_noproxy_preserved = CGROUP_NOPROXY_PRESVERED;
|
const string cgroup_noproxy_preserved = CGROUP_NOPROXY_PRESVERED;
|
||||||
|
|
||||||
vector<string> program_proxy;
|
vector<string> program_proxy = {cgroup_proxy_preserved};
|
||||||
vector<string> program_noproxy;
|
vector<string> program_noproxy = {cgroup_noproxy_preserved};
|
||||||
vector<string> cgroup_proxy;
|
vector<string> cgroup_proxy;
|
||||||
vector<string> cgroup_noproxy;
|
vector<string> cgroup_noproxy;
|
||||||
bool enable_gateway = false;
|
bool enable_gateway = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user