diff --git a/.gitignore b/.gitignore index be0de155..9515fb56 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ ltmain.sh examples/simple_example_using_c/test /tools/rules-check/modsec-rules-check examples/multiprocess_c/multi +examples/multithread/multithread examples/reading_logs_via_rule_message/simple_request examples/reading_logs_with_offset/read examples/using_bodies_in_chunks/simple_request diff --git a/build/win32/CMakeLists.txt b/build/win32/CMakeLists.txt index 1e6303fd..cebf4c9b 100644 --- a/build/win32/CMakeLists.txt +++ b/build/win32/CMakeLists.txt @@ -259,6 +259,10 @@ setExampleTargetProperties(reading_logs_via_rule_message) add_executable(reading_logs_with_offset ${BASE_DIR}/examples/reading_logs_with_offset/read.cc) setExampleTargetProperties(reading_logs_with_offset) +# multithread +add_executable(multithread ${BASE_DIR}/examples/multithread/multithread.cc) +setExampleTargetProperties(multithread) + # tools # diff --git a/build/win32/README.md b/build/win32/README.md index 7b70cfbd..85fd868e 100644 --- a/build/win32/README.md +++ b/build/win32/README.md @@ -51,6 +51,7 @@ Built files will be located in the directory: `build\win32\build\[build_configur * `using_bodies_in_chunks.exe` * `reading_logs_via_rule_message.exe` * `reading_logs_with_offset.exe` + * `multithread.exe` * Executable files for tools * `rules_check.exe` diff --git a/configure.ac b/configure.ac index 3a0fbb48..34281a3f 100644 --- a/configure.ac +++ b/configure.ac @@ -423,6 +423,7 @@ AM_COND_IF([EXAMPLES], examples/Makefile \ examples/simple_example_using_c/Makefile \ examples/multiprocess_c/Makefile \ + examples/multithread/Makefile \ examples/reading_logs_with_offset/Makefile \ examples/reading_logs_via_rule_message/Makefile \ examples/using_bodies_in_chunks/Makefile \ diff --git a/examples/Makefile.am b/examples/Makefile.am index 609cb93e..2dbb21ac 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -4,6 +4,7 @@ ACLOCAL_AMFLAGS = -I build SUBDIRS = \ multiprocess_c \ + multithread \ reading_logs_with_offset \ reading_logs_via_rule_message \ simple_example_using_c \ diff --git a/examples/multithread/Makefile.am b/examples/multithread/Makefile.am new file mode 100644 index 00000000..40e81dd1 --- /dev/null +++ b/examples/multithread/Makefile.am @@ -0,0 +1,54 @@ + + +noinst_PROGRAMS = multithread + +multithread_SOURCES = \ + multithread.cc + +multithread_LDADD = \ + $(CURL_LDADD) \ + $(GEOIP_LDADD) \ + $(GLOBAL_LDADD) \ + $(LIBXML2_LDADD) \ + $(LMDB_LDADD) \ + $(MAXMIND_LDADD) \ + $(LUA_LDADD) \ + $(PCRE_LDADD) \ + $(SSDEEP_LDADD) \ + $(YAJL_LDADD) + +multithread_LDFLAGS = \ + -L$(top_builddir)/src/.libs/ \ + $(GEOIP_LDFLAGS) \ + -lmodsecurity \ + -lm \ + -lstdc++ \ + $(LMDB_LDFLAGS) \ + $(LUA_LDFLAGS) \ + $(MAXMIND_LDFLAGS) \ + $(SSDEEP_LDFLAGS) \ + $(YAJL_LDFLAGS) + +multithread_CPPFLAGS = \ + $(GLOBAL_CFLAGS) \ + -I$(top_builddir)/headers \ + -I$(top_builddir) \ + -g \ + -I../others \ + -fPIC \ + -O3 \ + $(CURL_CFLAGS) \ + $(GEOIP_CFLAGS) \ + $(GLOBAL_CPPFLAGS) \ + $(MODSEC_NO_LOGS) \ + $(YAJL_CFLAGS) \ + $(LMDB_CFLAGS) \ + $(LUA_CFLAGS) \ + $(PCRE_CFLAGS) \ + $(LIBXML2_CFLAGS) + + +MAINTAINERCLEANFILES = \ + Makefile.in + + diff --git a/examples/multithread/basic_rules.conf b/examples/multithread/basic_rules.conf new file mode 100644 index 00000000..cff18342 --- /dev/null +++ b/examples/multithread/basic_rules.conf @@ -0,0 +1,14 @@ +SecDebugLog debug.log +SecDebugLogLevel 9 + + +SecRule REQUEST_HEADERS:User-Agent ".*" "id:1,phase:1,t:sha1,t:hexEncode,setvar:tx.ua_hash=%{MATCHED_VAR}" + +SecAction "id:2,phase:2,initcol:ip=%{REMOTE_ADDR}_%{tx.ua_hash}" + +SecRule REQUEST_HEADERS:User-Agent "@rx .*" "id:3,phase:2,setvar:ip.auth_attempt=+1" + +SecRule ARGS:foo "@rx herewego" "id:4,phase:2,setvar:ip.foo=bar,expirevar:ip.foo=2" +#SecRule ARGS:foo "@rx herewego" "id:4,phase:2,setvar:ip.foo=bar" +SecRule IP "@rx bar" "id:5,phase:2,pass" +SecRule IP:auth_attempt "@rx bar" "id:6,phase:2,pass" diff --git a/examples/multithread/multithread.cc b/examples/multithread/multithread.cc new file mode 100644 index 00000000..4233bc71 --- /dev/null +++ b/examples/multithread/multithread.cc @@ -0,0 +1,68 @@ +#include +#include +#include + +#include +#include +#include + +static void process_request(modsecurity::ModSecurity *modsec, modsecurity::RulesSet *rules, int tid) { + std::cout << "Hello World! It's me, thread #" << tid << std::endl; + + for(int i = 0; i != 1'000; i++) { + auto modsecTransaction = std::make_unique(modsec, rules, nullptr); + + modsecTransaction->processConnection("127.0.0.1", 12345, "127.0.0.1", 80); + modsecTransaction->processURI( + "https://www.modsecurity.org/test?foo=herewego", + "GET", "1.1"); + + modsecTransaction->addRequestHeader("User-Agent", + "Basic ModSecurity example"); + modsecTransaction->processRequestHeaders(); + modsecTransaction->processRequestBody(); + + modsecTransaction->addResponseHeader("HTTP/1.1", + "200 OK"); + modsecTransaction->processResponseHeaders(200, "HTTP 1.2"); + modsecTransaction->processResponseBody(); + + modsecTransaction->processLogging(); + + std::this_thread::sleep_for(std::chrono::microseconds(100)); + } + + std::cout << "Thread #" << tid << " exits" << std::endl; +} + +int main (int argc, char *argv[]) { + auto modsec = std::make_unique(); + modsec->setConnectorInformation("ModSecurity-test v0.0.1-alpha (Simple " \ + "example on how to use ModSecurity API"); + + char main_rule_uri[] = "basic_rules.conf"; + auto rules = std::make_unique(); + if (rules->loadFromUri(main_rule_uri) < 0) { + std::cerr << "Problems loading the rules..." << std::endl; + std::cerr << rules->m_parserError.str() << std::endl; + return -1; + } + + constexpr auto NUM_THREADS = 100; + std::array threads; + + for (auto i = 0; i != threads.size(); ++i) { + threads[i] = std::thread( + [&modsec, &rules, i]() { + process_request(modsec.get(), rules.get(), i); + }); + } + + std::this_thread::sleep_for(std::chrono::microseconds(10000)); + + for (auto i = 0; i != threads.size(); ++i) { + threads[i].join(); + } + + return 0; +} \ No newline at end of file