Read config from stdin

This commit is contained in:
DomySh
2022-06-28 00:36:26 +02:00
parent 753e54a22c
commit 4770fe7314
2 changed files with 52 additions and 61 deletions

View File

@@ -30,6 +30,7 @@ class Proxy:
def __init__(self, internal_port, public_port, callback_blocked_update=None, filters=None, public_host="0.0.0.0", internal_host="127.0.0.1"): def __init__(self, internal_port, public_port, callback_blocked_update=None, filters=None, public_host="0.0.0.0", internal_host="127.0.0.1"):
self.filter_map = {} self.filter_map = {}
self.filter_map_lock = Lock() self.filter_map_lock = Lock()
self.update_config_lock = Lock()
self.public_host = public_host self.public_host = public_host
self.public_port = public_port self.public_port = public_port
self.internal_host = internal_host self.internal_host = internal_host
@@ -37,35 +38,27 @@ class Proxy:
self.filters = set(filters) if filters else set([]) self.filters = set(filters) if filters else set([])
self.process = None self.process = None
self.callback_blocked_update = callback_blocked_update self.callback_blocked_update = callback_blocked_update
self.config_file_path = None
while self.config_file_path is None:
config_file_path = os.path.join("/tmp/" + token_urlsafe(16))
if not os.path.exists(config_file_path):
self.config_file_path = config_file_path
def start(self, in_pause=False): def start(self, in_pause=False):
if not self.isactive(): if not self.isactive():
self.filter_map = self.compile_filters() self.filter_map = self.compile_filters()
filters_codes = list(self.filter_map.keys()) if not in_pause else [] filters_codes = list(self.filter_map.keys()) if not in_pause else []
proxy_binary_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),"./proxy") proxy_binary_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),"./proxy")
try:
self.__write_config(filters_codes) self.process = subprocess.Popen(
[ proxy_binary_path, str(self.public_host), str(self.public_port), str(self.internal_host), str(self.internal_port)],
self.process = subprocess.Popen( stdout=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True
[ proxy_binary_path, str(self.public_host), str(self.public_port), str(self.internal_host), str(self.internal_port), self.config_file_path], )
stdout=subprocess.PIPE, universal_newlines=True self.update_config(filters_codes, sendsignal=False)
)
for stdout_line in iter(self.process.stdout.readline, ""): for stdout_line in iter(self.process.stdout.readline, ""):
if stdout_line.startswith("BLOCKED"): if stdout_line.startswith("BLOCKED"):
regex_id = stdout_line.split()[1] regex_id = stdout_line.split()[1]
with self.filter_map_lock: with self.filter_map_lock:
self.filter_map[regex_id].blocked+=1 self.filter_map[regex_id].blocked+=1
if self.callback_blocked_update: self.callback_blocked_update(self.filter_map[regex_id]) if self.callback_blocked_update: self.callback_blocked_update(self.filter_map[regex_id])
self.process.stdout.close() self.process.stdout.close()
return self.process.wait() return self.process.wait()
finally:
self.__delete_config()
def stop(self): def stop(self):
if self.isactive(): if self.isactive():
@@ -84,36 +77,31 @@ class Proxy:
self.start(in_pause=in_pause) self.start(in_pause=in_pause)
return status return status
def __write_config(self, filters_codes): def update_config(self, filters_codes, sendsignal=True):
with open(self.config_file_path,'w') as config_file: with self.update_config_lock:
for line in filters_codes: if (self.isactive()):
config_file.write(line + '\n') self.process.stdin.write(" ".join(filters_codes))
self.process.stdin.write(" END ")
def __delete_config(self): self.process.stdin.flush()
if os.path.exists(self.config_file_path): if sendsignal:
os.remove(self.config_file_path) self.process.send_signal(SIGUSR1)
def reload(self): def reload(self):
if self.isactive(): if self.isactive():
with self.filter_map_lock: with self.filter_map_lock:
self.filter_map = self.compile_filters() self.filter_map = self.compile_filters()
filters_codes = list(self.filter_map.keys()) filters_codes = list(self.filter_map.keys())
self.__write_config(filters_codes) self.update_config(filters_codes)
self.trigger_reload_config()
def isactive(self): def isactive(self):
if self.process and not self.process.poll() is None: if self.process and not self.process.poll() is None:
self.process = None self.process = None
return True if self.process else False return True if self.process else False
def trigger_reload_config(self):
self.process.send_signal(SIGUSR1)
def pause(self): def pause(self):
if self.isactive(): if self.isactive():
self.__write_config([]) self.update_config([])
self.trigger_reload_config()
else: else:
self.start(in_pause=True) self.start(in_pause=True)

