code push
This commit is contained in:
@@ -364,9 +364,9 @@ class PktRequest {
|
||||
#endif
|
||||
if (tcp && ack_seq_offset && packet.size() != _original_size){
|
||||
if (is_input){
|
||||
ack_seq_offset->in += packet.size() - _original_size;
|
||||
ack_seq_offset->in += data_size() - _data_original_size;
|
||||
}else{
|
||||
ack_seq_offset->out += packet.size() - _original_size;
|
||||
ack_seq_offset->out += data_size() - _data_original_size;
|
||||
}
|
||||
}
|
||||
nfq_nlmsg_verdict_put(nlh_verdict, ntohl(packet_id), NF_ACCEPT );
|
||||
|
||||
@@ -72,7 +72,7 @@ PyFilterResponse {
|
||||
|
||||
Every time a packet is received, the packet handler will execute the following code:
|
||||
```python
|
||||
firegex.nfproxy.internals.handle_packet()
|
||||
firegex.nfproxy.internals.handle_packet(globals())
|
||||
````
|
||||
|
||||
The TCP stream is sorted by libtins using c++ code, but the c++ code is not responsabile di buffer the stream, but only to sort those
|
||||
|
||||
@@ -34,7 +34,7 @@ class PyProxyQueue: public NfQueue::ThreadNfQueue<PyProxyQueue> {
|
||||
public:
|
||||
stream_ctx sctx;
|
||||
StreamFollower follower;
|
||||
PyThreadState * gtstate = nullptr;
|
||||
PyThreadState * tstate = nullptr;
|
||||
|
||||
PyInterpreterConfig py_thread_config = {
|
||||
.use_main_obmalloc = 0,
|
||||
@@ -45,15 +45,16 @@ class PyProxyQueue: public NfQueue::ThreadNfQueue<PyProxyQueue> {
|
||||
.check_multi_interp_extensions = 1,
|
||||
.gil = PyInterpreterConfig_OWN_GIL,
|
||||
};
|
||||
PyThreadState *tstate = NULL;
|
||||
NfQueue::PktRequest<PyProxyQueue>* pkt;
|
||||
NfQueue::tcp_ack_seq_ctx* current_tcp_ack = nullptr;
|
||||
|
||||
PyObject* handle_packet_code = nullptr;
|
||||
|
||||
void before_loop() override {
|
||||
PyStatus pystatus;
|
||||
// Create a new interpreter for the thread
|
||||
gtstate = PyThreadState_New(PyInterpreterState_Main());
|
||||
PyEval_AcquireThread(gtstate);
|
||||
tstate = PyThreadState_New(PyInterpreterState_Main());
|
||||
PyEval_AcquireThread(tstate);
|
||||
pystatus = Py_NewInterpreterFromConfig(&tstate, &py_thread_config);
|
||||
if(tstate == nullptr){
|
||||
cerr << "[fatal] [main] Failed to create new interpreter" << endl;
|
||||
@@ -64,6 +65,12 @@ class PyProxyQueue: public NfQueue::ThreadNfQueue<PyProxyQueue> {
|
||||
Py_ExitStatusException(pystatus);
|
||||
throw invalid_argument("Failed to create new interpreter (pystatus exc)");
|
||||
}
|
||||
|
||||
if(!PyGC_IsEnabled()){
|
||||
PyGC_Enable();
|
||||
}
|
||||
|
||||
handle_packet_code = unmarshal_code(py_handle_packet_code);
|
||||
// Setting callbacks for the stream follower
|
||||
follower.new_stream_callback(bind(on_new_stream, placeholders::_1, this));
|
||||
follower.stream_termination_callback(bind(on_stream_close, placeholders::_1, this));
|
||||
@@ -100,11 +107,24 @@ class PyProxyQueue: public NfQueue::ThreadNfQueue<PyProxyQueue> {
|
||||
if (compiled_code == nullptr){
|
||||
stream.client_data_callback(nullptr);
|
||||
stream.server_data_callback(nullptr);
|
||||
stream.ignore_client_data();
|
||||
stream.ignore_server_data();
|
||||
return pkt->accept();
|
||||
}else{
|
||||
try{
|
||||
stream_match = new pyfilter_ctx(compiled_code, handle_packet_code);
|
||||
}catch(invalid_argument& e){
|
||||
cerr << "[error] [filter_action] Failed to create the filter context" << endl;
|
||||
print_exception_reason();
|
||||
sctx.clean_stream_by_id(pkt->sid);
|
||||
stream.client_data_callback(nullptr);
|
||||
stream.server_data_callback(nullptr);
|
||||
stream.ignore_client_data();
|
||||
stream.ignore_server_data();
|
||||
return pkt->accept();
|
||||
}
|
||||
sctx.streams_ctx.insert_or_assign(pkt->sid, stream_match);
|
||||
}
|
||||
stream_match = new pyfilter_ctx(compiled_code);
|
||||
Py_DECREF(compiled_code);
|
||||
sctx.streams_ctx.insert_or_assign(pkt->sid, stream_match);
|
||||
}else{
|
||||
stream_match = stream_search->second;
|
||||
}
|
||||
@@ -140,6 +160,8 @@ class PyProxyQueue: public NfQueue::ThreadNfQueue<PyProxyQueue> {
|
||||
print_exception_reason();
|
||||
sctx.clean_stream_by_id(pkt->sid);
|
||||
//Free the packet data
|
||||
stream.ignore_client_data();
|
||||
stream.ignore_server_data();
|
||||
stream.client_data_callback(nullptr);
|
||||
stream.server_data_callback(nullptr);
|
||||
return pkt->accept();
|
||||
@@ -233,6 +255,7 @@ class PyProxyQueue: public NfQueue::ThreadNfQueue<PyProxyQueue> {
|
||||
PyEval_ReleaseThread(tstate);
|
||||
PyThreadState_Clear(tstate);
|
||||
PyThreadState_Delete(tstate);
|
||||
Py_DECREF(handle_packet_code);
|
||||
|
||||
sctx.clean();
|
||||
}
|
||||
|
||||
@@ -16,9 +16,13 @@ namespace PyProxy {
|
||||
class PyCodeConfig;
|
||||
|
||||
shared_ptr<PyCodeConfig> config;
|
||||
PyObject* py_handle_packet_code = nullptr;
|
||||
UnixClientConnection control_socket;
|
||||
|
||||
PyObject* unmarshal_code(string encoded_code){
|
||||
if (encoded_code.empty()) return nullptr;
|
||||
return PyMarshal_ReadObjectFromString(encoded_code.c_str(), encoded_code.size());
|
||||
}
|
||||
|
||||
class PyCodeConfig{
|
||||
public:
|
||||
string encoded_code;
|
||||
@@ -32,22 +36,24 @@ class PyCodeConfig{
|
||||
PyObject* glob = PyDict_New();
|
||||
PyObject* result = PyEval_EvalCode(compiled_code, glob, glob);
|
||||
Py_DECREF(glob);
|
||||
if (!result){
|
||||
if (PyErr_Occurred()){
|
||||
PyErr_Print();
|
||||
Py_DECREF(compiled_code);
|
||||
std::cerr << "[fatal] [main] Failed to execute the code" << endl;
|
||||
throw invalid_argument("Failed to execute the code, maybe an invalid filter code has been provided");
|
||||
}
|
||||
Py_DECREF(result);
|
||||
Py_XDECREF(result);
|
||||
PyObject* code_dump = PyMarshal_WriteObjectToString(compiled_code, 4);
|
||||
Py_DECREF(compiled_code);
|
||||
if (code_dump == nullptr){
|
||||
PyErr_Print();
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
std::cerr << "[fatal] [main] Failed to dump the code" << endl;
|
||||
throw invalid_argument("Failed to dump the code");
|
||||
}
|
||||
if (!PyBytes_Check(code_dump)){
|
||||
std::cerr << "[fatal] [main] Failed to dump the code" << endl;
|
||||
Py_DECREF(code_dump);
|
||||
throw invalid_argument("Failed to dump the code");
|
||||
}
|
||||
encoded_code = string(PyBytes_AsString(code_dump), PyBytes_Size(code_dump));
|
||||
@@ -55,8 +61,7 @@ class PyCodeConfig{
|
||||
}
|
||||
|
||||
PyObject* compiled_code(){
|
||||
if (encoded_code.empty()) return nullptr;
|
||||
return PyMarshal_ReadObjectFromString(encoded_code.c_str(), encoded_code.size());
|
||||
return unmarshal_code(encoded_code);
|
||||
}
|
||||
|
||||
PyCodeConfig(){}
|
||||
@@ -69,16 +74,27 @@ void init_control_socket(){
|
||||
control_socket = UnixClientConnection(socket_path);
|
||||
}
|
||||
|
||||
string py_handle_packet_code;
|
||||
|
||||
void init_handle_packet_code(){
|
||||
py_handle_packet_code = Py_CompileStringExFlags(
|
||||
"firegex.nfproxy.internals.handle_packet()\n", "<pyfilter>",
|
||||
PyObject* compiled_code = Py_CompileStringExFlags(
|
||||
"firegex.nfproxy.internals.handle_packet(globals())\n", "<pyfilter>",
|
||||
Py_file_input, NULL, 2);
|
||||
|
||||
if (py_handle_packet_code == nullptr){
|
||||
std::cerr << "[fatal] [main] Failed to compile the utility python code (strange behaviour, probably a bug)" << endl;
|
||||
throw invalid_argument("Failed to compile the code");
|
||||
PyObject* code_dump = PyMarshal_WriteObjectToString(compiled_code, 4);
|
||||
Py_DECREF(compiled_code);
|
||||
if (code_dump == nullptr){
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
std::cerr << "[fatal] [main] Failed to dump the code" << endl;
|
||||
throw invalid_argument("Failed to dump the code");
|
||||
}
|
||||
if (!PyBytes_Check(code_dump)){
|
||||
std::cerr << "[fatal] [main] Failed to dump the code" << endl;
|
||||
Py_DECREF(code_dump);
|
||||
throw invalid_argument("Failed to dump the code");
|
||||
}
|
||||
py_handle_packet_code = string(PyBytes_AsString(code_dump), PyBytes_Size(code_dump));
|
||||
Py_DECREF(code_dump);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -55,11 +55,15 @@ typedef Tins::TCPIP::StreamIdentifier stream_id;
|
||||
struct pyfilter_ctx {
|
||||
|
||||
PyObject * glob = nullptr;
|
||||
PyObject * py_handle_packet = nullptr;
|
||||
|
||||
pyfilter_ctx(PyObject * compiled_code){
|
||||
pyfilter_ctx(PyObject * compiled_code, PyObject * handle_packet_code){
|
||||
py_handle_packet = handle_packet_code;
|
||||
Py_INCREF(py_handle_packet);
|
||||
glob = PyDict_New();
|
||||
PyObject* result = PyEval_EvalCode(compiled_code, glob, glob);
|
||||
if (!result){
|
||||
Py_XDECREF(compiled_code);
|
||||
if (PyErr_Occurred()){
|
||||
PyErr_Print();
|
||||
Py_XDECREF(glob);
|
||||
std::cerr << "[fatal] [main] Failed to compile the code" << endl;
|
||||
@@ -69,7 +73,10 @@ struct pyfilter_ctx {
|
||||
}
|
||||
|
||||
~pyfilter_ctx(){
|
||||
cerr << "[info] [pyfilter_ctx] Cleaning pyfilter_ctx" << endl;
|
||||
Py_DECREF(glob);
|
||||
Py_DECREF(py_handle_packet);
|
||||
PyGC_Collect();
|
||||
}
|
||||
|
||||
inline void set_item_to_glob(const char* key, PyObject* value){
|
||||
@@ -82,14 +89,16 @@ struct pyfilter_ctx {
|
||||
|
||||
void del_item_from_glob(const char* key){
|
||||
if (PyDict_DelItemString(glob, key) != 0){
|
||||
PyErr_Print();
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
throw invalid_argument("Failed to delete item from dict");
|
||||
}
|
||||
}
|
||||
|
||||
inline void set_item_to_dict(PyObject* dict, const char* key, PyObject* value){
|
||||
if (PyDict_SetItemString(dict, key, value) != 0){
|
||||
PyErr_Print();
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
throw invalid_argument("Failed to set item to dict");
|
||||
}
|
||||
Py_DECREF(value);
|
||||
@@ -111,11 +120,18 @@ struct pyfilter_ctx {
|
||||
|
||||
// Set packet info to the global context
|
||||
set_item_to_glob("__firegex_packet_info", packet_info);
|
||||
PyObject * result = PyEval_EvalCode(py_handle_packet_code, glob, glob);
|
||||
#ifdef DEBUG
|
||||
cerr << "[DEBUG] [handle_packet] Calling python with a data of " << data.size() << endl;
|
||||
#endif
|
||||
PyObject * result = PyEval_EvalCode(py_handle_packet, glob, glob);
|
||||
PyGC_Collect();
|
||||
#ifdef DEBUG
|
||||
cerr << "[DEBUG] [handle_packet] End of python call" << endl;
|
||||
#endif
|
||||
del_item_from_glob("__firegex_packet_info");
|
||||
|
||||
Py_DECREF(packet_info);
|
||||
if (!result){
|
||||
if (PyErr_Occurred()){
|
||||
cerr << "[error] [handle_packet] Failed to execute the code " << result << endl;
|
||||
PyErr_Print();
|
||||
#ifdef DEBUG
|
||||
cerr << "[DEBUG] [handle_packet] Exception raised" << endl;
|
||||
@@ -134,7 +150,9 @@ struct pyfilter_ctx {
|
||||
}
|
||||
|
||||
if (!PyDict_Check(result)){
|
||||
PyErr_Print();
|
||||
if (PyErr_Occurred()){
|
||||
PyErr_Print();
|
||||
}
|
||||
#ifdef DEBUG
|
||||
cerr << "[DEBUG] [handle_packet] Result is not a dict" << endl;
|
||||
#endif
|
||||
|
||||
@@ -78,7 +78,7 @@ class FiregexInterceptor:
|
||||
await run_func(self.outstrem_function, self.srv.id, line)
|
||||
|
||||
async def _start_binary(self):
|
||||
proxy_binary_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),"../cpproxy")
|
||||
proxy_binary_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../cpproxy"))
|
||||
self.process = await asyncio.create_subprocess_exec(
|
||||
proxy_binary_path, stdin=asyncio.subprocess.DEVNULL,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
|
||||
Reference in New Issue
Block a user