diff --git a/etc/fastly_edge_modules/netacea_integration.json b/etc/fastly_edge_modules/netacea_integration.json index f3412871..ed11775a 100644 --- a/etc/fastly_edge_modules/netacea_integration.json +++ b/etc/fastly_edge_modules/netacea_integration.json @@ -1,8 +1,15 @@ { - "description": "Set of VCLs required to integrate Netacea services. Please note for full functionality Fastly support needs to enable proper handling of POST requests. Do not enable unless this has been done.", + "description": "Set of VCLs required to integrate Netacea services. Please note for full functionality Fastly support needs to enable proper handling of POST requests. Additionally, an edge dictionary named netacea_edge_config must be created. Use of this dictionary is optional and requires advanced configuration. A Netacea Engineer can assist you with this setup. Do not enable this module unless the prerequisite steps have been completed.", "id": "netacea_integration", "name": "Netacea Bot Detection integration", "properties": [ + { + "description": "Integration Mode. Must be one of BYPASS, INGEST, INJECT, MITIGATE.", + "label": "Integration Mode", + "name": "netacea_integration_mode", + "required": true, + "type": "string" + }, { "description": "API Key", "label": "Netacea API Key", @@ -84,24 +91,24 @@ "vcl": [ { "priority": 45, - "template": "# Change the shielding condition to account for restarts due to bot detection\nset var.fastly_req_do_shield = (req.restarts <= 1);\n# Reenable clustering. It gets turned off on restarts\nset req.http.Fastly-Force-Shield = \"1\";\n# Invoke Netacea Bot Detection checking\ncall netacea_recv;\n", + "template": "set var.fastly_req_do_shield = (req.restarts <= 1);\nset req.http.Fastly-Force-Shield = \"1\";\nif (req.restarts == 0) {\n call cleanup_netacea_variables;\n}\ncall netacea_check_req;\n", "type": "recv" }, { "priority": 45, - "template": "call netacea_deliver;", + "template": "if (!is_path_ignored()) {\n declare local var.netacea_use_relative_path_captcha_assets STRING;\n declare local var.integration_mode STRING;\n set var.netacea_use_relative_path_captcha_assets = get_netacea_config_use_relative_path_captcha_assets();\n if (var.netacea_use_relative_path_captcha_assets == \"true\") {\n if (std.prefixof(req.url.path, \"/Mitigations/\") && req.method == \"GET\") {\n if (std.suffixof(req.url.path, \".css\") || std.suffixof(req.url.path, \".js\")) {\n return(deliver);\n }\n }\n }\n if (req.http.netacea_captcha_path == \"1\") {\n call netacea_hide_response_headers;\n call set_netacea_captcha_header;\n return(deliver);\n }\n call netacea_calculate_best_mitigation;\n if (req.http.netacea_processed == \"1\") {\n set var.integration_mode = get_netacea_config_integration_mode();\n set req.http.mit_status = resp.status;\n if (resp.status != 200 && req.http.X-Netacea-Compile-JSON != \"done\") {\n set req.http.netacea_best_mitigation = \"\";\n set req.http.netacea_bctype_string = \"\";\n if(req.url == \"/AtaVerifyCaptcha\") {\n unset resp.http.Set-Cookie;\n set req.http.netacea_set_cookies = \"0\";\n }\n }\n if (var.integration_mode == \"MITIGATE\" && req.http.X-Netacea-Compile-JSON != \"done\" && netacea_should_return_json()) { \n if (req.url != \"/AtaVerifyCaptcha\" && resp.http.X-Netacea-Mitigate == \"1\") { \n if (resp.http.X-Netacea-Captcha == \"1\" || resp.http.X-Netacea-Captcha == \"5\") { \n set req.http.X-Netacea-Event-ID = resp.http.X-Netacea-Event-ID;\n set req.http.X-Netacea-Compile-JSON = \"requested\";\n }\n }\n }\n if (var.integration_mode == \"INJECT\" || req.http.X-Netacea-Compile-JSON == \"requested\") {\n set req.http.X-Netacea-Match = \"\" resp.http.X-Netacea-Match;\n set req.http.X-Netacea-Mitigate = \"\" resp.http.X-Netacea-Mitigate;\n set req.http.X-Netacea-Captcha = \"\" resp.http.X-Netacea-Captcha;\n }\n set req.http.netacea_mitata_captcha_cookie_value = resp.http.x-netacea-mitatacaptcha-value;\n set req.http.netacea_mitata_captcha_cookie_expiry = resp.http.x-netacea-mitatacaptcha-expiry;\n call set_netacea_cookies;\n call netacea_hide_response_headers;\n if(req.url == \"/AtaVerifyCaptcha\") {\n return(deliver);\n }\n set req.http.host = req.http.netacea_origin_host;\n set req.url = req.http.netacea_origin_url;\n set req.method = req.http.netacea_origin_method;\n unset req.http.netacea_origin_url;\n unset req.http.netacea_origin_host;\n unset req.http.netacea_origin_method;\n unset req.http.X-Netacea-Api-Key;\n if (\n req.http.netacea_best_mitigation != \"captcha\"\n || var.integration_mode == \"INJECT\"\n || req.http.X-Netacea-Compile-JSON == \"requested\"\n ) {\n unset req.http.x-netacea:netacea_check_req_called;\n restart;\n }\n set resp.status = 403;\n set resp.response = \"Forbidden\";\n unset req.http.X-Netacea-Compile-JSON;\n call set_netacea_captcha_header;\n return(deliver);\n }\n call set_netacea_cookies;\n}\n", "type": "deliver" }, { "priority": 45, - "template": "call netacea_error;", + "template": "declare local var.captcha_url STRING;\ndeclare local var.response STRING;\nif (obj.status == 601 && req.http.X-Netacea-Compile-JSON == \"processing\") {\n set var.captcha_url = get_netacea_captcha_path();\n set var.captcha_url = var.captcha_url \"?trackingId=\" req.http.X-Netacea-Event-ID;\n set var.response = \"{\" LF\n \" %22captchaRelativeURL%22:%22\" var.captcha_url \"%22,\" LF\n \" %22captchaAbsoluteURL%22:%22\" req.protocol \"://\" fastly_info.host_header var.captcha_url \"%22\" LF\n \"}\";\n set obj.status = 200;\n set obj.response = \"Forbidden\";\n set obj.http.Content-Type = \"application/json\";\n set obj.http.X-Netacea-Match = req.http.X-Netacea-Match;\n set obj.http.X-Netacea-Mitigate = req.http.X-Netacea-Mitigate;\n set obj.http.X-Netacea-Captcha = req.http.X-Netacea-Captcha;\n synthetic var.response;\n unset req.http.X-Netacea-Event-ID;\n unset req.http.X-Netacea-Match;\n unset req.http.X-Netacea-Mitigate;\n unset req.http.X-Netacea-Captcha;\n set req.http.X-Netacea-Compile-JSON = \"done\";\n return(deliver);\n}", "type": "error" }, { "priority": 45, - "template": "backend F_MitSvc {\n .between_bytes_timeout = 100ms;\n .connect_timeout = 500ms;\n .dynamic = true;\n .first_byte_timeout = 500ms;\n .host = \"geo-mitigations.netacea.net\";\n .max_connections = 200;\n .port = \"443\";\n .share_key = \"NetaceaGeoMitigations\";\n .host_header = \"geo-mitigations.netacea.net\";\n .always_use_host_header = true;\n .ssl = true;\n .ssl_cert_hostname = \"geo-mitigations.netacea.net\";\n .ssl_check_cert = always;\n .ssl_sni_hostname = \"geo-mitigations.netacea.net\";\n .probe = {\n .dummy = false;\n .initial = 5;\n .request = \"GET /_health HTTP/1.1\" \"Host: geo-mitigations.netacea.net\" \"Connection: close\" \"User-Agent: Varnish/fastly (healthcheck)\";\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n .expected_response = 200;\n }\n}\nbackend F_CaptchaAssets {\n .between_bytes_timeout = 10s;\n .connect_timeout = 1s;\n .dynamic = true;\n .first_byte_timeout = 15s;\n .host = \"assets.ntcacdn.net\";\n .max_connections = 200;\n .port = \"443\";\n .share_key = \"4nxXnE6VkrJiVuGz4G1VbJ\";\n .host_header = \"assets.ntcacdn.net\";\n .always_use_host_header = true;\n .ssl = true;\n .ssl_cert_hostname = \"assets.ntcacdn.net\";\n .ssl_check_cert = always;\n .ssl_sni_hostname = \"assets.ntcacdn.net\";\n .probe = {\n .dummy = true;\n .initial = 5;\n .request = \"HEAD / HTTP/1.1\" \"Host: assets.ntcacdn.net\" \"Connection: close\";\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n }\n}\ntable Netacea_Config {\n \"integration_type\": \"fastly/magento\",\n \"integration_version\": \"5.6.1\",\n \"integration_mode\": \"MITIGATE\",\n \"api_key\": \"{{netacea_api_key}}\",\n \"secret_key\": \"{{netacea_secret}}\",\n \"encryption_key\": \"{{netacea_encryption_key}}\",\n \"ignore_list\": \"{{netacea_ignore_list}}\",\n \"cookie_name\": \"{{netacea_cookie_name}}\",\n \"captcha_cookie_name\": \"{{netacea_captcha_cookie_name}}\",\n \"use_relative_path_captcha_assets\": \"{{netacea_use_relative_path_captcha_assets}}\",\n \"real_ip_header_name\": \"{{netacea_real_ip_header_name}}\",\n \"captcha_path\": \"{{netacea_captcha_path}}\",\n \"captcha_header\": \"{{netacea_captcha_header}}\",\n \"enable_captcha_content_negotiation\": \"{{netacea_enable_ccn}}\"\n}\nsub get_netacea_cookie_name STRING {\n if (table.lookup(Netacea_Config, \"cookie_name\") ~ \"^\\s*(.*?)\\s*$\") {\n if (re.group.1 != \"\") {\n return re.group.1;\n }\n }\n return \"_mitata\";\n}\nsub get_netacea_captcha_cookie_name STRING {\n if (table.lookup(Netacea_Config, \"captcha_cookie_name\") ~ \"^\\s*(.*?)\\s*$\") {\n if (re.group.1 != \"\") {\n return re.group.1;\n }\n }\n return \"_mitatacaptcha\";\n}\nsub get_netacea_captcha_path STRING {\n declare local var.path STRING;\n set var.path = table.lookup(Netacea_Config, \"captcha_path\");\n set var.path = regsub(var.path, \"^\\s*/*\", \"/\");\n set var.path = regsub(var.path, \"\\s*$\", \"\");\n return urldecode(var.path);\n}\nsub get_netacea_captcha_header STRING {\n declare local var.config STRING;\n set var.config = urldecode(regsuball(table.lookup(Netacea_Config, \"captcha_header\"), \"&#x(.{2});\", \"%25\\1\"));\n set var.config = std.replaceall(var.config, \""\", \"%22\");\n set var.config = std.replaceall(var.config, \"<\", \"<\");\n set var.config = std.replaceall(var.config, \">\", \">\");\n set var.config = std.replaceall(var.config, \"&\", \"&\");\n return var.config;\n}\nsub get_netacea_captcha_header_name STRING {\n declare local var.config STRING;\n set var.config = get_netacea_captcha_header();\n if (var.config ~ \"(?i)(?:^|&)\\s*name\\s*=\\s*(.*?)\\s*(?:&|$)\") {\n return re.group.1;\n }\n return \"\";\n}\nsub get_netacea_captcha_header_value STRING {\n declare local var.config STRING;\n set var.config = get_netacea_captcha_header();\n if (var.config ~ \"(?i)(?:^|&)\\s*value\\s*=\\s*(.*?)\\s*(?:&|$)\") {\n return re.group.1;\n }\n return \"\";\n}\nsub is_path_ignored BOOL {\n declare local var.netacea_ignore_list STRING;\n declare local var.req_path STRING;\n set var.netacea_ignore_list = table.lookup(Netacea_Config, \"ignore_list\");\n set var.req_path = urldecode(req.url.path);\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"\\s*(,\\s*)+\", \",\");\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"(^|,)\\s*/*\", \"\\1/\");\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"/*\\s*(,|$)\", \"\\1\");\n if (var.netacea_ignore_list ~ \"^([^,]+),*([^,]+)?,*([^,]+)?,*([^,]+)?,*([^,]+)?\") {\n if (re.group.1 && (var.req_path == urldecode(re.group.1) || std.prefixof(var.req_path, urldecode(re.group.1) + \"/\"))) {\n return true;\n }\n if (re.group.2 && (var.req_path == urldecode(re.group.2) || std.prefixof(var.req_path, urldecode(re.group.2) + \"/\"))) {\n return true;\n }\n if (re.group.3 && (var.req_path == urldecode(re.group.3) || std.prefixof(var.req_path, urldecode(re.group.3) + \"/\"))) {\n return true;\n }\n if (re.group.4 && (var.req_path == urldecode(re.group.4) || std.prefixof(var.req_path, urldecode(re.group.4) + \"/\"))) {\n return true;\n }\n if (re.group.5 && (var.req_path == urldecode(re.group.5) || std.prefixof(var.req_path, urldecode(re.group.5) + \"/\"))) {\n return true;\n }\n }\n return false;\n}\nsub netacea_should_return_json BOOL {\n if (table.lookup(Netacea_Config, \"enable_captcha_content_negotiation\") != \"true\") {\n return false;\n }\n declare local var.html_weight FLOAT;\n declare local var.json_weight FLOAT;\n set var.html_weight = 0.0;\n set var.json_weight = 0.0;\n if (req.http.Accept ~ \"(?i)(^|,)\\s*application/json\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.json_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n } elseif (req.http.Accept ~ \"(?i)(^|,)\\s*application/\\*\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.json_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n }\n if (req.http.Accept ~ \"(?i)(^|,)\\s*text/html\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.html_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n } elseif (req.http.Accept ~ \"(^|,)\\s*text/\\*\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.html_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n }\n return var.json_weight > var.html_weight;\n}\nsub netacea_recv {\n if (!is_path_ignored()) {\n declare local var.netacea_mitSvc_authenticate BOOL;\n declare local var.netacea_mitSvc_apiKey STRING;\n declare local var.netacea_integration_mode STRING;\n declare local var.netacea_use_relative_path_captcha_assets STRING;\n declare local var.captcha_path STRING;\n set var.netacea_mitSvc_apiKey = table.lookup(Netacea_Config, \"api_key\");\n set var.netacea_integration_mode = table.lookup(Netacea_Config, \"integration_mode\");\n set var.netacea_use_relative_path_captcha_assets = table.lookup(Netacea_Config, \"use_relative_path_captcha_assets\");\n set var.captcha_path = get_netacea_captcha_path();\n if (var.netacea_use_relative_path_captcha_assets == \"true\") {\n if (std.prefixof(req.url.path, \"/Mitigations/\") && req.method == \"GET\") {\n if (std.suffixof(req.url.path, \".css\") || std.suffixof(req.url.path, \".js\")) {\n set req.backend = F_CaptchaAssets;\n return(lookup);\n }\n }\n }\n if (var.captcha_path != \"\" && urldecode(req.url.path) == var.captcha_path) {\n set req.backend = F_MitSvc;\n if (req.backend.healthy) {\n set req.http.netacea_origin_method = \"GET\";\n set req.http.netacea_processed = \"1\";\n set req.http.netacea_captcha_path = \"1\";\n set req.http.netacea_origin_host = req.http.host;\n set req.http.netacea_origin_url = req.url;\n set req.url = \"/captcha?\" + req.url.qs;\n set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;\n return(lookup);\n }\n }\n unset req.http.netacea_processed;\n if (req.restarts == 0 && fastly.ff.visits_this_service == 0) {\n set req.http.netacea_best_mitigation_code = \"000\";\n set req.http.netacea_match = \"0\";\n set req.http.netacea_mitigate = \"0\";\n set req.http.netacea_captcha = \"0\";\n call set_netacea_ip_header;\n unset req.http.mit_status;\n unset req.http.netacea_bctype_string;\n unset req.http.netacea_best_mitigation;\n unset req.http.netacea_cookies;\n unset req.http.netacea_mitata_captcha_cookie_expiry;\n unset req.http.netacea_mitata_captcha_cookie_value;\n unset req.http.netacea_mitata_must_reauthenticate;\n unset req.http.netacea_require_revalidation;\n unset req.http.netacea_set_cookies;\n unset req.http.X-Netacea-Match;\n unset req.http.X-Netacea-Mitigate;\n unset req.http.X-Netacea-Captcha;\n unset req.http.X-Netacea-Event-ID;\n unset req.http.X-Netacea-Api-Key;\n unset req.http.X-Netacea-Captcha-Status;\n unset req.http.X-Netacea-UserId;\n unset req.http.X-Netacea-Compile-JSON;\n if (var.netacea_integration_mode != \"BYPASS\") {\n set var.netacea_mitSvc_authenticate = true;\n call normalise_netacea_cookie_names;\n call decrypt_netacea_cookies_values;\n call process_netacea_mitata_cookie;\n }\n } else {\n if (req.http.X-Netacea-Compile-JSON == \"requested\") {\n set req.http.netacea_processed = \"1\";\n set req.http.X-Netacea-Compile-JSON = \"processing\";\n error 601;\n }\n if (var.netacea_integration_mode == \"MITIGATE\" && req.http.netacea_best_mitigation == \"block\") {\n error 403;\n }\n }\n if (req.http.Cookie:_mitata && !req.http.netacea_mitata_must_reauthenticate) {\n set var.netacea_mitSvc_authenticate = false;\n }\n set req.http.mitigation_user_id = req.http.X-Netacea-UserId;\n set req.http.integration_type = table.lookup(Netacea_Config, \"integration_type\");\n set req.http.integration_version = table.lookup(Netacea_Config, \"integration_version\");\n if (var.netacea_mitSvc_authenticate) {\n set req.http.netacea_set_cookies = \"1\";\n } else {\n if (var.netacea_integration_mode == \"INJECT\" && req.restarts == 0 && fastly.ff.visits_this_service == 0) {\n set req.http.X-Netacea-Match = req.http.netacea_match;\n set req.http.X-Netacea-Mitigate = req.http.netacea_mitigate;\n set req.http.X-Netacea-Captcha = req.http.netacea_captcha;\n }\n }\n if (var.netacea_integration_mode ~ \"(MITIGATE|INJECT)\" && var.netacea_mitSvc_authenticate) {\n set req.backend = F_MitSvc;\n if (req.backend.healthy) {\n unset req.http.netacea_match;\n unset req.http.netacea_mitigate;\n unset req.http.netacea_captcha;\n unset req.http.Cookie:_mitata;\n set req.http.netacea_origin_method = req.method;\n set req.http.netacea_processed = \"1\";\n set req.http.netacea_origin_host = req.http.host;\n set req.http.netacea_origin_url = req.url;\n if (req.url != \"/AtaVerifyCaptcha\") {\n set req.method = \"GET\";\n set req.url = \"/\";\n }\n set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;\n return(pass);\n }\n }\n }\n}\nsub netacea_hide_response_headers {\n unset resp.http.X-Netacea-Captcha;\n unset resp.http.X-Netacea-Event-ID;\n unset resp.http.X-Netacea-Match;\n unset resp.http.X-Netacea-MitATA-Expiry;\n unset resp.http.X-Netacea-MitATA-Value;\n unset resp.http.X-Netacea-Mitigate;\n}\nsub set_netacea_captcha_header {\n declare local var.captcha_header_name STRING;\n declare local var.captcha_header_value STRING;\n set var.captcha_header_name = get_netacea_captcha_header_name();\n set var.captcha_header_value = get_netacea_captcha_header_value();\n if (var.captcha_header_name != \"\") {\n header.set(resp, var.captcha_header_name, var.captcha_header_value);\n }\n}\nsub netacea_error {\n declare local var.captcha_url STRING;\n declare local var.response STRING;\n if (obj.status == 601 && req.http.X-Netacea-Compile-JSON == \"processing\") {\n set var.captcha_url = get_netacea_captcha_path();\n set var.captcha_url = var.captcha_url \"?trackingId=\" req.http.X-Netacea-Event-ID;\n set var.response = \"{\" LF\n \" %22captchaRelativeURL%22:%22\" var.captcha_url \"%22,\" LF\n \" %22captchaAbsoluteURL%22:%22\" req.protocol \"://\" fastly_info.host_header var.captcha_url \"%22\" LF\n \"}\";\n set obj.status = 200;\n set obj.response = \"Forbidden\";\n set obj.http.Content-Type = \"application/json\";\n set obj.http.X-Netacea-Match = req.http.X-Netacea-Match;\n set obj.http.X-Netacea-Mitigate = req.http.X-Netacea-Mitigate;\n set obj.http.X-Netacea-Captcha = req.http.X-Netacea-Captcha;\n synthetic var.response;\n unset req.http.X-Netacea-Event-ID;\n unset req.http.X-Netacea-Match;\n unset req.http.X-Netacea-Mitigate;\n unset req.http.X-Netacea-Captcha;\n set req.http.X-Netacea-Compile-JSON = \"done\";\n return(deliver);\n }\n}\nsub netacea_deliver {\n if (!is_path_ignored()) {\n declare local var.netacea_use_relative_path_captcha_assets STRING;\n declare local var.integration_mode STRING;\n set var.netacea_use_relative_path_captcha_assets = table.lookup(Netacea_Config, \"use_relative_path_captcha_assets\");\n if (var.netacea_use_relative_path_captcha_assets == \"true\") {\n if (std.prefixof(req.url.path, \"/Mitigations/\") && req.method == \"GET\") {\n if (std.suffixof(req.url.path, \".css\") || std.suffixof(req.url.path, \".js\")) {\n return(deliver);\n }\n }\n }\n if (req.http.netacea_captcha_path == \"1\") {\n call netacea_hide_response_headers;\n call set_netacea_captcha_header;\n return(deliver);\n }\n call netacea_calculate_best_mitigation;\n if (req.http.netacea_processed == \"1\") {\n set var.integration_mode = table.lookup(Netacea_Config, \"integration_mode\");\n set req.http.mit_status = resp.status;\n if (resp.status != 200 && req.http.X-Netacea-Compile-JSON != \"done\") {\n set req.http.netacea_best_mitigation = \"\";\n set req.http.netacea_bctype_string = \"\";\n if(req.url == \"/AtaVerifyCaptcha\") {\n unset resp.http.Set-Cookie;\n set req.http.netacea_set_cookies = \"0\";\n }\n }\n if (var.integration_mode == \"MITIGATE\" && req.http.X-Netacea-Compile-JSON != \"done\" && netacea_should_return_json()) { \n if (req.url != \"/AtaVerifyCaptcha\" && resp.http.X-Netacea-Mitigate == \"1\") { \n if (resp.http.X-Netacea-Captcha == \"1\" || resp.http.X-Netacea-Captcha == \"5\") { \n set req.http.X-Netacea-Event-ID = resp.http.X-Netacea-Event-ID;\n set req.http.X-Netacea-Compile-JSON = \"requested\";\n }\n }\n }\n if (var.integration_mode == \"INJECT\" || req.http.X-Netacea-Compile-JSON == \"requested\") {\n set req.http.X-Netacea-Match = \"\" resp.http.X-Netacea-Match;\n set req.http.X-Netacea-Mitigate = \"\" resp.http.X-Netacea-Mitigate;\n set req.http.X-Netacea-Captcha = \"\" resp.http.X-Netacea-Captcha;\n }\n set req.http.netacea_mitata_captcha_cookie_value = resp.http.x-netacea-mitatacaptcha-value;\n set req.http.netacea_mitata_captcha_cookie_expiry = resp.http.x-netacea-mitatacaptcha-expiry;\n call set_netacea_cookies;\n call netacea_hide_response_headers;\n if(req.url == \"/AtaVerifyCaptcha\") {\n return(deliver);\n }\n set req.http.host = req.http.netacea_origin_host;\n set req.url = req.http.netacea_origin_url;\n set req.method = req.http.netacea_origin_method;\n unset req.http.netacea_origin_url;\n unset req.http.netacea_origin_host;\n unset req.http.netacea_origin_method;\n unset req.http.X-Netacea-Api-Key;\n if (\n req.http.netacea_best_mitigation != \"captcha\"\n || var.integration_mode == \"INJECT\"\n || req.http.X-Netacea-Compile-JSON == \"requested\"\n ) {\n restart;\n }\n set resp.status = 403;\n set resp.response = \"Forbidden\";\n unset req.http.X-Netacea-Compile-JSON;\n call set_netacea_captcha_header;\n return(deliver);\n }\n call set_netacea_cookies;\n }\n}\nsub set_netacea_ip_header {\n declare local var.ip_header_name STRING;\n set var.ip_header_name = table.lookup(Netacea_Config, \"real_ip_header_name\");\n declare local var.ip_header_value STRING;\n set var.ip_header_value = if (std.strlen(var.ip_header_name) > 0, header.get(req, var.ip_header_name), \"\");\n set req.http.X-Netacea-Client-IP = if (std.strlen(var.ip_header_value) > 0, var.ip_header_value, client.ip);\n}\nsub set_netacea_cookies {\n if (req.http.netacea_set_cookies == \"1\") {\n declare local var.ignored BOOL;\n declare local var.netacea_mitSvc_secret STRING;\n set var.ignored = setcookie.delete_by_name(resp, \"_mitata\");\n set var.ignored = setcookie.delete_by_name(resp, \"_mitatacaptcha\");\n declare local var.netacea_captcha_cookie_name STRING;\n set var.netacea_captcha_cookie_name = get_netacea_captcha_cookie_name();\n set var.netacea_mitSvc_secret = table.lookup(Netacea_Config, \"secret_key\");\n call set_mitata_cookie;\n if (req.http.netacea_mitata_captcha_cookie_value && req.http.netacea_mitata_captcha_cookie_expiry) {\n if (table.lookup(Netacea_Config, \"encryption_key\") ~ \".\") {\n declare local var.netacea_encryption_key STRING;\n declare local var.netacea_iv STRING;\n declare local var.netacea_iv_trimmed STRING;\n declare local var.netacea_sig STRING;\n declare local var.netacea_mitata_captcha_cookie_value_base64 STRING;\n declare local var.netacea_mitata_captcha_cookie_value_hex STRING;\n declare local var.netacea_mitata_captcha_cookie_value_encrypted STRING;\n declare local var.netacea_mitata_captcha_cookie_final_value STRING;\n set var.netacea_encryption_key = table.lookup(Netacea_Config, \"encryption_key\");\n set var.netacea_mitata_captcha_cookie_value_base64 = digest.base64(req.http.netacea_mitata_captcha_cookie_value);\n set var.netacea_mitata_captcha_cookie_value_hex = bin.base64_to_hex(var.netacea_mitata_captcha_cookie_value_base64);\n set var.netacea_iv = uuid.version4();\n set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, \"-\", \"\");\n set var.netacea_mitata_captcha_cookie_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_captcha_cookie_value_hex);\n set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_value_encrypted);\n set var.netacea_mitata_captcha_cookie_final_value = var.netacea_iv_trimmed + \".\" + var.netacea_mitata_captcha_cookie_value_encrypted + \".\" + var.netacea_sig;\n add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + \"=\" + var.netacea_mitata_captcha_cookie_final_value + \"; Max-Age=\" + req.http.netacea_mitata_captcha_cookie_expiry + \"; Path=/;\";\n }\n if (table.lookup(Netacea_Config, \"encryption_key\") !~ \".\") {\n add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + \"=\" + req.http.netacea_mitata_captcha_cookie_value + \"; Max-Age=\" + req.http.netacea_mitata_captcha_cookie_expiry + \"; Path=/;\";\n }\n }\n }\n}\ntable Netacea_Match_Dict {\n \"0\": \"\",\n \"1\": \"ua\",\n \"2\": \"ip\",\n \"3\": \"visitor\",\n \"4\": \"datacenter\",\n \"5\": \"customer_session\",\n \"6\": \"organisation\",\n \"7\": \"asn\",\n \"8\": \"country\",\n \"9\": \"combination\"\n}\ntable Netacea_Mitigate_Dict {\n \"0\": \"\",\n \"1\": \"blocked\",\n \"2\": \"allow\",\n \"3\": \"hardblocked\"\n}\ntable Netacea_Best_Mitigations_Dict {\n \"0\": \"\",\n \"1\": \"block\",\n \"2\": \"allow\",\n \"3\": \"block\"\n}\ntable Netacea_Best_Mitigations_Captcha_Dict {\n \"1\": \"captcha\",\n \"2\": \"\",\n \"3\": \"captcha\",\n \"4\": \"\",\n \"5\": \"captcha\"\n}\ntable Netacea_Captcha_Dict {\n \"0\": \"\",\n \"1\": \"captcha_serve\",\n \"2\": \"captcha_pass\",\n \"3\": \"captcha_fail\",\n \"4\": \"captcha_cookiepass\",\n \"5\": \"captcha_cookiefail\",\n}\nsub netacea_calculate_best_mitigation {\n if (!req.http.netacea_bctype_string) {\n declare local var.netacea_match STRING;\n declare local var.netacea_mitigate STRING;\n declare local var.netacea_captcha STRING;\n declare local var.netacea_match_string STRING;\n declare local var.netacea_mitigate_string STRING;\n declare local var.netacea_captcha_string STRING;\n declare local var.netacea_captcha_mitigate_string STRING;\n declare local var.netacea_best_mitigation STRING;\n declare local var.netacea_bctype_string STRING;\n if (resp.http.x-netacea-match) { \n set var.netacea_match = resp.http.x-netacea-match;\n } elseif (req.http.netacea_match) { \n set var.netacea_match = req.http.netacea_match;\n } else {\n set var.netacea_match = \"0\";\n }\n if (resp.http.x-netacea-mitigate) { \n set var.netacea_mitigate = resp.http.x-netacea-mitigate;\n } elseif (req.http.netacea_mitigate) { \n set var.netacea_mitigate = req.http.netacea_mitigate;\n } else {\n set var.netacea_mitigate = \"0\";\n }\n if (resp.http.x-netacea-captcha) { \n set var.netacea_captcha = resp.http.x-netacea-captcha;\n } elseif (req.http.netacea_captcha) { \n set var.netacea_captcha = req.http.netacea_captcha;\n } else {\n set var.netacea_captcha = \"0\";\n }\n if (var.netacea_match) {\n set var.netacea_match_string = table.lookup(Netacea_Match_Dict, var.netacea_match, \"unknown\");\n if (var.netacea_match_string != \"\") {\n set var.netacea_bctype_string = var.netacea_match_string + \"_\";\n }\n }\n if (var.netacea_mitigate) {\n set var.netacea_mitigate_string = table.lookup(Netacea_Mitigate_Dict, var.netacea_mitigate, \"unknown\");\n if (var.netacea_mitigate_string != \"\") {\n set var.netacea_bctype_string = var.netacea_bctype_string + var.netacea_mitigate_string;\n }\n set var.netacea_best_mitigation = table.lookup(Netacea_Best_Mitigations_Dict, var.netacea_mitigate, \"no-best-mitigation\");\n if (var.netacea_best_mitigation == \"no-best-mitigation\") {\n set var.netacea_best_mitigation = \"\";\n }\n }\n if (var.netacea_captcha) {\n if (req.url != \"/AtaVerifyCaptcha\") {\n if (var.netacea_captcha == \"2\") {\n set var.netacea_captcha = \"4\";\n } elseif (var.netacea_captcha == \"3\") {\n set var.netacea_captcha = \"5\";\n }\n }\n set var.netacea_captcha_string = table.lookup(Netacea_Captcha_Dict, var.netacea_captcha, \"unknown\");\n if (var.netacea_captcha_string != \"\") {\n set var.netacea_bctype_string = var.netacea_bctype_string + \",\" + var.netacea_captcha_string;\n }\n set var.netacea_captcha_mitigate_string = table.lookup(Netacea_Best_Mitigations_Captcha_Dict, var.netacea_captcha, \"no-best-captcha-mitigation\");\n if (var.netacea_captcha_mitigate_string != \"no-best-captcha-mitigation\") {\n set var.netacea_best_mitigation = var.netacea_captcha_mitigate_string;\n }\n }\n set req.http.netacea_bctype_string = var.netacea_bctype_string;\n set req.http.netacea_best_mitigation = var.netacea_best_mitigation;\n set req.http.netacea_best_mitigation_code = var.netacea_match + var.netacea_mitigate + var.netacea_captcha;\n if (var.netacea_mitigate == \"3\") {\n set req.http.netacea_require_revalidation = \"1\";\n }\n if (var.netacea_mitigate == \"1\" && var.netacea_captcha != \"2\" && var.netacea_captcha != \"4\") {\n set req.http.netacea_require_revalidation = \"1\";\n }\n }\n}\nsub set_mitata_cookie {\n declare local var.netacea_mitSvc_secret STRING;\n set var.netacea_mitSvc_secret = table.lookup(Netacea_Config, \"secret_key\");\n if (!req.http.X-Netacea-UserId) {\n set req.http.X-Netacea-UserId = \"c\" + randomstr(15, \"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n }\n declare local var.netacea_encryption_key STRING;\n declare local var.netacea_iv STRING;\n declare local var.netacea_iv_trimmed STRING;\n declare local var.netacea_sig STRING;\n declare local var.netacea_mitata_cookie_full_value_base64 STRING;\n declare local var.netacea_mitata_cookie_full_value_hex STRING;\n declare local var.netacea_mitata_cookie_full_value_encrypted STRING;\n declare local var.netacea_mitata_cookie_final_value STRING;\n declare local var.netacea_mitata_cookie_full_value STRING;\n declare local var.netacea_ataCookie_stringValue STRING;\n declare local var.netacea_ataCookie_HMAC STRING;\n declare local var.netacea_mitSvc_exp STRING;\n declare local var.netacea_mitSvc_sig STRING;\n declare local var.netacea_mitSvc_userId STRING;\n declare local var.netacea_mitigation_code STRING;\n declare local var.netacea_client_ip_time STRING;\n declare local var.netacea_client_ip_time_hash STRING;\n declare local var.netacea_cookie_name STRING;\n set var.netacea_mitigation_code = req.http.netacea_best_mitigation_code;\n set var.netacea_mitSvc_userId = req.http.X-Netacea-UserId;\n set var.netacea_cookie_name = get_netacea_cookie_name();\n if (req.http.netacea_require_revalidation == \"1\") {\n set var.netacea_mitSvc_exp = time.units(\"s\", time.sub(now, 1m));\n } else {\n set var.netacea_mitSvc_exp = time.units(\"s\", time.add(now, 1m));\n }\n set var.netacea_client_ip_time = req.http.X-Netacea-Client-IP + var.netacea_mitSvc_exp;\n set var.netacea_client_ip_time_hash = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_client_ip_time);\n if (var.netacea_client_ip_time_hash ~ \"0x(.*)\") {\n set var.netacea_client_ip_time_hash = re.group.1;\n }\n set var.netacea_ataCookie_stringValue = var.netacea_mitSvc_exp + \"_/@#/\" + var.netacea_mitSvc_userId + \"_/@#/\" + digest.base64(var.netacea_client_ip_time_hash) + \"_/@#/\" + var.netacea_mitigation_code;\n set var.netacea_ataCookie_HMAC = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_ataCookie_stringValue);\n if (var.netacea_ataCookie_HMAC ~ \"0x(.*)\") {\n set var.netacea_ataCookie_HMAC = re.group.1;\n }\n set var.netacea_mitSvc_sig = digest.base64(var.netacea_ataCookie_HMAC);\n set var.netacea_mitata_cookie_full_value = var.netacea_mitSvc_sig + \"_/@#/\" + var.netacea_ataCookie_stringValue;\n if (table.lookup(Netacea_Config, \"encryption_key\") ~ \".\") {\n set var.netacea_encryption_key = table.lookup(Netacea_Config, \"encryption_key\");\n set var.netacea_mitata_cookie_full_value_base64 = digest.base64(var.netacea_mitata_cookie_full_value);\n set var.netacea_mitata_cookie_full_value_hex = bin.base64_to_hex(var.netacea_mitata_cookie_full_value_base64);\n set var.netacea_iv = uuid.version4();\n set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, \"-\", \"\");\n set var.netacea_mitata_cookie_full_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_cookie_full_value_hex);\n set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_full_value_encrypted);\n set var.netacea_mitata_cookie_final_value = var.netacea_iv_trimmed + \".\" + var.netacea_mitata_cookie_full_value_encrypted + \".\" + var.netacea_sig;\n add resp.http.Set-Cookie = var.netacea_cookie_name + \"=\" + var.netacea_mitata_cookie_final_value + \"; Max-Age=\" + time.units(\"s\", 1d) + \"; Path=/;\";\n }\n if (table.lookup(Netacea_Config, \"encryption_key\") !~ \".\") {\n add resp.http.Set-Cookie = var.netacea_cookie_name + \"=\" + var.netacea_mitata_cookie_full_value+ \"; Max-Age=\" + time.units(\"s\", 1d) + \"; Path=/;\";\n }\n set req.http.mitigation_user_id = var.netacea_mitSvc_userId;\n}\nsub process_netacea_mitata_cookie {\n declare local var.netacea_mitSvc_secret STRING;\n set var.netacea_mitSvc_secret = table.lookup(Netacea_Config, \"secret_key\");\n declare local var.netacea_cookie_sig STRING;\n declare local var.netacea_cookie_payload STRING;\n declare local var.netacea_cookie_expiry STRING;\n declare local var.netacea_client_ip_time_hash STRING;\n declare local var.netacea_real_client_ip_time STRING;\n declare local var.netacea_real_client_ip_time_hash STRING;\n declare local var.netacea_cookie_HMAC STRING;\n declare local var.netacea_cookie_real_value STRING;\n if (req.http.Cookie:_mitata) {\n if (req.http.Cookie:_mitata ~ \"^(.*)_\\/@#\\/((\\d+)_\\/@#\\/(.+)_\\/@#\\/(.+)_\\/@#\\/((\\d)(\\d)(\\d)))$\") {\n set var.netacea_cookie_sig = re.group.1;\n set var.netacea_cookie_payload = re.group.2;\n set var.netacea_cookie_expiry = re.group.3;\n set req.http.X-Netacea-UserId = re.group.4;\n set var.netacea_client_ip_time_hash = re.group.5;\n set req.http.netacea_match = re.group.7;\n set req.http.netacea_mitigate = re.group.8;\n set req.http.netacea_captcha = re.group.9;\n set var.netacea_cookie_real_value = var.netacea_cookie_expiry + \"_/@#/\" + req.http.X-Netacea-UserId + \"_/@#/\" + var.netacea_client_ip_time_hash + \"_/@#/\" + req.http.netacea_match + req.http.netacea_mitigate + req.http.netacea_captcha;\n set var.netacea_cookie_HMAC = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_cookie_real_value);\n if (var.netacea_cookie_HMAC ~ \"0x(.*)\") {\n set var.netacea_cookie_HMAC = re.group.1;\n }\n set var.netacea_real_client_ip_time = req.http.X-Netacea-Client-IP + var.netacea_cookie_expiry;\n set var.netacea_real_client_ip_time_hash = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_real_client_ip_time);\n if (var.netacea_real_client_ip_time_hash ~ \"0x(.*)\") {\n set var.netacea_real_client_ip_time_hash = re.group.1;\n }\n if (var.netacea_cookie_sig != digest.base64(var.netacea_cookie_HMAC)) {\n unset req.http.Cookie:_mitata;\n unset req.http.X-Netacea-UserId;\n unset req.http.netacea_match;\n unset req.http.netacea_mitigate;\n unset req.http.netacea_captcha;\n } else {\n if (time.is_after(now, std.time(var.netacea_cookie_expiry, now)) || digest.base64(var.netacea_real_client_ip_time_hash) != var.netacea_client_ip_time_hash ) {\n set req.http.netacea_mitata_must_reauthenticate = \"1\";\n }\n }\n } else {\n unset req.http.Cookie:_mitata;\n }\n }\n if (!req.http.Cookie:_mitata) {\n unset req.http.Cookie:_mitatacaptcha;\n }\n}\nsub normalise_netacea_cookie_names {\n declare local var.netacea_custom_cookie_name STRING;\n declare local var.netacea_custom_captcha_cookie_name STRING;\n set var.netacea_custom_cookie_name = get_netacea_cookie_name();\n set var.netacea_custom_captcha_cookie_name = get_netacea_captcha_cookie_name();\n set req.http.Cookie = regsuball(req.http.Cookie, \";\\s*+\", \"; \");\n if (var.netacea_custom_cookie_name !~ \"^_mitata$\") {\n unset req.http.Cookie:_mitata;\n set req.http.Cookie = std.replace_prefix(req.http.Cookie, var.netacea_custom_cookie_name + \"=\", \"_mitata=\");\n set req.http.Cookie = std.replace(req.http.Cookie, \"; \" + var.netacea_custom_cookie_name + \"=\", \"; _mitata=\");\n }\n if (var.netacea_custom_captcha_cookie_name !~ \"^_mitatacaptcha$\") {\n unset req.http.Cookie:_mitatacaptcha;\n set req.http.Cookie = std.replace_prefix(req.http.Cookie, var.netacea_custom_captcha_cookie_name + \"=\", \"_mitatacaptcha=\");\n set req.http.Cookie = std.replace(req.http.Cookie, \"; \" + var.netacea_custom_captcha_cookie_name + \"=\", \"; _mitatacaptcha=\");\n }\n}\nsub decrypt_netacea_cookies_values {\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_mitata_cookie_encrypted STRING;\n declare local var.netacea_encryption_key STRING;\n declare local var.netacea_iv STRING;\n declare local var.netacea_mitata_cookie_base64 STRING;\n declare local var.netacea_mitata_cookie_hex STRING;\n declare local var.netacea_mitata_cookie_value STRING;\n declare local var.netacea_mitata_cookie_sig STRING;\n declare local var.netacea_mitata_captcha_cookie_encrypted STRING;\n declare local var.netacea_captcha_iv STRING;\n declare local var.netacea_mitata_captcha_cookie_base64 STRING;\n declare local var.netacea_mitata_captcha_cookie_hex STRING;\n declare local var.netacea_mitata_captcha_cookie_value STRING;\n declare local var.netacea_mitata_captcha_cookie_sig STRING;\n if (table.lookup(Netacea_Config, \"encryption_key\") ~ \".\") {\n set var.netacea_encryption_key = table.lookup(Netacea_Config, \"encryption_key\");\n set var.netacea_mitSvc_secret = table.lookup(Netacea_Config, \"secret_key\");\n if (req.http.Cookie:_mitata ~ \".\") {\n if (req.http.Cookie:_mitata ~ \"^(.*?)\\.\") {\n set var.netacea_iv = re.group.1;\n }\n if (req.http.Cookie:_mitata ~ \"\\.(.*?)\\.\") {\n set var.netacea_mitata_cookie_encrypted = re.group.1;\n }\n if (req.http.Cookie:_mitata ~ \"([^\\.]+$)\") {\n set var.netacea_mitata_cookie_sig = re.group.1;\n }\n set var.netacea_mitata_cookie_hex = crypto.decrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv, var.netacea_mitata_cookie_encrypted);\n set var.netacea_mitata_cookie_base64 = bin.hex_to_base64(var.netacea_mitata_cookie_hex);\n set var.netacea_mitata_cookie_value = digest.base64_decode(var.netacea_mitata_cookie_base64);\n set req.http.Cookie:_mitata = var.netacea_mitata_cookie_value;\n if(var.netacea_mitata_cookie_sig != digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_encrypted)) {\n unset req.http.Cookie:_mitata;\n }\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"^(.*?)\\.\") {\n if (req.http.Cookie:_mitatacaptcha ~ \"^(.*?)\\.\") {\n set var.netacea_captcha_iv = re.group.1;\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"\\.(.*?)\\.\") {\n set var.netacea_mitata_captcha_cookie_encrypted = re.group.1;\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"([^\\.]+$)\") {\n set var.netacea_mitata_captcha_cookie_sig = re.group.1;\n }\n set var.netacea_mitata_captcha_cookie_hex = crypto.decrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_captcha_iv, var.netacea_mitata_captcha_cookie_encrypted);\n set var.netacea_mitata_captcha_cookie_base64 = bin.hex_to_base64(var.netacea_mitata_captcha_cookie_hex);\n set var.netacea_mitata_captcha_cookie_value = digest.base64_decode(var.netacea_mitata_captcha_cookie_base64);\n set req.http.Cookie:_mitatacaptcha = var.netacea_mitata_captcha_cookie_value;\n if(var.netacea_mitata_captcha_cookie_sig != digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_encrypted)) {\n unset req.http.Cookie:_mitatacaptcha;\n }\n }\n }\n}\n", + "template": "backend F_MitSvc {\n .between_bytes_timeout = 100ms;\n .connect_timeout = 500ms;\n .dynamic = true;\n .first_byte_timeout = 500ms;\n .host = \"geo-mitigations.netacea.net\";\n .max_connections = 200;\n .port = \"443\";\n .share_key = \"NetaceaGeoMitigations\";\n .host_header = \"geo-mitigations.netacea.net\";\n .always_use_host_header = true;\n .ssl = true;\n .ssl_cert_hostname = \"geo-mitigations.netacea.net\";\n .ssl_check_cert = always;\n .ssl_sni_hostname = \"geo-mitigations.netacea.net\";\n .probe = {\n .dummy = false;\n .initial = 5;\n .request = \"GET /_health HTTP/1.1\" \"Host: geo-mitigations.netacea.net\" \"Connection: close\" \"User-Agent: Varnish/fastly (healthcheck)\";\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n .expected_response = 200;\n }\n}\nbackend F_CaptchaAssets {\n .between_bytes_timeout = 10s;\n .connect_timeout = 1s;\n .dynamic = true;\n .first_byte_timeout = 15s;\n .host = \"assets.ntcacdn.net\";\n .max_connections = 200;\n .port = \"443\";\n .share_key = \"4nxXnE6VkrJiVuGz4G1VbJ\";\n .host_header = \"assets.ntcacdn.net\";\n .always_use_host_header = true;\n .ssl = true;\n .ssl_cert_hostname = \"assets.ntcacdn.net\";\n .ssl_check_cert = always;\n .ssl_sni_hostname = \"assets.ntcacdn.net\";\n .probe = {\n .dummy = true;\n .initial = 5;\n .request = \"HEAD / HTTP/1.1\" \"Host: assets.ntcacdn.net\" \"Connection: close\";\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n }\n}\ntable Netacea_Config {\n \"integration_type\": \"fastly/magento\",\n \"integration_version\": \"5.7.0\",\n \"integration_mode\": \"{{netacea_integration_mode}}\",\n \"api_key\": \"{{netacea_api_key}}\",\n \"secret_key\": \"{{netacea_secret}}\",\n \"encryption_key\": \"{{netacea_encryption_key}}\",\n \"cookie_name\": \"{{netacea_cookie_name}}\",\n \"captcha_cookie_name\": \"{{netacea_captcha_cookie_name}}\",\n \"ignore_list\": \"{{netacea_ignore_list}}\",\n \"use_relative_path_captcha_assets\": \"{{netacea_use_relative_path_captcha_assets}}\",\n \"real_ip_header_name\": \"{{netacea_real_ip_header_name}}\",\n \"captcha_path\": \"{{netacea_captcha_path}}\",\n \"captcha_header\": \"{{netacea_captcha_header}}\",\n \"enable_captcha_content_negotiation\": \"{{netacea_enable_ccn}}\"\n}\nsub get_netacea_config_integration_type STRING {\n return table.lookup(Netacea_Config, \"integration_type\", \"\");\n}\nsub get_netacea_config_integration_version STRING {\n return table.lookup(Netacea_Config, \"integration_version\", \"\");\n}\nsub get_netacea_config_api_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"api_key\");\n }\n return table.lookup(Netacea_Config, \"api_key\", \"\");\n}\nsub get_netacea_config_secret_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"secret_key\");\n }\n return table.lookup(Netacea_Config, \"secret_key\", \"\");\n}\nsub get_netacea_config_encryption_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"encryption_key\");\n }\n return table.lookup(Netacea_Config, \"encryption_key\", \"\");\n}\nsub get_netacea_config_integration_mode STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"integration_mode\");\n }\n return table.lookup(Netacea_Config, \"integration_mode\", \"\");\n}\nsub get_netacea_config_ignore_list STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"ignore_list\");\n }\n return table.lookup(Netacea_Config, \"ignore_list\", \"\");\n}\nsub get_netacea_config_cookie_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"cookie_name\");\n }\n return table.lookup(Netacea_Config, \"cookie_name\", \"\");\n}\nsub get_netacea_config_captcha_cookie_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_cookie_name\");\n }\n return table.lookup(Netacea_Config, \"captcha_cookie_name\", \"\");\n}\nsub get_netacea_config_use_relative_path_captcha_assets STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"use_relative_path_captcha_assets\");\n }\n return table.lookup(Netacea_Config, \"use_relative_path_captcha_assets\", \"\");\n}\nsub get_netacea_config_real_ip_header_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"real_ip_header_name\");\n }\n return table.lookup(Netacea_Config, \"real_ip_header_name\", \"\");\n}\nsub get_netacea_config_captcha_path STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_path\");\n }\n return table.lookup(Netacea_Config, \"captcha_path\", \"\");\n}\nsub get_netacea_config_captcha_header STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_header\");\n }\n return table.lookup(Netacea_Config, \"captcha_header\", \"\");\n}\nsub get_netacea_config_enable_captcha_content_negotiation STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"enable_captcha_content_negotiation\");\n }\n return table.lookup(Netacea_Config, \"enable_captcha_content_negotiation\", \"\");\n}\nsub get_sanitised_netacea_config_cookie_name STRING {\n declare local var.name STRING;\n set var.name = get_netacea_config_cookie_name();\n if (var.name ~ \"^\\s*(.*?)\\s*$\") {\n if (re.group.1 != \"\") {\n return re.group.1;\n }\n }\n return \"_mitata\";\n}\nsub get_sanitised_netacea_config_captcha_cookie_name STRING {\n declare local var.name STRING;\n set var.name = get_netacea_config_captcha_cookie_name();\n if (var.name ~ \"^\\s*(.*?)\\s*$\") {\n if (re.group.1 != \"\") {\n return re.group.1;\n }\n }\n return \"_mitatacaptcha\";\n}\ntable Netacea_Match_Dict {\n \"0\": \"\",\n \"1\": \"ua\",\n \"2\": \"ip\",\n \"3\": \"visitor\",\n \"4\": \"datacenter\",\n \"5\": \"customer_session\",\n \"6\": \"organisation\",\n \"7\": \"asn\",\n \"8\": \"country\",\n \"9\": \"combination\"\n}\ntable Netacea_Mitigate_Dict {\n \"0\": \"\",\n \"1\": \"blocked\",\n \"2\": \"allow\",\n \"3\": \"hardblocked\"\n}\ntable Netacea_Best_Mitigations_Dict {\n \"0\": \"\",\n \"1\": \"block\",\n \"2\": \"allow\",\n \"3\": \"block\"\n}\ntable Netacea_Best_Mitigations_Captcha_Dict {\n \"1\": \"captcha\",\n \"2\": \"\",\n \"3\": \"captcha\",\n \"4\": \"\",\n \"5\": \"captcha\"\n}\ntable Netacea_Captcha_Dict {\n \"0\": \"\",\n \"1\": \"captcha_serve\",\n \"2\": \"captcha_pass\",\n \"3\": \"captcha_fail\",\n \"4\": \"captcha_cookiepass\",\n \"5\": \"captcha_cookiefail\",\n}\nsub get_netacea_captcha_path STRING {\n declare local var.path STRING;\n set var.path = get_netacea_config_captcha_path();\n set var.path = regsub(var.path, \"^\\s*/*\", \"/\");\n set var.path = regsub(var.path, \"\\s*$\", \"\");\n return urldecode(var.path);\n}\nsub get_sanitised_netacea_config_captcha_header STRING {\n declare local var.value STRING;\n set var.value = get_netacea_config_captcha_header();\n set var.value = urldecode(regsuball(var.value, \"&#x(.{2});\", \"%25\\1\"));\n set var.value = std.replaceall(var.value, \""\", \"%22\");\n set var.value = std.replaceall(var.value, \"<\", \"<\");\n set var.value = std.replaceall(var.value, \">\", \">\");\n set var.value = std.replaceall(var.value, \"&\", \"&\");\n return var.value;\n}\nsub get_netacea_captcha_header_name STRING {\n declare local var.config STRING;\n set var.config = get_sanitised_netacea_config_captcha_header();\n if (var.config ~ \"(?i)(?:^|&)\\s*name\\s*=\\s*(.*?)\\s*(?:&|$)\") {\n return re.group.1;\n }\n return \"\";\n}\nsub get_netacea_captcha_header_value STRING {\n declare local var.config STRING;\n set var.config = get_sanitised_netacea_config_captcha_header();\n if (var.config ~ \"(?i)(?:^|&)\\s*value\\s*=\\s*(.*?)\\s*(?:&|$)\") {\n return re.group.1;\n }\n return \"\";\n}\nsub is_path_ignored BOOL {\n declare local var.netacea_ignore_list STRING;\n declare local var.req_path STRING;\n set var.netacea_ignore_list = get_netacea_config_ignore_list();\n set var.req_path = urldecode(req.url.path);\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"\\s*(,\\s*)+\", \",\");\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"(^|,)\\s*/*\", \"\\1/\");\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"/*\\s*(,|$)\", \"\\1\");\n if (var.netacea_ignore_list ~ \"^([^,]+),*([^,]+)?,*([^,]+)?,*([^,]+)?,*([^,]+)?\") {\n if (re.group.1 && (var.req_path == urldecode(re.group.1) || std.prefixof(var.req_path, urldecode(re.group.1) + \"/\"))) {\n return true;\n }\n if (re.group.2 && (var.req_path == urldecode(re.group.2) || std.prefixof(var.req_path, urldecode(re.group.2) + \"/\"))) {\n return true;\n }\n if (re.group.3 && (var.req_path == urldecode(re.group.3) || std.prefixof(var.req_path, urldecode(re.group.3) + \"/\"))) {\n return true;\n }\n if (re.group.4 && (var.req_path == urldecode(re.group.4) || std.prefixof(var.req_path, urldecode(re.group.4) + \"/\"))) {\n return true;\n }\n if (re.group.5 && (var.req_path == urldecode(re.group.5) || std.prefixof(var.req_path, urldecode(re.group.5) + \"/\"))) {\n return true;\n }\n }\n return false;\n}\nsub netacea_should_return_json BOOL {\n declare local var.enable_captcha_content_negotiation STRING;\n set var.enable_captcha_content_negotiation = get_netacea_config_enable_captcha_content_negotiation();\n if (var.enable_captcha_content_negotiation != \"true\") {\n return false;\n }\n declare local var.html_weight FLOAT;\n declare local var.json_weight FLOAT;\n set var.html_weight = 0.0;\n set var.json_weight = 0.0;\n if (req.http.Accept ~ \"(?i)(^|,)\\s*application/json\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.json_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n } elseif (req.http.Accept ~ \"(?i)(^|,)\\s*application/\\*\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.json_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n }\n if (req.http.Accept ~ \"(?i)(^|,)\\s*text/html\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.html_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n } elseif (req.http.Accept ~ \"(^|,)\\s*text/\\*\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.html_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n }\n return var.json_weight > var.html_weight;\n}\nsub netacea_hide_response_headers {\n unset resp.http.X-Netacea-Captcha;\n unset resp.http.X-Netacea-Event-ID;\n unset resp.http.X-Netacea-Match;\n unset resp.http.X-Netacea-MitATA-Expiry;\n unset resp.http.X-Netacea-MitATA-Value;\n unset resp.http.X-Netacea-Mitigate;\n}\nsub set_netacea_captcha_header {\n declare local var.captcha_header_name STRING;\n declare local var.captcha_header_value STRING;\n set var.captcha_header_name = get_netacea_captcha_header_name();\n set var.captcha_header_value = get_netacea_captcha_header_value();\n if (var.captcha_header_name != \"\") {\n header.set(resp, var.captcha_header_name, var.captcha_header_value);\n }\n}\nsub set_netacea_ip_header {\n declare local var.ip_header_name STRING;\n set var.ip_header_name = get_netacea_config_real_ip_header_name();\n declare local var.ip_header_value STRING;\n set var.ip_header_value = if (std.strlen(var.ip_header_name) > 0, header.get(req, var.ip_header_name), \"\");\n set req.http.X-Netacea-Client-IP = if (std.strlen(var.ip_header_value) > 0, var.ip_header_value, client.ip);\n}\nsub set_netacea_cookies {\n if (req.http.netacea_set_cookies == \"1\") {\n declare local var.ignored BOOL;\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_encryption_key STRING;\n set var.ignored = setcookie.delete_by_name(resp, \"_mitata\");\n set var.ignored = setcookie.delete_by_name(resp, \"_mitatacaptcha\");\n declare local var.netacea_captcha_cookie_name STRING;\n set var.netacea_captcha_cookie_name = get_sanitised_netacea_config_captcha_cookie_name();\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n call set_mitata_cookie;\n if (req.http.netacea_mitata_captcha_cookie_value && req.http.netacea_mitata_captcha_cookie_expiry) {\n if (var.netacea_encryption_key ~ \".\") {\n declare local var.netacea_iv STRING;\n declare local var.netacea_iv_trimmed STRING;\n declare local var.netacea_sig STRING;\n declare local var.netacea_mitata_captcha_cookie_value_base64 STRING;\n declare local var.netacea_mitata_captcha_cookie_value_hex STRING;\n declare local var.netacea_mitata_captcha_cookie_value_encrypted STRING;\n declare local var.netacea_mitata_captcha_cookie_final_value STRING;\n set var.netacea_mitata_captcha_cookie_value_base64 = digest.base64(req.http.netacea_mitata_captcha_cookie_value);\n set var.netacea_mitata_captcha_cookie_value_hex = bin.base64_to_hex(var.netacea_mitata_captcha_cookie_value_base64);\n set var.netacea_iv = uuid.version4();\n set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, \"-\", \"\");\n set var.netacea_mitata_captcha_cookie_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_captcha_cookie_value_hex);\n set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_value_encrypted);\n set var.netacea_mitata_captcha_cookie_final_value = var.netacea_iv_trimmed + \".\" + var.netacea_mitata_captcha_cookie_value_encrypted + \".\" + var.netacea_sig;\n add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + \"=\" + var.netacea_mitata_captcha_cookie_final_value + \"; Max-Age=\" + req.http.netacea_mitata_captcha_cookie_expiry + \"; Path=/;\";\n }\n if (var.netacea_encryption_key !~ \".\") {\n add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + \"=\" + req.http.netacea_mitata_captcha_cookie_value + \"; Max-Age=\" + req.http.netacea_mitata_captcha_cookie_expiry + \"; Path=/;\";\n }\n }\n }\n}\nsub netacea_calculate_best_mitigation {\n if (!req.http.netacea_bctype_string) {\n declare local var.netacea_match STRING;\n declare local var.netacea_mitigate STRING;\n declare local var.netacea_captcha STRING;\n declare local var.netacea_match_string STRING;\n declare local var.netacea_mitigate_string STRING;\n declare local var.netacea_captcha_string STRING;\n declare local var.netacea_captcha_mitigate_string STRING;\n declare local var.netacea_best_mitigation STRING;\n declare local var.netacea_bctype_string STRING;\n if (resp.http.x-netacea-match) { \n set var.netacea_match = resp.http.x-netacea-match;\n } elseif (req.http.netacea_match) { \n set var.netacea_match = req.http.netacea_match;\n } else {\n set var.netacea_match = \"0\";\n }\n if (resp.http.x-netacea-mitigate) { \n set var.netacea_mitigate = resp.http.x-netacea-mitigate;\n } elseif (req.http.netacea_mitigate) { \n set var.netacea_mitigate = req.http.netacea_mitigate;\n } else {\n set var.netacea_mitigate = \"0\";\n }\n if (resp.http.x-netacea-captcha) { \n set var.netacea_captcha = resp.http.x-netacea-captcha;\n } elseif (req.http.netacea_captcha) { \n set var.netacea_captcha = req.http.netacea_captcha;\n } else {\n set var.netacea_captcha = \"0\";\n }\n if (var.netacea_match) {\n set var.netacea_match_string = table.lookup(Netacea_Match_Dict, var.netacea_match, \"unknown\");\n if (var.netacea_match_string != \"\") {\n set var.netacea_bctype_string = var.netacea_match_string + \"_\";\n }\n }\n if (var.netacea_mitigate) {\n set var.netacea_mitigate_string = table.lookup(Netacea_Mitigate_Dict, var.netacea_mitigate, \"unknown\");\n if (var.netacea_mitigate_string != \"\") {\n set var.netacea_bctype_string = var.netacea_bctype_string + var.netacea_mitigate_string;\n }\n set var.netacea_best_mitigation = table.lookup(Netacea_Best_Mitigations_Dict, var.netacea_mitigate, \"no-best-mitigation\");\n if (var.netacea_best_mitigation == \"no-best-mitigation\") {\n set var.netacea_best_mitigation = \"\";\n }\n }\n if (var.netacea_captcha) {\n if (req.url != \"/AtaVerifyCaptcha\") {\n if (var.netacea_captcha == \"2\") {\n set var.netacea_captcha = \"4\";\n } elseif (var.netacea_captcha == \"3\") {\n set var.netacea_captcha = \"5\";\n }\n }\n set var.netacea_captcha_string = table.lookup(Netacea_Captcha_Dict, var.netacea_captcha, \"unknown\");\n if (var.netacea_captcha_string != \"\") {\n set var.netacea_bctype_string = var.netacea_bctype_string + \",\" + var.netacea_captcha_string;\n }\n set var.netacea_captcha_mitigate_string = table.lookup(Netacea_Best_Mitigations_Captcha_Dict, var.netacea_captcha, \"no-best-captcha-mitigation\");\n if (var.netacea_captcha_mitigate_string != \"no-best-captcha-mitigation\") {\n set var.netacea_best_mitigation = var.netacea_captcha_mitigate_string;\n }\n }\n set req.http.netacea_bctype_string = var.netacea_bctype_string;\n set req.http.netacea_best_mitigation = var.netacea_best_mitigation;\n set req.http.netacea_best_mitigation_code = var.netacea_match + var.netacea_mitigate + var.netacea_captcha;\n if (var.netacea_mitigate == \"3\") {\n set req.http.netacea_require_revalidation = \"1\";\n }\n if (var.netacea_mitigate == \"1\" && var.netacea_captcha != \"2\" && var.netacea_captcha != \"4\") {\n set req.http.netacea_require_revalidation = \"1\";\n }\n }\n}\nsub set_mitata_cookie {\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_encryption_key STRING;\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n if (!req.http.X-Netacea-UserId) {\n set req.http.X-Netacea-UserId = \"c\" + randomstr(15, \"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n }\n declare local var.netacea_iv STRING;\n declare local var.netacea_iv_trimmed STRING;\n declare local var.netacea_sig STRING;\n declare local var.netacea_mitata_cookie_full_value_base64 STRING;\n declare local var.netacea_mitata_cookie_full_value_hex STRING;\n declare local var.netacea_mitata_cookie_full_value_encrypted STRING;\n declare local var.netacea_mitata_cookie_final_value STRING;\n declare local var.netacea_mitata_cookie_full_value STRING;\n declare local var.netacea_ataCookie_stringValue STRING;\n declare local var.netacea_ataCookie_HMAC STRING;\n declare local var.netacea_mitSvc_exp STRING;\n declare local var.netacea_mitSvc_sig STRING;\n declare local var.netacea_mitSvc_userId STRING;\n declare local var.netacea_mitigation_code STRING;\n declare local var.netacea_client_ip_time STRING;\n declare local var.netacea_client_ip_time_hash STRING;\n declare local var.netacea_cookie_name STRING;\n set var.netacea_mitigation_code = req.http.netacea_best_mitigation_code;\n set var.netacea_mitSvc_userId = req.http.X-Netacea-UserId;\n set var.netacea_cookie_name = get_sanitised_netacea_config_cookie_name();\n if (req.http.netacea_require_revalidation == \"1\") {\n set var.netacea_mitSvc_exp = time.units(\"s\", time.sub(now, 1m));\n } else {\n set var.netacea_mitSvc_exp = time.units(\"s\", time.add(now, 1m));\n }\n set var.netacea_client_ip_time = req.http.X-Netacea-Client-IP + var.netacea_mitSvc_exp;\n set var.netacea_client_ip_time_hash = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_client_ip_time);\n if (var.netacea_client_ip_time_hash ~ \"0x(.*)\") {\n set var.netacea_client_ip_time_hash = re.group.1;\n }\n set var.netacea_ataCookie_stringValue = var.netacea_mitSvc_exp + \"_/@#/\" + var.netacea_mitSvc_userId + \"_/@#/\" + digest.base64(var.netacea_client_ip_time_hash) + \"_/@#/\" + var.netacea_mitigation_code;\n set var.netacea_ataCookie_HMAC = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_ataCookie_stringValue);\n if (var.netacea_ataCookie_HMAC ~ \"0x(.*)\") {\n set var.netacea_ataCookie_HMAC = re.group.1;\n }\n set var.netacea_mitSvc_sig = digest.base64(var.netacea_ataCookie_HMAC);\n set var.netacea_mitata_cookie_full_value = var.netacea_mitSvc_sig + \"_/@#/\" + var.netacea_ataCookie_stringValue;\n if (var.netacea_encryption_key ~ \".\") {\n set var.netacea_mitata_cookie_full_value_base64 = digest.base64(var.netacea_mitata_cookie_full_value);\n set var.netacea_mitata_cookie_full_value_hex = bin.base64_to_hex(var.netacea_mitata_cookie_full_value_base64);\n set var.netacea_iv = uuid.version4();\n set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, \"-\", \"\");\n set var.netacea_mitata_cookie_full_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_cookie_full_value_hex);\n set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_full_value_encrypted);\n set var.netacea_mitata_cookie_final_value = var.netacea_iv_trimmed + \".\" + var.netacea_mitata_cookie_full_value_encrypted + \".\" + var.netacea_sig;\n add resp.http.Set-Cookie = var.netacea_cookie_name + \"=\" + var.netacea_mitata_cookie_final_value + \"; Max-Age=\" + time.units(\"s\", 1d) + \"; Path=/;\";\n }\n if (var.netacea_encryption_key !~ \".\") {\n add resp.http.Set-Cookie = var.netacea_cookie_name + \"=\" + var.netacea_mitata_cookie_full_value+ \"; Max-Age=\" + time.units(\"s\", 1d) + \"; Path=/;\";\n }\n set req.http.mitigation_user_id = var.netacea_mitSvc_userId;\n}\nsub process_netacea_mitata_cookie {\n declare local var.netacea_mitSvc_secret STRING;\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n declare local var.netacea_cookie_sig STRING;\n declare local var.netacea_cookie_payload STRING;\n declare local var.netacea_cookie_expiry STRING;\n declare local var.netacea_client_ip_time_hash STRING;\n declare local var.netacea_real_client_ip_time STRING;\n declare local var.netacea_real_client_ip_time_hash STRING;\n declare local var.netacea_cookie_HMAC STRING;\n declare local var.netacea_cookie_real_value STRING;\n if (req.http.Cookie:_mitata) {\n if (req.http.Cookie:_mitata ~ \"^(.*)_\\/@#\\/((\\d+)_\\/@#\\/(.+)_\\/@#\\/(.+)_\\/@#\\/((\\d)(\\d)(\\d)))$\") {\n set var.netacea_cookie_sig = re.group.1;\n set var.netacea_cookie_payload = re.group.2;\n set var.netacea_cookie_expiry = re.group.3;\n set req.http.X-Netacea-UserId = re.group.4;\n set var.netacea_client_ip_time_hash = re.group.5;\n set req.http.netacea_match = re.group.7;\n set req.http.netacea_mitigate = re.group.8;\n set req.http.netacea_captcha = re.group.9;\n set var.netacea_cookie_real_value = var.netacea_cookie_expiry + \"_/@#/\" + req.http.X-Netacea-UserId + \"_/@#/\" + var.netacea_client_ip_time_hash + \"_/@#/\" + req.http.netacea_match + req.http.netacea_mitigate + req.http.netacea_captcha;\n set var.netacea_cookie_HMAC = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_cookie_real_value);\n if (var.netacea_cookie_HMAC ~ \"0x(.*)\") {\n set var.netacea_cookie_HMAC = re.group.1;\n }\n set var.netacea_real_client_ip_time = req.http.X-Netacea-Client-IP + var.netacea_cookie_expiry;\n set var.netacea_real_client_ip_time_hash = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_real_client_ip_time);\n if (var.netacea_real_client_ip_time_hash ~ \"0x(.*)\") {\n set var.netacea_real_client_ip_time_hash = re.group.1;\n }\n if (var.netacea_cookie_sig != digest.base64(var.netacea_cookie_HMAC)) {\n unset req.http.Cookie:_mitata;\n unset req.http.X-Netacea-UserId;\n unset req.http.netacea_match;\n unset req.http.netacea_mitigate;\n unset req.http.netacea_captcha;\n } else {\n if (time.is_after(now, std.time(var.netacea_cookie_expiry, now)) || digest.base64(var.netacea_real_client_ip_time_hash) != var.netacea_client_ip_time_hash ) {\n set req.http.netacea_mitata_must_reauthenticate = \"1\";\n }\n }\n } else {\n unset req.http.Cookie:_mitata;\n }\n }\n if (!req.http.Cookie:_mitata) {\n unset req.http.Cookie:_mitatacaptcha;\n }\n}\nsub normalise_netacea_cookie_names {\n declare local var.netacea_custom_cookie_name STRING;\n declare local var.netacea_custom_captcha_cookie_name STRING;\n set var.netacea_custom_cookie_name = get_sanitised_netacea_config_cookie_name();\n set var.netacea_custom_captcha_cookie_name = get_sanitised_netacea_config_captcha_cookie_name();\n set req.http.Cookie = regsuball(req.http.Cookie, \";\\s*+\", \"; \");\n if (var.netacea_custom_cookie_name !~ \"^_mitata$\") {\n unset req.http.Cookie:_mitata;\n set req.http.Cookie = std.replace_prefix(req.http.Cookie, var.netacea_custom_cookie_name + \"=\", \"_mitata=\");\n set req.http.Cookie = std.replace(req.http.Cookie, \"; \" + var.netacea_custom_cookie_name + \"=\", \"; _mitata=\");\n }\n if (var.netacea_custom_captcha_cookie_name !~ \"^_mitatacaptcha$\") {\n unset req.http.Cookie:_mitatacaptcha;\n set req.http.Cookie = std.replace_prefix(req.http.Cookie, var.netacea_custom_captcha_cookie_name + \"=\", \"_mitatacaptcha=\");\n set req.http.Cookie = std.replace(req.http.Cookie, \"; \" + var.netacea_custom_captcha_cookie_name + \"=\", \"; _mitatacaptcha=\");\n }\n}\nsub decrypt_netacea_cookies_values {\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_mitata_cookie_encrypted STRING;\n declare local var.netacea_encryption_key STRING;\n declare local var.netacea_iv STRING;\n declare local var.netacea_mitata_cookie_base64 STRING;\n declare local var.netacea_mitata_cookie_hex STRING;\n declare local var.netacea_mitata_cookie_value STRING;\n declare local var.netacea_mitata_cookie_sig STRING;\n declare local var.netacea_mitata_captcha_cookie_encrypted STRING;\n declare local var.netacea_captcha_iv STRING;\n declare local var.netacea_mitata_captcha_cookie_base64 STRING;\n declare local var.netacea_mitata_captcha_cookie_hex STRING;\n declare local var.netacea_mitata_captcha_cookie_value STRING;\n declare local var.netacea_mitata_captcha_cookie_sig STRING;\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n if (var.netacea_encryption_key ~ \".\") {\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n if (req.http.Cookie:_mitata ~ \".\") {\n if (req.http.Cookie:_mitata ~ \"^(.*?)\\.\") {\n set var.netacea_iv = re.group.1;\n }\n if (req.http.Cookie:_mitata ~ \"\\.(.*?)\\.\") {\n set var.netacea_mitata_cookie_encrypted = re.group.1;\n }\n if (req.http.Cookie:_mitata ~ \"([^\\.]+$)\") {\n set var.netacea_mitata_cookie_sig = re.group.1;\n }\n set var.netacea_mitata_cookie_hex = crypto.decrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv, var.netacea_mitata_cookie_encrypted);\n set var.netacea_mitata_cookie_base64 = bin.hex_to_base64(var.netacea_mitata_cookie_hex);\n set var.netacea_mitata_cookie_value = digest.base64_decode(var.netacea_mitata_cookie_base64);\n set req.http.Cookie:_mitata = var.netacea_mitata_cookie_value;\n if(var.netacea_mitata_cookie_sig != digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_encrypted)) {\n unset req.http.Cookie:_mitata;\n }\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"^(.*?)\\.\") {\n if (req.http.Cookie:_mitatacaptcha ~ \"^(.*?)\\.\") {\n set var.netacea_captcha_iv = re.group.1;\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"\\.(.*?)\\.\") {\n set var.netacea_mitata_captcha_cookie_encrypted = re.group.1;\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"([^\\.]+$)\") {\n set var.netacea_mitata_captcha_cookie_sig = re.group.1;\n }\n set var.netacea_mitata_captcha_cookie_hex = crypto.decrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_captcha_iv, var.netacea_mitata_captcha_cookie_encrypted);\n set var.netacea_mitata_captcha_cookie_base64 = bin.hex_to_base64(var.netacea_mitata_captcha_cookie_hex);\n set var.netacea_mitata_captcha_cookie_value = digest.base64_decode(var.netacea_mitata_captcha_cookie_base64);\n set req.http.Cookie:_mitatacaptcha = var.netacea_mitata_captcha_cookie_value;\n if(var.netacea_mitata_captcha_cookie_sig != digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_encrypted)) {\n unset req.http.Cookie:_mitatacaptcha;\n }\n }\n }\n}\nsub cleanup_netacea_variables {\n set req.http.netacea_best_mitigation_code = \"000\";\n set req.http.netacea_match = \"0\";\n set req.http.netacea_mitigate = \"0\";\n set req.http.netacea_captcha = \"0\";\n unset req.http.mit_status;\n unset req.http.netacea_bctype_string;\n unset req.http.netacea_best_mitigation;\n unset req.http.netacea_cookies;\n unset req.http.netacea_mitata_captcha_cookie_expiry;\n unset req.http.netacea_mitata_captcha_cookie_value;\n unset req.http.netacea_mitata_must_reauthenticate;\n unset req.http.netacea_require_revalidation;\n unset req.http.netacea_set_cookies;\n unset req.http.X-Netacea-Match;\n unset req.http.X-Netacea-Mitigate;\n unset req.http.X-Netacea-Captcha;\n unset req.http.X-Netacea-Event-ID;\n unset req.http.X-Netacea-Api-Key;\n unset req.http.X-Netacea-Captcha-Status;\n unset req.http.X-Netacea-UserId;\n unset req.http.X-Netacea-Compile-JSON;\n unset req.http.x-netacea;\n}\nsub netacea_check_req {\n declare local var.netacea_mitSvc_authenticate BOOL;\n declare local var.netacea_mitSvc_apiKey STRING;\n declare local var.netacea_integration_mode STRING;\n declare local var.netacea_use_relative_path_captcha_assets STRING;\n declare local var.captcha_path STRING;\n if (req.http.x-netacea:netacea_check_req_called) {\n return;\n }\n set var.netacea_integration_mode = get_netacea_config_integration_mode();\n if (std.strlen(var.netacea_integration_mode) == 0) {\n return;\n }\n set req.http.x-netacea:netacea_check_req_called = \"true\";\n unset req.http.netacea_processed;\n if (is_path_ignored()) {\n return;\n }\n set var.netacea_mitSvc_apiKey = get_netacea_config_api_key();\n set var.netacea_use_relative_path_captcha_assets = get_netacea_config_use_relative_path_captcha_assets();\n set var.captcha_path = get_netacea_captcha_path();\n if (var.netacea_use_relative_path_captcha_assets == \"true\") {\n if (std.prefixof(req.url.path, \"/Mitigations/\") && req.method == \"GET\") {\n if (std.suffixof(req.url.path, \".css\") || std.suffixof(req.url.path, \".js\")) {\n set req.backend = F_CaptchaAssets;\n return(lookup);\n }\n }\n }\n if (var.captcha_path != \"\" && urldecode(req.url.path) == var.captcha_path) {\n set req.backend = F_MitSvc;\n if (req.backend.healthy) {\n set req.http.netacea_origin_method = \"GET\";\n set req.http.netacea_processed = \"1\";\n set req.http.netacea_captcha_path = \"1\";\n set req.http.netacea_origin_host = req.http.host;\n set req.http.netacea_origin_url = req.url;\n set req.url = \"/captcha?\" + req.url.qs;\n set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;\n return(lookup);\n }\n }\n if (req.restarts == 0 && fastly.ff.visits_this_service == 0) {\n call set_netacea_ip_header;\n if (var.netacea_integration_mode != \"BYPASS\") {\n set var.netacea_mitSvc_authenticate = true;\n call normalise_netacea_cookie_names;\n call decrypt_netacea_cookies_values;\n call process_netacea_mitata_cookie;\n }\n } else {\n if (req.http.X-Netacea-Compile-JSON == \"requested\") {\n set req.http.netacea_processed = \"1\";\n set req.http.X-Netacea-Compile-JSON = \"processing\";\n error 601;\n }\n if (var.netacea_integration_mode == \"MITIGATE\" && req.http.netacea_best_mitigation == \"block\") {\n error 403;\n }\n }\n if (req.http.Cookie:_mitata && !req.http.netacea_mitata_must_reauthenticate) {\n set var.netacea_mitSvc_authenticate = false;\n }\n set req.http.mitigation_user_id = req.http.X-Netacea-UserId;\n set req.http.integration_type = get_netacea_config_integration_type();\n set req.http.integration_version = get_netacea_config_integration_version();\n if (var.netacea_mitSvc_authenticate) {\n set req.http.netacea_set_cookies = \"1\";\n } else {\n if (var.netacea_integration_mode == \"INJECT\" && req.restarts == 0 && fastly.ff.visits_this_service == 0) {\n set req.http.X-Netacea-Match = req.http.netacea_match;\n set req.http.X-Netacea-Mitigate = req.http.netacea_mitigate;\n set req.http.X-Netacea-Captcha = req.http.netacea_captcha;\n }\n }\n if (var.netacea_integration_mode ~ \"(MITIGATE|INJECT)\" && var.netacea_mitSvc_authenticate) {\n set req.backend = F_MitSvc;\n if (req.backend.healthy) {\n unset req.http.netacea_match;\n unset req.http.netacea_mitigate;\n unset req.http.netacea_captcha;\n unset req.http.Cookie:_mitata;\n set req.http.netacea_origin_method = req.method;\n set req.http.netacea_processed = \"1\";\n set req.http.netacea_origin_host = req.http.host;\n set req.http.netacea_origin_url = req.url;\n if (req.url != \"/AtaVerifyCaptcha\") {\n set req.method = \"GET\";\n set req.url = \"/\";\n }\n set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;\n return(pass);\n }\n }\n}\n", "type": "init" } ], - "version": 7 + "version": "5.7.0" }