Read config from stdin
This commit is contained in:
@@ -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,24 +38,19 @@ 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(
|
self.process = subprocess.Popen(
|
||||||
[ proxy_binary_path, str(self.public_host), str(self.public_port), str(self.internal_host), str(self.internal_port), self.config_file_path],
|
[ proxy_binary_path, str(self.public_host), str(self.public_port), str(self.internal_host), str(self.internal_port)],
|
||||||
stdout=subprocess.PIPE, universal_newlines=True
|
stdout=subprocess.PIPE, stdin=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]
|
||||||
@@ -63,9 +59,6 @@ class Proxy:
|
|||||||
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 ")
|
||||||
|
self.process.stdin.flush()
|
||||||
|
if sendsignal:
|
||||||
|
self.process.send_signal(SIGUSR1)
|
||||||
|
|
||||||
def __delete_config(self):
|
|
||||||
if os.path.exists(self.config_file_path):
|
|
||||||
os.remove(self.config_file_path)
|
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,15 +432,18 @@ int main(int argc, char* argv[])
|
|||||||
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(SIGUSR1, signal_handler);
|
||||||
signal(SIGTERM, 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;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user