Add docket support

This commit is contained in:
Ned Wright
2022-10-25 14:45:02 +00:00
parent 09847ac179
commit 3703b14ba6
71 changed files with 7126 additions and 2644 deletions

View File

@@ -1 +1,2 @@
add_subdirectory(nginx_attachment_util)
add_subdirectory(ngx_module)

View File

@@ -1,5 +1,6 @@
add_definitions(-DUSERSPACE)
add_library(osrc_nginx_attachment_util SHARED nginx_attachment_util.cc)
target_link_libraries(osrc_nginx_attachment_util http_configuration)
install(TARGETS osrc_nginx_attachment_util DESTINATION lib)

View File

@@ -83,6 +83,18 @@ getFailOpenTimeout()
return conf_data.getNumericalValue("fail_open_timeout");
}
int
isFailOpenHoldMode()
{
return conf_data.getNumericalValue("is_fail_open_mode_hold_enabled");
}
unsigned int
getFailOpenHoldTimeout()
{
return conf_data.getNumericalValue("fail_open_hold_timeout");
}
unsigned int
getMaxSessionsPerMinute()
{
@@ -137,6 +149,12 @@ getResBodyThreadTimeout()
return conf_data.getNumericalValue("res_body_thread_timeout_msec");
}
unsigned int
getWaitingForVerdictThreadTimeout()
{
return conf_data.getNumericalValue("waiting_for_verdict_thread_timeout_msec");
}
int
isIPAddress(c_str ip_str)
{

View File

@@ -0,0 +1,48 @@
MACRO(CREATE_INCLUDE_LIST result)
file(READ ${CMAKE_INSTALL_PREFIX}/nginx-src/include_paths.mk relative_includes)
STRING(REGEX REPLACE "\n" ";" relative_includes "${relative_includes}")
set(inclist "")
FOREACH(include ${relative_includes})
if(NOT include MATCHES "^/")
set(inclist ${inclist} "${CMAKE_INSTALL_PREFIX}/nginx-src/${include}")
else()
set(inclist ${inclist} "${include}")
endif()
ENDFOREACH()
set(${result} ${inclist})
ENDMACRO()
MACRO(READ_COMPILE_FLAGS result)
file(READ ${CMAKE_INSTALL_PREFIX}/nginx-src/cc_flags.mk CC_FLAGS)
string(REGEX REPLACE "\n" "" CC_FLAGS "${CC_FLAGS}")
set(flag_list "")
FOREACH(flag ${CC_FLAGS})
if (flag MATCHES "-fstack-clash-protection" OR flag MATCHES "-fcf-protection" OR flag MATCHES "-Wno-cast-function-type")
continue()
endif()
set(flag_list ${flag_list} "${flag}")
ENDFOREACH()
separate_arguments(flag_list)
set(${result} ${flag_list})
ENDMACRO()
add_library(
ngx_module
SHARED
ngx_http_cp_attachment_module.c ngx_cp_thread.c ngx_cp_hook_threads.c ngx_cp_hooks.c ngx_cp_utils.c
ngx_cp_initializer.c ngx_cp_io.c ngx_cp_static_content.c ngx_cp_custom_response.c ngx_modules.c
ngx_cp_compression.c ngx_cp_http_parser.c ngx_cp_failing_state.c ngx_cp_metric.c
)
add_dependencies(ngx_module osrc_shmem_ipc osrc_nginx_attachment_util osrc_compression_utils)
target_link_libraries(ngx_module osrc_shmem_ipc osrc_nginx_attachment_util osrc_compression_utils)
CREATE_INCLUDE_LIST(NGX_INCLUDES)
READ_COMPILE_FLAGS(CC_FLAG_LIST)
target_include_directories(ngx_module PRIVATE ${NGX_INCLUDES})
target_compile_options(ngx_module PRIVATE ${CC_FLAG_LIST})
install(TARGETS ngx_module DESTINATION lib)

View File

@@ -0,0 +1,66 @@
#!/bin/bash
NGINX_VERSION_CONF_INPUT_PATH=/tmp/nginx.sourcefile.ver
if [ "${1}" == "--docker" ]; then
docker run -it ${2} nginx -V > ${NGINX_VERSION_CONF_INPUT_PATH}
elif [ "${1}" == "--conf" ]; then
cp ${2} ${NGINX_VERSION_CONF_INPUT_PATH}
else
echo "Usage: ${0} [--conf <input nginx compilation flags file> | --docker <input docker name>] <compilation artifacts directory>"
exit 1
fi
NGINX_VERSION_CONF_OUTPUT_PATH=/tmp/nginx.sourcefile.conf
$(dirname $0)/nginx_version_extractor.sh -i ${NGINX_VERSION_CONF_INPUT_PATH} -o ${NGINX_VERSION_CONF_OUTPUT_PATH}
BUILD_OUTPUT_DIR=${3}
if [[ ${BUILD_OUTPUT_DIR} != /* ]]; then
BUILD_OUTPUT_DIR=$(pwd)/${BUILD_OUTPUT_DIR}
fi
source ${NGINX_VERSION_CONF_OUTPUT_PATH}
CURRENT_PWD=$(pwd)
mkdir -p ${BUILD_OUTPUT_DIR}
cd ${BUILD_OUTPUT_DIR}
wget --no-check-certificate https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
tar -xzvf nginx-${NGINX_VERSION}.tar.gz
rm nginx-${NGINX_VERSION}.tar.gz
mv nginx-${NGINX_VERSION} nginx-src
cd nginx-src
if test ! -f configured.ok; then
echo "Configuring nginx compiler: ./configure ${CONFIGURE_OPT} --with-cc-opt=\"${EXTRA_CC_OPT} ${LOCAL_CC_OPT}\" && touch configured.ok"
./configure ${CONFIGURE_OPT} --with-cc-opt="${EXTRA_CC_OPT} ${LOCAL_CC_OPT}" && touch configured.ok
else
echo "Nginx compiler already Configured...\n"
fi
make && echo "${EXTRA_CC_OPT}" > cc_flags.mk
OUTPUT_FILE_NAME=include_paths.mk
ALL_INCS=$(cat objs/Makefile|grep -v \$\(ALL_INCS\) | awk '/ALL_INCS/' RS="\n\n" ORS="\n\n" | tr '\\' ' ')
ALL_INCS=${ALL_INCS/ALL_INCS =/}
ALL_INCS=$(sed "s/-I//g" <<< "${ALL_INCS}")
echo > include_paths.mk
for include in ${ALL_INCS}; do
echo $include >> include_paths.mk
done
cd ${CURRENT_PWD}
if [ "${1}" == "--docker" ]; then
cp -f $(dirname $0)/../../../docker/Dockerfile ${BUILD_OUTPUT_DIR}/Dockerfile
sed -i "s|<DOCKER BASE IMAGE>|${2}|g" ${BUILD_OUTPUT_DIR}/Dockerfile
docker run -it ${2} whoami > /tmp/usertouse
USER_NAME="$(cat /tmp/usertouse)"
rm /tmp/usertouse
sed -i "s|<DOCKER USER>|${USER_NAME}|g" ${BUILD_OUTPUT_DIR}/Dockerfile
fi

View File

@@ -0,0 +1,347 @@
#!/bin/bash
initializeEnviroment()
{
CURRENT_TIME=""
PACKAGE_VERSION=""
CUR_NGINX_ALREADY_SUPPORTED=false
NUMBER_OF_CONFIGURATION_FLAGS=0
TMP_NGINX_UNPARSED_CONFIGURATION="/tmp/nginx_unparsed_tmp_conf.txt"
TMP_NGINX_PARSED_CONFIGURATION_FLAGS="/tmp/nginx_parsed_conf_flags.txt"
TMP_DECODED_FILE_PATH="/tmp/decoded_file.txt"
IS_ALPINE=false
if [ ! -z "$(cat /etc/*release | grep alpine)" ]; then
IS_ALPINE=true
fi
}
usage()
{
local IS_ERROR=$1
local option=$2
if [[ ${IS_ERROR} == true ]]; then
echo "Error: unsupported option '${option}'"
fi
echo "Usage:"
line_padding=" "
local debug_print_option="-h, --help"
printf "%s %s Print (this) help message\n" "$debug_print_option" "${line_padding:${#debug_print_option}}"
debug_print_option="-d, --debug"
printf "%s %s Enable debug mode\n" "$debug_print_option" "${line_padding:${#debug_print_option}}"
debug_print_option="-v, --verbose"
printf "%s %s show version and configure options\n" "$debug_print_option" "${line_padding:${#debug_print_option}}"
debug_print_option="-o, --output"
printf "%s %s change output file name into '${option}'\n" "$debug_print_option" "${line_padding:${#debug_print_option}}"
debug_print_option="-f, --force"
printf "%s %s force creation of makefile'\n" "$debug_print_option" "${line_padding:${#debug_print_option}}"
if [[ ${IS_ERROR} == true ]]; then
exit -1
else
exit 1
fi
}
debug()
{
local debug_message=$1
if [[ $IS_DEBUG_MODE_ACTIVE == true ]]; then
echo -e $debug_message
fi
}
check_flags_options()
{
local argc=$#
for (( i = 1; i <= $argc; i++ )); do
local option=${!i}
local IS_ERROR=false
if [[ "$option" == "--debug" || "$option" == "-d" ]]; then
IS_DEBUG_MODE_ACTIVE=true
elif [[ "$option" == "--verbose" || "$option" == "-v" ]]; then
IS_VERBOSE_MODE_ACTIVE=true
elif [[ "$option" == "--force" || "$option" == "-f" ]]; then
IS_FORCE_OUTPUT=true
elif [[ "$option" == "--output" || "$option" == "-o" ]]; then
IS_OUTPUT_NAME_MODE_ACTIVE=true
i=$((i+1))
FILE_NAME=${!i}
if [[ -z ${FILE_NAME} ]]; then
echo "Error: No file name was given for ${option} option."
exit -1
fi
elif [[ "$option" == "--input" || "$option" == "-i" ]]; then
i=$((i+1))
if [[ -z ${!i} ]]; then
echo "Error: No file name was given for ${option} option."
exit -1
fi
cp -f ${!i} ${TMP_NGINX_UNPARSED_CONFIGURATION}
IS_INPUT_NAME_MODE_ACTIVE=true
elif [[ "$option" == "--help" || "$option" == "-h" ]]; then
usage ${IS_ERROR} ${option}
elif [[ ! -z $option ]]; then
IS_ERROR=true
usage ${IS_ERROR} ${option}
fi
done
}
_main()
{
echo "Starting verification of Check Point support with local nginx server"
initializeEnviroment
if [[ ${IS_INPUT_NAME_MODE_ACTIVE} != true ]]; then
nginx -V &> "$TMP_NGINX_UNPARSED_CONFIGURATION"
fi
getNginxVersion
if [[ $IS_VERBOSE_MODE_ACTIVE == true ]]; then
echo ""
cat ${TMP_NGINX_UNPARSED_CONFIGURATION}
echo ""
fi
while IFS= read -ra UNPARSED_CONFIGURATION_LINE <&3; do
if [[ ${UNPARSED_CONFIGURATION_LINE} =~ ^"nginx version:" ]]; then
openFile
elif [[ ${UNPARSED_CONFIGURATION_LINE} =~ ^"built by gcc" ]]; then
addBuiltConfiguration "${UNPARSED_CONFIGURATION_LINE}"
elif [[ ${UNPARSED_CONFIGURATION_LINE} =~ ^"configure arguments:" ]]; then
IFS="'"
addAndCutOptionalFlags ${UNPARSED_CONFIGURATION_LINE}
IFS=" "
addRequiredFlags ${CONFIGURATION_FLAGES_NEED_TO_BE_PARSED}
fi
done 3<"$TMP_NGINX_UNPARSED_CONFIGURATION"
PARSED_CONFIGURATION="CONFIGURE_OPT=\"${COMBINED_CONFIGURATION_FLAGS}\"\n\n"
NUMBER_OF_CONFIGURATION_FLAGS=$((NUMBER_OF_CONFIGURATION_FLAGS-1))
local local_pwd=$(pwd)
if [[ ${local_pwd:0:2} == "//" ]]; then
local_pwd=${local_pwd:1}
fi
debug "Moving parsed configuration to target ${local_pwd}/${FILE_NAME} configuration file"
echo -e ${PARSED_CONFIGURATION} > ${FILE_NAME}
echo -e ${CC_OPTIONAL_FLAGS} >> ${FILE_NAME}
add_nginx_and_release_versions
if [[ $CUR_NGINX_ALREADY_SUPPORTED == true ]]; then
tearDown
echo -e "Check Point Nano Agent already supported on this environment"
else
tearDown
echo -e "Extracted environment data to $(pwd)/${FILE_NAME} \nPlease send file to nano-agent-attachments-support@checkpoint.com"
fi
}
tearDown()
{
rm -f ${TMP_NGINX_UNPARSED_CONFIGURATION}
rm -f ${TMP_NGINX_PARSED_CONFIGURATION_FLAGS}
rm -f ${TMP_DECODED_FILE_PATH}
rm -f ${TMP_NGINX_VERSION_FILE}
}
getNginxVersion()
{
TMP_NGINX_VERSION_FILE="/tmp/nginx_version_file.txt"
cat ${TMP_NGINX_UNPARSED_CONFIGURATION} | grep "nginx version:" &> "$TMP_NGINX_VERSION_FILE"
if [[ $IS_ALPINE == true ]]; then
NGINX_VERSION=`cat ${TMP_NGINX_VERSION_FILE} | grep -oE [0-9]+.[0-9]+.[0-9]+`
else
NGINX_VERSION=`cat ${TMP_NGINX_VERSION_FILE} | grep -oP [0-9]+.[0-9]+.[0-9]+`
fi
}
openFile()
{
if [[ ${IS_OUTPUT_NAME_MODE_ACTIVE} != true ]]; then
FILE_NAME="${NGINX_VERSION}.mk"
debug "Trying to create an empty ${NGINX_VERSION} file"
FILE_NAME_PATH="$(pwd)/${FILE_NAME}"
if [[ -z ${FILE_NAME_PATH} || ! ( ${FILE_NAME} =~ [0-9]+.[0-9]+.[0-9]+.mk ) ]]; then
echo "ERROR: can't find nginx version."
exit -1
fi
if [[ -f "${FILE_NAME_PATH}" ]]; then
echo "The output file: ${FILE_NAME} already exists. Do you want to overwrite this file? [y/N]"
read answer
if [[ ${answer} != "y" ]]; then
echo -e "Stopping after the operation was cancelled.\nIf you wish to use other output file name you can use option -o or --output"
exit -1
fi
fi
else
debug "Trying to create an empty ${FILE_NAME} file"
FILE_NAME_PATH="${FILE_NAME}"
fi
touch ${FILE_NAME_PATH} &> /dev/null
if [ ! -e ${FILE_NAME_PATH} ];then
echo "Failed to create ${FILE_NAME_PATH}"
exit -1
fi
debug "Created an empty ${FILE_NAME} file"
}
checkAllDBLineFlags()
{
local argc=$#
local argv=("$@")
local number_of_db_line_flags=$((argc-3))
local gcc_version_prefix="--with-cc="
if [[ ${number_of_db_line_flags} == ${NUMBER_OF_CONFIGURATION_FLAGS} ]]; then
for ((i = 3; i < ${argc}; i++)); do
if [[ ${argv[i]} =~ ^"${gcc_version_prefix}"* ]]; then
continue
fi
checkFlag ${argv[i]}
if [[ ${found_equal_flag} == false ]]; then
EQUAL_FLAGS=false
return
fi
done
else return
fi
EQUAL_FLAGS=true
}
checkFlag()
{
found_equal_flag=false
db_flag=$1
while IFS='\' read -ra flag; do
if [[ "${flag}" == "${db_flag}" ]] || [[ "${flag} " == "${db_flag}" ]]; then
found_equal_flag=true
break
fi
done < ${TMP_NGINX_PARSED_CONFIGURATION_FLAGS}
}
addBuiltConfiguration()
{
BUILT_BY_GCC_FLAG_PREFIX="--with-cc=/usr/bin/"
if [[ $IS_ALPINE == true ]]; then
GCC_VERSION=`echo "$1" | grep -oE "gcc "[0-9]+ | tr ' ' '-'`
else
GCC_VERSION=`echo "$1" | grep -oP "gcc "[0-9]+ | tr ' ' '-'`
fi
if [[ "$GCC_VERSION" == "gcc-4" ]]; then
GCC_VERSION=gcc-5
elif [[ "$GCC_VERSION" == "gcc-10" ]] || [[ "$GCC_VERSION" == "gcc-11" ]]; then
GCC_VERSION=gcc-8
fi
BUILT_BY_GCC_FLAG=" \\\\\n${BUILT_BY_GCC_FLAG_PREFIX}${GCC_VERSION}"
NUMBER_OF_CONFIGURATION_FLAGS=$((NUMBER_OF_CONFIGURATION_FLAGS+1))
}
addAndCutOptionalFlags()
{
debug "Parsing all nginx configuration flags"
CC_EXTRA_PREFIX="EXTRA_CC_OPT="
CC_OPTIONAL_FLAG_PREFIX="--with-cc-opt="
LD_OPTIONAL_FLAG_PREFIX="--with-ld-opt="
local argc=$#
local argv=("$@")
for (( i = 0; i < $argc; i++ )); do
if [[ ${argv[i]} == *"${CC_OPTIONAL_FLAG_PREFIX}"* ]]; then
debug "Successfully added compilation flags"
CONFIGURATION_FLAGES_NEED_TO_BE_PARSED="${CONFIGURATION_FLAGES_NEED_TO_BE_PARSED}${argv[i]}"
i=$((i+1))
IFS=" "
addCCFlagsWithoutSpecsLocalFlag ${argv[i]}
CC_OPTIONAL_FLAGS="${CC_EXTRA_PREFIX}\"${CC_OPTIONAL_FLAGS}\""
elif [[ ${argv[i]} == *"${LD_OPTIONAL_FLAG_PREFIX}"* ]]; then
CONFIGURATION_FLAGES_NEED_TO_BE_PARSED="${CONFIGURATION_FLAGES_NEED_TO_BE_PARSED}${argv[i]}"
i=$((i+1))
else
CONFIGURATION_FLAGES_NEED_TO_BE_PARSED="${CONFIGURATION_FLAGES_NEED_TO_BE_PARSED}${argv[i]}"
fi
done
debug "Successfully finished adding optional flags"
}
addCCFlagsWithoutSpecsLocalFlag()
{
local argc=$#
local argv=("$@")
SPECS_FLAG_PREFIX="-specs="
NO_ERROR_PREFIX="-Wno-error="
FCF_PROTECTION_PREFIX="-fcf-protection"
FSTACK_PREFIX="-fstack-clash-protection"
for (( j = 0; j < $argc; j++ )); do
if [[ ! ${argv[j]} =~ ^${SPECS_FLAG_PREFIX} ]] && \
[[ ! ${argv[j]} =~ ^${NO_ERROR_PREFIX} ]] && \
[[ ! ${argv[j]} =~ ^${FSTACK_PREFIX} ]] && \
[[ ! ${argv[j]} =~ ^${FCF_PROTECTION_PREFIX} ]]; \
then
CC_OPTIONAL_FLAGS="${CC_OPTIONAL_FLAGS} ${argv[j]}"
fi
done
CC_OPTIONAL_FLAGS=`echo $CC_OPTIONAL_FLAGS | grep ^"-"`
}
addRequiredFlags()
{
local argc=$#
local argv=("$@")
CC_OPTIONAL_FLAG_PREFIX="--with-cc-opt="
LD_OPTIONAL_FLAG_PREFIX="--with-ld-opt="
ADDITIONAL_MODULE_FLAG_PREFIX="--add-module="
DYNAMIC_MODULE_FLAG_PREFIX="--add-dynamic-module="
BUILD_FLAG_PREFIX="--build="
OPENSSL_VERSION_PREFIX="--with-openssl="
OPENSSL_OPT_PREFIX="--with-openssl-opt="
HPACK_ENC_PREFIX="--with-http_v2_hpack_enc"
AUTH_JWT_PREFIX="--with-http_auth_jwt_module"
F4F_PREFIX="--with-http_f4f_module"
HLS_PREFIX="--with-http_hls_module"
SESSION_LOG_PREFIX="--with-http_session_log_module"
COMMON_PREFIX="--"
WITH_CC_PREFIX="--with-cc"
for (( i = 1; i < $argc; i++ )); do
if [[ "${argv[i]}" =~ ^${COMMON_PREFIX} ]] && \
[[ ! ("${argv[i]}" =~ ^${CC_OPTIONAL_FLAG_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ^${LD_OPTIONAL_FLAG_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${ADDITIONAL_MODULE_FLAG_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${OPENSSL_VERSION_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${OPENSSL_OPT_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${DYNAMIC_MODULE_FLAG_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${BUILD_FLAG_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${AUTH_JWT_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${F4F_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${HLS_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${SESSION_LOG_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${WITH_CC_PREFIX}) ]] && \
[[ ! ("${argv[i]}" =~ ${HPACK_ENC_PREFIX}) ]] ; \
then
debug "Adding configuration flag: ${argv[i]}\n"
NUMBER_OF_CONFIGURATION_FLAGS=$((NUMBER_OF_CONFIGURATION_FLAGS+1))
CONFIGURATION_FLAGS="${CONFIGURATION_FLAGS} \\\\\n${argv[i]}"
fi
done
COMBINED_CONFIGURATION_FLAGS="${CONFIGURATION_FLAGS}"
debug "Successfully added nginx configuration flags"
}
add_nginx_and_release_versions()
{
echo -e "NGINX_VERSION=\"${NGINX_VERSION}\"" >> ${FILE_NAME}
RELEASE_VERSION=`cat /etc/*-release | grep -i "PRETTY_NAME\|Gaia" | cut -d"\"" -f2`
echo -e "RELEASE_VERSION=\"${RELEASE_VERSION}\"" >> ${FILE_NAME}
}
initializeEnviroment
echo -e "Open-appsec Nginx version extractor\n"
check_flags_options "$@"
_main

View File

@@ -380,7 +380,11 @@ compression_chain_filter(
}
ngx_memcpy(curr_input_link->buf, output_buffer, sizeof(ngx_buf_t));
curr_input_link->buf->memory = 1;
// Empty buffer should not be marked as "in-memory"
if (curr_input_link->buf->last - curr_input_link->buf->pos != 0) {
curr_input_link->buf->memory = 1;
}
}
write_dbg(DBG_LEVEL_TRACE, "Successfully %s chain", should_compress ? "compressed" : "decompressed");

View File

@@ -333,7 +333,7 @@ ngx_http_cp_finalize_rejected_request(ngx_http_request_t *request)
}
out_chain[0].buf->last_buf = 1;
out_chain[0].next = NULL;
return ngx_http_output_filter(request, &out_chain[0]);
ngx_http_output_filter(request, &out_chain[0]);
}
CUSTOM_RES_OUT:

View File

@@ -86,8 +86,8 @@ init_thread_ctx(
void *
ngx_http_cp_registration_thread(void *_ctx)
{
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)_ctx;
ngx_int_t res = ngx_cp_attachment_init_process();
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
ngx_int_t res = ngx_cp_attachment_init_process(ctx->request);
if (res == NGX_ABORT && already_registered) {
already_registered = 0;
disconnect_communication();
@@ -141,7 +141,8 @@ end_req_header_handler(
&session_data_p->verdict,
session_data_p->session_id,
request,
modifications
modifications,
REQUEST_END
);
}
@@ -154,7 +155,7 @@ does_contain_body(ngx_http_headers_in_t *headers)
void *
ngx_http_cp_req_header_handler_thread(void *_ctx)
{
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)_ctx;
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
ngx_http_request_t *request = ctx->request;
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
ngx_int_t send_meta_data_result;
@@ -218,7 +219,7 @@ ngx_http_cp_req_header_handler_thread(void *_ctx)
void *
ngx_http_cp_req_body_filter_thread(void *_ctx)
{
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)_ctx;
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
ngx_http_request_t *request = ctx->request;
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
ngx_int_t is_last_part;
@@ -248,31 +249,14 @@ ngx_http_cp_req_body_filter_thread(void *_ctx)
}
session_data_p->remaining_messages_to_reply += num_messages_sent;
num_messages_sent = 0;
if (is_last_part) {
// Signals the nano service that the transaction reached the end.
if (ngx_http_cp_end_transaction_sender(REQUEST_END, session_data_p->session_id, &num_messages_sent) != NGX_OK) {
write_dbg(
DBG_LEVEL_WARNING,
"Failed to send request end data to the nano service. Session ID: %d",
session_data_p->session_id
);
handle_inspection_failure(inspection_failure_weight, fail_mode_verdict, session_data_p);
if (fail_mode_verdict == NGX_OK) {
THREAD_CTX_RETURN_NEXT_FILTER();
}
THREAD_CTX_RETURN(NGX_ERROR);
}
session_data_p->remaining_messages_to_reply++;
}
// Fetch nano services' results.
ctx->res = ngx_http_cp_reply_receiver(
&session_data_p->remaining_messages_to_reply,
&session_data_p->verdict,
session_data_p->session_id,
request,
&ctx->modifications
&ctx->modifications,
REQUEST_BODY
);
if (is_last_part) session_data_p->was_request_fully_inspected = 1;
@@ -280,10 +264,49 @@ ngx_http_cp_req_body_filter_thread(void *_ctx)
return NULL;
}
void *
ngx_http_cp_req_end_transaction_thread(void *_ctx)
{
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
ngx_http_request_t *request = ctx->request;
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
ngx_uint_t num_messages_sent = 0;
if (ngx_http_cp_end_transaction_sender(REQUEST_END, session_data_p->session_id, &num_messages_sent) != NGX_OK) {
write_dbg(
DBG_LEVEL_WARNING,
"Failed to send request end data to the nano service. Session ID: %d",
session_data_p->session_id
);
handle_inspection_failure(inspection_failure_weight, fail_mode_verdict, session_data_p);
if (fail_mode_verdict == NGX_OK) {
THREAD_CTX_RETURN_NEXT_FILTER();
}
THREAD_CTX_RETURN(NGX_ERROR);
}
session_data_p->remaining_messages_to_reply += num_messages_sent;
if (session_data_p->verdict != TRAFFIC_VERDICT_ACCEPT &&
session_data_p->verdict != TRAFFIC_VERDICT_DROP) {
// Fetch nano services' results.
ctx->res = ngx_http_cp_reply_receiver(
&session_data_p->remaining_messages_to_reply,
&session_data_p->verdict,
session_data_p->session_id,
request,
&ctx->modifications,
REQUEST_END
);
}
return NULL;
}
void *
ngx_http_cp_res_header_filter_thread(void *_ctx)
{
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)_ctx;
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
ngx_http_request_t *request = ctx->request;
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
ngx_int_t set_response_content_encoding_res;
@@ -383,7 +406,8 @@ ngx_http_cp_res_header_filter_thread(void *_ctx)
&session_data_p->verdict,
session_data_p->session_id,
request,
&ctx->modifications
&ctx->modifications,
RESPONSE_HEADER
);
return NULL;
@@ -392,7 +416,7 @@ ngx_http_cp_res_header_filter_thread(void *_ctx)
void *
ngx_http_cp_res_body_filter_thread(void *_ctx)
{
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)_ctx;
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
ngx_http_request_t *request = ctx->request;
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
ngx_int_t send_body_result;
@@ -446,7 +470,50 @@ ngx_http_cp_res_body_filter_thread(void *_ctx)
&session_data_p->verdict,
session_data_p->session_id,
request,
&ctx->modifications
&ctx->modifications,
RESPONSE_BODY
);
return NULL;
}
void *
ngx_http_cp_hold_verdict_thread(void *_ctx)
{
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
ngx_http_request_t *request = ctx->request;
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
ngx_uint_t num_messages_sent = 0;
if (ngx_http_cp_wait_sender(session_data_p->session_id, &num_messages_sent) != NGX_OK) {
write_dbg(
DBG_LEVEL_WARNING,
"Failed to send inspect wait request to the nano service. Session ID: %d",
session_data_p->session_id
);
handle_inspection_failure(inspection_failure_weight, fail_mode_hold_verdict, session_data_p);
if (fail_mode_hold_verdict == NGX_OK) {
THREAD_CTX_RETURN_NEXT_FILTER();
}
THREAD_CTX_RETURN(NGX_ERROR);
}
session_data_p->remaining_messages_to_reply += num_messages_sent;
ctx->res = ngx_http_cp_reply_receiver(
&session_data_p->remaining_messages_to_reply,
&session_data_p->verdict,
session_data_p->session_id,
request,
&ctx->modifications,
HOLD_DATA
);
write_dbg(
DBG_LEVEL_TRACE,
"Successfully receivied response to wait from the nano service. Session ID: %d",
session_data_p->session_id
);
return NULL;

View File

@@ -121,6 +121,19 @@ void * ngx_http_cp_req_header_handler_thread(void *_ctx);
///
void * ngx_http_cp_req_body_filter_thread(void *_ctx);
///
/// @brief Sends end request transmission to the attachment's service.
/// @details Communicates with the attachment service by sending request body to the attachment's service
/// and modifies _ctx by the received response.
/// @note _ctx needs to be properly initialized by init_thread_ctx() and ngx_chain_t needs of not NULL.
/// @param[in, out] _ctx is of type ngx_http_cp_event_thread_ctx_t.
/// Modifies _ctx res to the following values:
/// - #NGX_OK
/// - #NGX_ERROR
/// @return NULL.
///
void * ngx_http_cp_req_end_transaction_thread(void *_ctx);
///
/// @brief Sends response headers to the attachment's service.
/// @details Communicates with the attachment service by sending response headers to the attachment's service
@@ -147,6 +160,21 @@ void * ngx_http_cp_res_header_filter_thread(void *_ctx);
///
void * ngx_http_cp_res_body_filter_thread(void *_ctx);
///
/// @brief Sends a request to the attachment's service to update the earlier provided "WAIT" verdict.
/// @details Communicates with the attachment service by sending a HOLD_DATA request to the attachment's service
/// and modifies _ctx by the received response.
/// @note _ctx needs to be properly initialized by init_thread_ctx() and
/// be called after another call returned wait verdict.
/// @param[in, out] _ctx is of type ngx_http_cp_event_thread_ctx_t.
/// Modifies _ctx res to the following values:
/// - #NGX_OK
/// - #NGX_ERROR
/// Modifies _ctx session data with an updated verdict.
/// @return NULL.
///
void * ngx_http_cp_hold_verdict_thread(void *_ctx);
///
/// @brief Check if transaction contains headers.
/// @param[in] headers ngx_http_headers_in_t struct.

View File

@@ -144,6 +144,44 @@ was_transaction_timedout(ngx_http_cp_session_data *ctx)
return 1;
}
ngx_int_t
ngx_http_cp_hold_verdict(struct ngx_http_cp_event_thread_ctx_t *ctx)
{
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
for (uint i = 0; i < 3; i++) {
sleep(1);
int res = ngx_cp_run_in_thread_timeout(
ngx_http_cp_hold_verdict_thread,
(void *)ctx,
waiting_for_verdict_thread_timeout_msec,
"ngx_http_cp_hold_verdict_thread"
);
if (!res) {
write_dbg(
DBG_LEVEL_DEBUG,
"ngx_http_cp_hold_verdict_thread failed at attempt number=%d",
i
);
continue;
}
if (session_data_p->verdict != TRAFFIC_VERDICT_WAIT) {
// Verdict was updated.
write_dbg(
DBG_LEVEL_DEBUG,
"finished ngx_http_cp_hold_verdict successfully. new verdict=%d",
session_data_p->verdict
);
return 1;
}
}
write_dbg(DBG_LEVEL_TRACE, "Handling Failure with fail %s mode", fail_mode_hold_verdict == NGX_OK ? "open" : "close");
handle_inspection_failure(inspection_failure_weight, fail_mode_hold_verdict, session_data_p);
session_data_p->verdict = fail_mode_hold_verdict == NGX_OK ? TRAFFIC_VERDICT_ACCEPT : TRAFFIC_VERDICT_DROP;
return 0;
}
ngx_http_cp_verdict_e
enforce_sessions_rate()
{
@@ -498,6 +536,12 @@ ngx_http_cp_req_body_filter(ngx_http_request_t *request, ngx_chain_t *request_bo
write_dbg(DBG_LEVEL_DEBUG, "spawn ngx_http_cp_req_body_filter_thread");
// Open threads while unprocessed chain elements still exist, up to num of elements in the chain iterations
for (chain_elem = ctx.chain; chain_elem != NULL && ctx.chain; chain_elem = chain_elem->next) {
// Notify if zero-size buf is marked as "memory". This should never happen but if it does we want to know.
if (chain_elem->buf && chain_elem->buf->pos &&
(chain_elem->buf->last - chain_elem->buf->pos == 0) && chain_elem->buf->memory == 1) {
write_dbg(DBG_LEVEL_WARNING,
"Warning: encountered request body chain element of size 0 with memory flag enabled");
}
clock_gettime(CLOCK_REALTIME, &hook_time_begin);
res = ngx_cp_run_in_thread_timeout(
ngx_http_cp_req_body_filter_thread,
@@ -529,8 +573,45 @@ ngx_http_cp_req_body_filter(ngx_http_request_t *request, ngx_chain_t *request_bo
ctx.res
);
calcProcessingTime(session_data_p, &hook_time_begin, 1);
if (session_data_p->verdict == TRAFFIC_VERDICT_WAIT) {
res = ngx_http_cp_hold_verdict(&ctx);
if (!res) {
session_data_p->verdict = fail_mode_hold_verdict == NGX_OK ? TRAFFIC_VERDICT_ACCEPT : TRAFFIC_VERDICT_DROP;
updateMetricField(HOLD_THREAD_TIMEOUT, 1);
return fail_mode_verdict == NGX_OK ? ngx_http_next_request_body_filter(request, request_body_chain) : NGX_ERROR;
}
}
if (session_data_p->was_request_fully_inspected) {
res = ngx_cp_run_in_thread_timeout(
ngx_http_cp_req_end_transaction_thread,
(void *)&ctx,
req_body_thread_timeout_msec,
"ngx_http_cp_req_end_transaction_thread"
);
if (!res) {
// failed to execute thread task, or it timed out
session_data_p->verdict = fail_mode_verdict == NGX_OK ? TRAFFIC_VERDICT_ACCEPT : TRAFFIC_VERDICT_DROP;
write_dbg(
DBG_LEVEL_DEBUG,
"req_end_transaction thread failed, returning default fail mode verdict. Session id: %d, verdict: %s",
session_data_p->session_id,
session_data_p->verdict == TRAFFIC_VERDICT_ACCEPT ? "accept" : "drop"
);
updateMetricField(REQ_BODY_THREAD_TIMEOUT, 1);
return fail_mode_verdict == NGX_OK ? ngx_http_next_request_body_filter(request, request_body_chain) : NGX_ERROR;
}
write_dbg(
DBG_LEVEL_DEBUG,
"finished ngx_http_cp_req_end_transaction_thread successfully. return=%d next_filter=%d res=%d",
ctx.should_return,
ctx.should_return_next_filter,
ctx.res
);
}
calcProcessingTime(session_data_p, &hook_time_begin, 1);
if (ctx.should_return_next_filter) {
return ngx_http_next_request_body_filter(request, request_body_chain);
}
@@ -787,7 +868,7 @@ ngx_http_cp_res_body_filter(ngx_http_request_t *request, ngx_chain_t *body_chain
if (session_data_p->verdict == TRAFFIC_VERDICT_DROP) request->keepalive = 0;
return ngx_http_next_response_body_filter(request, body_chain);
}
session_data_p->response_data.num_body_chunk++;
if (body_chain == NULL) {
@@ -890,6 +971,12 @@ ngx_http_cp_res_body_filter(ngx_http_request_t *request, ngx_chain_t *body_chain
write_dbg(DBG_LEVEL_DEBUG, "spawn ngx_http_cp_res_body_filter_thread");
// Open threads while unprocessed chain elements still exist, up to num of elements in the chain iterations
for (chain_elem = ctx.chain; chain_elem != NULL && ctx.chain; chain_elem = chain_elem->next) {
// Notify if zero-size buf is marked as "memory". This should never happen but if it does we want to know.
if (chain_elem->buf && chain_elem->buf->pos &&
(chain_elem->buf->last - chain_elem->buf->pos == 0) && chain_elem->buf->memory == 1) {
write_dbg(DBG_LEVEL_WARNING,
"Warning: encountered response body chain element of size 0 with memory flag enabled");
}
clock_gettime(CLOCK_REALTIME, &hook_time_begin);
if (!ngx_cp_run_in_thread_timeout(
ngx_http_cp_res_body_filter_thread,

View File

@@ -25,6 +25,7 @@
#include "ngx_cp_http_parser.h"
#include "nginx_attachment_common.h"
#include "ngx_cp_hook_threads.h"
static const int registration_failure_weight = 2; ///< Registration failure weight.
static const int inspection_failure_weight = 1; ///< Inspection failure weight.
@@ -96,6 +97,16 @@ ngx_int_t ngx_http_cp_res_header_filter(ngx_http_request_t *request);
///
ngx_int_t ngx_http_cp_req_header_handler(ngx_http_request_t *request);
///
/// @brief Sends a request to the nano service to update the verdict.
/// @note Should be called after the nano service provided the verdict TRAFFIC_VERDICT_WAIT to get the updated verdict.
/// @param[in, out] request Event thread context to be updated.
/// @returns ngx_int_t
/// - #1 if request was properly communicated with the nano service and provided an updated response.
/// - #0 otherwise.
///
ngx_int_t ngx_http_cp_hold_verdict(struct ngx_http_cp_event_thread_ctx_t *ctx);
///
/// @brief Checks if transaction was timed out.
/// @param[in, out] ctx

View File

@@ -32,7 +32,7 @@ typedef enum ngx_cp_comm_direction {
/// - #NGX_ERROR
/// - #NGX_ABORT
///
ngx_int_t ngx_cp_attachment_init_process();
ngx_int_t ngx_cp_attachment_init_process(ngx_http_request_t *);
///
/// @brief Preforms send\receive information to\from the service via a socket.

View File

@@ -81,6 +81,7 @@ ngx_http_cp_signal_to_service(uint32_t cur_session_id)
///
/// @brief Signals and recieve signal to/from nano service about new session to inspect.
/// @param[in] cur_session_id Session's Id.
/// @param[in] chunk_type Chunk type that the attachment is waiting for a response from nano service.
/// @returns ngx_int_t
/// - #NGX_OK
/// - #NGX_ERROR
@@ -88,7 +89,7 @@ ngx_http_cp_signal_to_service(uint32_t cur_session_id)
/// - #NGX_AGAIN
///
static ngx_int_t
ngx_http_cp_wait_for_service(uint32_t cur_session_id)
ngx_http_cp_wait_for_service(uint32_t cur_session_id, ngx_http_chunk_type_e chunk_type)
{
static int dbg_count = 0;
static clock_t clock_start = (clock_t) 0;
@@ -97,6 +98,7 @@ ngx_http_cp_wait_for_service(uint32_t cur_session_id)
uint32_t reply_from_service;
ngx_int_t retry;
int is_fail_open_disabled = (inspection_mode != NON_BLOCKING_THREAD);
ngx_uint_t timeout = chunk_type == HOLD_DATA ? fail_open_hold_timeout : fail_open_timeout;
res = ngx_http_cp_signal_to_service(cur_session_id);
if (res != NGX_OK) return res;
@@ -111,7 +113,7 @@ ngx_http_cp_wait_for_service(uint32_t cur_session_id)
s_poll.fd = comm_socket;
s_poll.events = POLLIN;
s_poll.revents = 0;
res = poll(&s_poll, 1, is_fail_open_disabled ? 150 : fail_open_timeout);
res = poll(&s_poll, 1, is_fail_open_disabled ? 150 : timeout);
if (res < 0) {
// Polling from the nano service has failed.
@@ -192,7 +194,9 @@ ngx_http_cp_send_data_to_service(
const uint16_t *fragments_sizes,
uint8_t num_of_data_elem,
uint32_t cur_session_id,
int *was_waiting)
int *was_waiting,
ngx_http_chunk_type_e chunk_type
)
{
ngx_int_t max_retries;
ngx_int_t res = NGX_OK;
@@ -209,7 +213,7 @@ ngx_http_cp_send_data_to_service(
*was_waiting = 1;
}
res = ngx_http_cp_wait_for_service(cur_session_id);
res = ngx_http_cp_wait_for_service(cur_session_id, chunk_type);
if (res != NGX_OK && res != NGX_AGAIN) return res;
}
@@ -428,7 +432,9 @@ ngx_http_cp_reply_receiver(
ngx_http_cp_verdict_e *verdict,
uint32_t cur_session_id,
ngx_http_request_t *request,
ngx_http_cp_modification_list **modification_list)
ngx_http_cp_modification_list **modification_list,
ngx_http_chunk_type_e chunk_type
)
{
ngx_http_cp_reply_from_service_t *reply_p;
ngx_http_cp_modification_list *new_modification = NULL;
@@ -446,7 +452,7 @@ ngx_http_cp_reply_receiver(
}
do {
res = ngx_http_cp_wait_for_service(cur_session_id);
res = ngx_http_cp_wait_for_service(cur_session_id, chunk_type);
} while (res == NGX_AGAIN);
if (res != NGX_OK) return NGX_ERROR;
@@ -554,10 +560,19 @@ ngx_http_cp_reply_receiver(
break;
}
case TRAFFIC_VERDICT_INSPECT:
case TRAFFIC_VERDICT_INSPECT: {
// After an irrelevant verdict, ignore the verdict and continue to the next response.
write_dbg(DBG_LEVEL_TRACE, "Verdict inspect received from the nano service");
updateMetricField(INSPECT_VERDICTS_COUNT, 1);
break;
}
case TRAFFIC_VERDICT_WAIT: {
// After a wait verdict, query the nano agent again to get an updated verdict.
write_dbg(DBG_LEVEL_DEBUG, "Verdict wait received from the nano service");
updateMetricField(HOLD_VERDICTS_COUNT, 1);
break;
}
}
free_data_from_service();
@@ -718,7 +733,7 @@ ngx_http_cp_meta_data_sender(ngx_http_request_t *request, uint32_t cur_request_i
set_fragment_elem(fragments, fragments_sizes, &client_port, sizeof(client_port), CLIENT_PORT + 2);
// Sends all the data to the nano service.
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, META_DATA_COUNT + 2, cur_request_id, NULL);
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, META_DATA_COUNT + 2, cur_request_id, NULL, fail_open_timeout);
if (res != NGX_OK) {
// Failed to send the metadata to nano service.
if (res == NGX_ERROR && failure_count++ == 5) {
@@ -764,7 +779,7 @@ ngx_http_cp_end_transaction_sender(
set_fragments_identifiers(fragments, fragments_sizes, (uint16_t *)&end_transaction_type, &cur_request_id);
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, end_transaction_num_fragments, cur_request_id, NULL);
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, end_transaction_num_fragments, cur_request_id, NULL, fail_open_timeout);
if (res != NGX_OK) {
return NGX_ERROR;
}
@@ -773,6 +788,30 @@ ngx_http_cp_end_transaction_sender(
return NGX_OK;
}
ngx_int_t
ngx_http_cp_wait_sender(uint32_t cur_request_id, ngx_uint_t *num_messages_sent)
{
static const ngx_uint_t end_transaction_num_fragments = 2;
char *fragments[end_transaction_num_fragments];
uint16_t fragments_sizes[end_transaction_num_fragments];
ngx_http_chunk_type_e transaction_type = HOLD_DATA;
ngx_int_t res;
set_fragments_identifiers(fragments, fragments_sizes, (uint16_t *)&transaction_type, &cur_request_id);
write_dbg(DBG_LEVEL_TRACE, "Sending wait event flag for inspection");
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, end_transaction_num_fragments, cur_request_id, NULL, fail_open_timeout);
if (res != NGX_OK) {
return NGX_ERROR;
}
write_dbg(DBG_LEVEL_TRACE, "Successfully sent wait event");
*num_messages_sent = 1;
return NGX_OK;
}
ngx_int_t
ngx_http_cp_res_code_sender(uint16_t response_code, uint32_t cur_req_id, ngx_uint_t *num_messages_sent)
{
@@ -788,7 +827,7 @@ ngx_http_cp_res_code_sender(uint16_t response_code, uint32_t cur_req_id, ngx_uin
set_fragments_identifiers(fragments, fragments_sizes, &chunck_type, &cur_req_id);
set_fragment_elem(fragments, fragments_sizes, &response_code, sizeof(uint16_t), 2);
if (ngx_http_cp_send_data_to_service(fragments, fragments_sizes, res_code_num_fragments, cur_req_id, NULL) != NGX_OK) {
if (ngx_http_cp_send_data_to_service(fragments, fragments_sizes, res_code_num_fragments, cur_req_id, NULL, fail_open_hold_timeout) != NGX_OK) {
return NGX_ERROR;
}
@@ -812,7 +851,7 @@ ngx_http_cp_content_length_sender(uint64_t content_length_n, uint32_t cur_req_id
set_fragments_identifiers(fragments, fragments_sizes, &chunck_type, &cur_req_id);
set_fragment_elem(fragments, fragments_sizes, &content_length_val, sizeof(content_length_val), 2);
if (ngx_http_cp_send_data_to_service(fragments, fragments_sizes, content_length_num_fragments, cur_req_id, NULL) != NGX_OK) {
if (ngx_http_cp_send_data_to_service(fragments, fragments_sizes, content_length_num_fragments, cur_req_id, NULL, fail_open_timeout) != NGX_OK) {
return NGX_ERROR;
}
@@ -865,7 +904,7 @@ send_header_bulk(
set_fragment_elem(data, data_sizes, &is_last_part, sizeof(is_last_part), 2);
set_fragment_elem(data, data_sizes, &bulk_part_index, sizeof(bulk_part_index), 3);
res = ngx_http_cp_send_data_to_service(data, data_sizes, HEADER_DATA_COUNT * num_headers + 4, cur_request_id, NULL);
res = ngx_http_cp_send_data_to_service(data, data_sizes, HEADER_DATA_COUNT * num_headers + 4, cur_request_id, NULL, fail_open_timeout);
if (res != NGX_OK) {
write_dbg(DBG_LEVEL_TRACE, "Failed to send bulk of %iu headers", num_headers);
return NGX_ERROR;
@@ -1048,7 +1087,7 @@ ngx_http_cp_body_sender(
}
// Sending the data to the nano service.
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, num_body_chunk_fragments, session_data->session_id,
&was_waiting);
&was_waiting, fail_open_timeout);
if (res != NGX_OK) {
// Failed to send the fragments to the nano service.
@@ -1091,7 +1130,7 @@ ngx_http_cp_metric_data_sender()
fragments = (char *)&data_to_send;
fragments_sizes = sizeof(ngx_http_cp_metric_data_t);
res = ngx_http_cp_send_data_to_service(&fragments, &fragments_sizes, 1, 0, NULL);
res = ngx_http_cp_send_data_to_service(&fragments, &fragments_sizes, 1, 0, NULL, fail_open_timeout);
reset_metric_data();
return res;
}

View File

@@ -47,6 +47,7 @@ extern int comm_socket; ///< Communication socket.
/// @param[in] cur_session_id Session's Id.
/// @param[in, out] request NGINX request.
/// @param[in] modification_list
/// @param[in] chunk_type Chunk type that the attachment is waiting for a response from nano service.
/// @returns ngx_int_t
/// - #NGX_OK
/// - #NGX_HTTP_FORBIDDEN
@@ -58,7 +59,8 @@ ngx_http_cp_reply_receiver(
ngx_http_cp_verdict_e *verdict,
uint32_t cur_session_id,
ngx_http_request_t *request,
ngx_http_cp_modification_list **modification_list
ngx_http_cp_modification_list **modification_list,
ngx_http_chunk_type_e chunk_type
);
///
@@ -170,6 +172,17 @@ ngx_http_cp_body_sender(
ngx_chain_t **next_elem_to_inspect
);
///
/// @brief Sends HOLD_DATA request to the nano service.
/// @details HOLD_DATA request is a request that asks the nano service to provide with an updated verdict.
/// @param[in] cur_request_id Request session's Id.
/// @param[in, out] num_messages_sent Number of messages sent will be saved onto this parameter.
/// - #NGX_OK
/// - #NGX_ERROR
///
ngx_int_t
ngx_http_cp_wait_sender(uint32_t cur_request_id, ngx_uint_t *num_messages_sent);
///
/// @brief Checks if reconf is needed and reconfigs if necessary.
/// @returns ngx_int_t

View File

@@ -51,7 +51,7 @@ ngx_cp_run_in_thread_timeout(CpThreadRoutine thread_func, void *arg, int timeout
void *res = NULL;
pthread_t thread;
struct timespec ts;
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)arg;
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)arg;
if (inspection_mode == NO_THREAD) return ngx_cp_run_without_thread_timeout(thread_func, arg, func_name);

View File

@@ -81,9 +81,11 @@ ngx_http_cp_sessions_per_minute_limit sessions_per_minute_limit_info = {
ngx_uint_t current_config_version = 0;
ngx_int_t fail_mode_verdict = NGX_OK; ///< Fail open verdict incase of a timeout.
ngx_int_t fail_mode_hold_verdict = NGX_OK; ///< Fail open verdict incase of a timeout when waiting for wait verdict.
ngx_int_t dbg_is_needed = 0; ///< Debug flag.
ngx_int_t num_of_connection_attempts = 0; ///< Maximum number of attempted connections.
ngx_uint_t fail_open_timeout = 50; ///< Fail open timeout in milliseconds.
ngx_uint_t fail_open_hold_timeout = 150; ///< Fail open wait timeout in milliseconds.
ngx_http_cp_verdict_e sessions_per_minute_limit_verdict = TRAFFIC_VERDICT_ACCEPT;
ngx_uint_t max_sessions_per_minute = 0; ///< Masimum session per minute.
ngx_uint_t req_max_proccessing_ms_time = 3000; ///< Total Request processing timeout in milliseconds.
@@ -93,6 +95,7 @@ ngx_uint_t req_header_thread_timeout_msec = 100; ///< Request header processing
ngx_uint_t req_body_thread_timeout_msec = 150; ///< Request body processing timeout in milliseconds.
ngx_uint_t res_header_thread_timeout_msec = 100; ///< Response header processing timeout in milliseconds.
ngx_uint_t res_body_thread_timeout_msec = 150; ///< Response body processing timeout in milliseconds.
ngx_uint_t waiting_for_verdict_thread_timeout_msec = 150; ///< Wait thread processing timeout in milliseconds.
ngx_http_inspection_mode_e inspection_mode = NON_BLOCKING_THREAD; ///< Default inspection mode.
ngx_uint_t num_of_nginx_ipc_elements = 200; ///< Number of NGINX IPC elements.
ngx_msec_t keep_alive_interval_msec = DEFAULT_KEEP_ALIVE_INTERVAL_MSEC;
@@ -892,6 +895,10 @@ init_general_config(const char *conf_path)
fail_mode_verdict = isFailOpenMode() == 1 ? NGX_OK : NGX_ERROR;
fail_open_timeout = getFailOpenTimeout();
// Setting fail wait open/close
fail_mode_hold_verdict = isFailOpenHoldMode() == 1 ? NGX_OK : NGX_ERROR;
fail_open_hold_timeout = getFailOpenHoldTimeout();
// Setting attachment's variables.
sessions_per_minute_limit_verdict = isFailOpenOnSessionLimit() ? TRAFFIC_VERDICT_ACCEPT : TRAFFIC_VERDICT_DROP;
max_sessions_per_minute = getMaxSessionsPerMinute();
@@ -903,6 +910,7 @@ init_general_config(const char *conf_path)
req_body_thread_timeout_msec = getReqBodyThreadTimeout();
res_header_thread_timeout_msec = getResHeaderThreadTimeout();
res_body_thread_timeout_msec = getResBodyThreadTimeout();
waiting_for_verdict_thread_timeout_msec = getWaitingForVerdictThreadTimeout();
num_of_nginx_ipc_elements = getNumOfNginxIpcElements();
keep_alive_interval_msec = (ngx_msec_t) getKeepAliveIntervalMsec();
@@ -917,6 +925,8 @@ init_general_config(const char *conf_path)
"debug level: %d, "
"failure mode: %s, "
"fail mode timeout: %u msec, "
"failure wait mode: %s, "
"fail mode wait timeout: %u msec, "
"sessions per minute limit verdict: %s, "
"max sessions per minute: %u, "
"req max processing time: %u msec, "
@@ -926,6 +936,7 @@ init_general_config(const char *conf_path)
"req body thread timeout: %u msec, "
"res header thread timeout: %u msec, "
"res body thread timeout: %u msec, "
"wait thread timeout: %u msec, "
"static resources path: %s, "
"num of nginx ipc elements: %u, "
"keep alive interval msec: %u msec",
@@ -933,6 +944,8 @@ init_general_config(const char *conf_path)
new_dbg_level,
(fail_mode_verdict == NGX_OK ? "fail-open" : "fail-close"),
fail_open_timeout,
(fail_mode_hold_verdict == NGX_OK ? "fail-open" : "fail-close"),
fail_open_hold_timeout,
sessions_per_minute_limit_verdict == TRAFFIC_VERDICT_ACCEPT ? "Accpet" : "Drop",
max_sessions_per_minute,
req_max_proccessing_ms_time,
@@ -942,6 +955,7 @@ init_general_config(const char *conf_path)
req_body_thread_timeout_msec,
res_header_thread_timeout_msec,
res_body_thread_timeout_msec,
waiting_for_verdict_thread_timeout_msec,
getStaticResourcesPath(),
num_of_nginx_ipc_elements,
keep_alive_interval_msec

View File

@@ -46,10 +46,12 @@
}
extern ngx_int_t fail_mode_verdict;
extern ngx_int_t fail_mode_hold_verdict;
extern ngx_int_t dbg_is_needed;
extern ngx_int_t num_of_connection_attempts;
extern ngx_uint_t content_length_would_change;
extern ngx_uint_t fail_open_timeout;
extern ngx_uint_t fail_open_hold_timeout;
extern ngx_uint_t req_max_proccessing_ms_time;
extern ngx_uint_t res_max_proccessing_ms_time;
extern ngx_uint_t registration_thread_timeout_msec;
@@ -57,6 +59,7 @@ extern ngx_uint_t req_header_thread_timeout_msec;
extern ngx_uint_t req_body_thread_timeout_msec;
extern ngx_uint_t res_header_thread_timeout_msec;
extern ngx_uint_t res_body_thread_timeout_msec;
extern ngx_uint_t waiting_for_verdict_thread_timeout_msec;
extern ngx_http_inspection_mode_e inspection_mode;
extern ngx_uint_t num_of_nginx_ipc_elements;

View File

@@ -0,0 +1,37 @@
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// @file ngx_modules.c
/// \brief This file is generated from configuration and hold the data structures connecting the plugin to the server
#include <ngx_config.h>
#include <ngx_core.h>
extern ngx_module_t ngx_http_cp_attachment_module;
ngx_module_t *ngx_modules[] = {
&ngx_http_cp_attachment_module,
NULL
};
char *ngx_module_names[] = {
"ngx_http_cp_attachment_module",
NULL
};
char *ngx_module_order[] = {
"ngx_http_cp_attachment_module",
"ngx_http_copy_filter_module",
NULL
};