View File

@@ -73,13 +73,13 @@ struct regex_rules{
if (arg[0] == '1'){ if (arg[0] == '1'){
regex regex(expr); regex regex(expr);
#ifdef DEBUG #ifdef DEBUG
cerr << "Added case sensitive regex " << expr_str << endl; cerr << "Added case sensitive regex " << expr << endl;
#endif #endif
getByCode(arg[1])->push_back(make_pair(string(arg), regex)); getByCode(arg[1])->push_back(make_pair(string(arg), regex));
} else { } else {
regex regex(expr,regex_constants::icase); regex regex(expr,regex_constants::icase);
#ifdef DEBUG #ifdef DEBUG
cerr << "Added case insensitive regex " << expr_str << endl; cerr << "Added case insensitive regex " << expr << endl;
#endif #endif
getByCode(arg[1])->push_back(make_pair(string(arg), regex)); getByCode(arg[1])->push_back(make_pair(string(arg), regex));
} }
@@ -91,7 +91,6 @@ struct regex_rules{
}; };
shared_ptr<regex_rules> regex_config; shared_ptr<regex_rules> regex_config;
const char* config_file;
mutex update_mutex; mutex update_mutex;
#ifdef MULTI_THREAD #ifdef MULTI_THREAD
mutex stdout_mutex; mutex stdout_mutex;
@@ -393,25 +392,23 @@ namespace tcp_proxy
void update_regex(){ void update_regex(){
#ifdef DEBUG
cerr << "Updating configuration" << endl;
#endif
std::unique_lock<std::mutex> lck(update_mutex); std::unique_lock<std::mutex> lck(update_mutex);
fstream fd;
fd.open(config_file,ios::in);
if (!fd.is_open()){
cerr << "Error: config file couln't be opened" << endl;
exit(1);
}
regex_rules *regex_new_config = new regex_rules(); regex_rules *regex_new_config = new regex_rules();
string line; string data;
while(getline(fd, line)) regex_new_config->add(line.c_str()); while(true){
cin >> data;
if (data == "END") break;
regex_new_config->add(data.c_str());
}
regex_config.reset(regex_new_config); regex_config.reset(regex_new_config);
} }
void signal_handler(int signal_num) void signal_handler(int signal_num)
{ {
if (signal_num == SIGUSR1){ if (signal_num == SIGUSR1){
#ifdef DEBUG
cerr << "Updating configurtation" << endl;
#endif
update_regex(); update_regex();
}else if(signal_num == SIGTERM){ }else if(signal_num == SIGTERM){
if (ios_loop != nullptr) ios_loop->stop(); if (ios_loop != nullptr) ios_loop->stop();
@@ -424,9 +421,9 @@ void signal_handler(int signal_num)
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
if (argc < 6) if (argc < 5)
{ {
cerr << "usage: tcpproxy_server <local host ip> <local port> <forward host ip> <forward port> <config_file>" << endl; cerr << "usage: tcpproxy_server <local host ip> <local port> <forward host ip> <forward port>" << endl;
return 1; return 1;
} }
@@ -434,16 +431,19 @@ int main(int argc, char* argv[])
const unsigned short forward_port = static_cast<unsigned short>(::atoi(argv[4])); const unsigned short forward_port = static_cast<unsigned short>(::atoi(argv[4]));
const string local_host = argv[1]; const string local_host = argv[1];
const string forward_host = argv[3]; const string forward_host = argv[3];
config_file = argv[5];
update_regex(); update_regex();
signal(SIGUSR1, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGUSR1, signal_handler);
boost::asio::io_service ios; boost::asio::io_service ios;
ios_loop = &ios; ios_loop = &ios;
signal(SIGTERM, signal_handler);
#ifdef DEBUG
cerr << "Starting Proxy" << endl;
#endif
try try
{ {
tcp_proxy::bridge::acceptor acceptor(ios, tcp_proxy::bridge::acceptor acceptor(ios,
@@ -470,6 +470,9 @@ int main(int argc, char* argv[])
cerr << "Error: " << e.what() << endl; cerr << "Error: " << e.what() << endl;
return 1; return 1;
} }
#ifdef DEBUG
cerr << "Proxy stopped!" << endl;
#endif
return 0; return 0;
} }