robust detect already in correspond cgroup

This commit is contained in:
springzfx
2020-05-27 00:00:05 +08:00
parent 1d29828d1b
commit c32457a1aa
8 changed files with 67 additions and 43 deletions

View File

@@ -31,7 +31,7 @@ DOC
}
## 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
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 UNICAST -j RETURN
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
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
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 UNICAST -j RETURN
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
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
ip6tables -t mangle -A OUTPUT -j TPROXY_OUT

View File

@@ -92,15 +92,16 @@ class cgproxyd {
v = config.program_noproxy;
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);
free(path);
return attach(pid, config.cgroup_noproxy_preserved);
}
}
v = config.program_proxy;
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);
free(path);
return attach(pid, config.cgroup_proxy_preserved);
@@ -215,14 +216,14 @@ class cgproxyd {
debug("process running program");
for (auto &path : config.program_noproxy)
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);
if (status == 0) info("noproxy running process %d %s", pid, path.c_str());
}
}
for (auto &path : config.program_proxy)
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);
if (status == 0) info("proxied running process %d %s", pid, path.c_str());
}

View File

@@ -27,34 +27,6 @@ string get_cgroup2_mount_point() {
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 pid_v = validPid(pid);
bool cg_v = validCgroup(cgroup);

View File

@@ -9,8 +9,6 @@ namespace CGPROXY::CGROUP {
extern string cgroup2_mount_point;
bool validate(string pid, string cgroup);
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 int pid, const string cgroup_target);

View File

@@ -22,6 +22,8 @@ string join2str(const int argc, char **argv, const char delm) {
return s;
}
bool startWith(string s, string prefix) { return s.rfind(prefix, 0) == 0; }
bool validCgroup(const string cgroup) {
return regex_match(cgroup, regex("^/[a-zA-Z0-9\\-_./@]*$"));
}
@@ -89,4 +91,41 @@ string getRealExistPath(const string &name) {
path = bash_readlink(path);
if (!fileExist(path)) return "";
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;
}

View File

@@ -75,6 +75,7 @@ template <typename... T> string to_str(T... args) {
string join2str(const vector<string> t, 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 vector<string> cgroup);
@@ -88,4 +89,12 @@ string bash_which(const string &name);
string bash_readlink(const string &path);
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

View File

@@ -21,7 +21,6 @@ using json = nlohmann::json;
namespace CGPROXY::CONFIG {
void Config::toEnv() {
mergeReserved();
setenv("program_proxy", join2str(program_proxy, ':').c_str(), 1);
setenv("program_noproxy", join2str(program_noproxy, ':').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_proxy);
mergeReserved();
return 0;
}
@@ -151,4 +152,8 @@ void Config::toRealProgramPath(vector<string> &v) {
v = tmp;
}
#undef tryassign
#undef add2json
#undef merge
} // namespace CGPROXY::CONFIG

View File

@@ -13,8 +13,8 @@ public:
const string cgroup_proxy_preserved = CGROUP_PROXY_PRESVERED;
const string cgroup_noproxy_preserved = CGROUP_NOPROXY_PRESVERED;
vector<string> program_proxy;
vector<string> program_noproxy;
vector<string> program_proxy = {cgroup_proxy_preserved};
vector<string> program_noproxy = {cgroup_noproxy_preserved};
vector<string> cgroup_proxy;
vector<string> cgroup_noproxy;
bool enable_gateway = false;