| @ -0,0 +1,238 @@ | |||||
| ######## DoS prevention module ######## | |||||
| # Default "order" is "Deny,Allow"(DA). | |||||
| # So if there is no data from DB request will be permitted by default. | |||||
| # | |||||
| loadmodule "ipops.so" | |||||
| modparam("htable", "htable", "acl=>initval=-1;autoexpire=7200") | |||||
| #!trydef ACL_MESSAGE_DENY "Rejected by ACL" | |||||
| #!trydef ACL_CODE_DENY "603" | |||||
| #!trydef ACL_ORDER_ALLOW_DENY "AD" | |||||
| #!trydef ACL_IP_ADDR_ANY "0.0.0.0/0" | |||||
| #!trydef IP_REGEX "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}" | |||||
| ## Route for ACL functionality | |||||
| route[ACL_CHECK] { | |||||
| if (isflagset(FLAG_IS_REPLY)) { | |||||
| $var(sip-packet) = $rs; | |||||
| } else { | |||||
| $var(sip-packet) = $rm; | |||||
| } | |||||
| # FIXUP for BYE method with IPinstead of REALM in From, take REALM fron To header | |||||
| if ($fd =~ IP_REGEX) { | |||||
| xlog("L_WARNING","$ci |ACL-realm| Fixup for $var(sip-packet) with IP in from URI: use to-domain"); | |||||
| $var(realm) = $td; | |||||
| } else { | |||||
| $var(realm) = $fd; | |||||
| } | |||||
| $var(acl-realm-request) = "false"; | |||||
| $var(acl-device-request) = "false"; | |||||
| $var(realm-decision) = $sht(acl=>$var(realm)/$si); | |||||
| if ($var(realm-decision) == -1) { # we do not have cached decision | |||||
| $var(acl-realm-request) = "true"; | |||||
| } else if ($var(realm-decision) == 1 ){ # We have cached decision, let's use it | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is permitted by ACL for $var(realm)\n"); | |||||
| return; | |||||
| } else { | |||||
| if (!isflagset(FLAG_IS_REPLY)) { | |||||
| sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY); | |||||
| } | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is rejected by ACL for $var(realm)\n"); | |||||
| exit; | |||||
| } | |||||
| if (not_empty("$fU")) { | |||||
| if ($fd =~ IP_REGEX) { | |||||
| xlog("L_WARNING","$ci |ACL-device| Fixup for $var(sip-packet) with IP in from URI: use to-domain"); | |||||
| $var(device) = $fU + "@" + $td; | |||||
| } else { | |||||
| $var(device) = $fU + "@" + $fd; | |||||
| } | |||||
| $var(device-decision) = $sht(acl=>$var(device)/$si); | |||||
| if ($var(device-decision) == -1) { # we do not have cached decision | |||||
| $var(acl-device-request) = "true"; | |||||
| } else if ($var(device-decision) == 1 ){ # We have cached decision, let's use it | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is permitted by ACL for $var(device)\n"); | |||||
| return; | |||||
| } else { | |||||
| if (!isflagset(FLAG_IS_REPLY)) { | |||||
| sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY); | |||||
| } | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is rejected by ACL for $var(device)\n"); | |||||
| exit; | |||||
| } | |||||
| } | |||||
| if ($var(acl-realm-request) == "true" || $var(acl-device-request)) { | |||||
| if (not_empty("$fU")) | |||||
| $var(query) = "{'Event-Category': 'acl', 'Event-Name': 'query', 'Entity': '" + $var(device) + "', 'With-Realm': " + $var(acl-realm-request) + "}"; | |||||
| else | |||||
| $var(query) = "{'Event-Category': 'acl', 'Event-Name': 'query', 'Entity': '" + $var(realm) + "'}"; | |||||
| xlog("L_INFO", "$ci |ACL log| Query: $var(query)"); | |||||
| if (kazoo_query("frontier", "sbc_config", $var(query), "$var(acl-response)")) { | |||||
| xlog("L_INFO", "$ci |ACL log| Response: $var(acl-response)"); | |||||
| kazoo_json($var(acl-response), "Realm.Order", "$var(acl-realm-order)"); | |||||
| kazoo_json($var(acl-response), "Realm.CIDR", "$var(acl-realm-cidr)"); | |||||
| kazoo_json($var(acl-response), "Realm.CIDR.length", "$var(acl-realm-cidr-len)"); | |||||
| kazoo_json($var(acl-response), "Realm.User-Agent", "$var(acl-realm-ua)"); | |||||
| kazoo_json($var(acl-response), "Device.Order", "$var(acl-device-order)"); | |||||
| kazoo_json($var(acl-response), "Device.CIDR", "$var(acl-device-cidr)"); | |||||
| kazoo_json($var(acl-response), "Device.CIDR.length","$var(acl-device-cidr-len)"); | |||||
| kazoo_json($var(acl-response), "Device.User-Agent", "$var(acl-device-ua)"); | |||||
| } else { | |||||
| xlog("L_ERROR","$ci |ACL log| DB is unreachable"); | |||||
| $sht(acl=>$var(device)/$si) = 1; | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is permitted by ACL for $var(device)\n"); | |||||
| return; | |||||
| } | |||||
| } | |||||
| route(ACL_CHECK_REALM); | |||||
| if (not_empty("$fU")) { | |||||
| route(ACL_CHECK_DEVICE); | |||||
| } | |||||
| } | |||||
| # Check ORDER setting for REALM | |||||
| route[ACL_CHECK_REALM] { | |||||
| if (not_empty("$var(acl-realm-order)")) { | |||||
| if ($var(acl-realm-order) == ACL_ORDER_ALLOW_DENY) { | |||||
| route(ACL_CHECK_REALM_ALLOW); | |||||
| } else { | |||||
| route(ACL_CHECK_REALM_DENY); | |||||
| } | |||||
| } else { | |||||
| xlog("L_INFO","$ci |ACL-realm| undefined Order in response for $var(realm)"); | |||||
| $sht(acl=>$var(realm)/$si) = 1; | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is permitted by ACL for $var(realm)\n"); | |||||
| } | |||||
| } | |||||
| route[ACL_CHECK_REALM_ALLOW] { | |||||
| if (not_empty("$var(acl-realm-cidr)")) { | |||||
| $var(i) = 0; | |||||
| xlog("L_INFO", "$ci |ACL-realm| checking $var(acl-realm-cidr-len) record(s)"); | |||||
| while($var(i) < $var(acl-realm-cidr-len)) { | |||||
| kazoo_json($var(acl-realm-cidr), "[$var(i)]", "$var(record)"); | |||||
| xlog("L_INFO", "$ci |ACL-realm| checking if $si is in $var(record)"); | |||||
| if (($var(record) == ACL_IP_ADDR_ANY) || is_in_subnet("$si", $var(record))) { | |||||
| $sht(acl=>$var(realm)/$si) = 1; | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is permitted by ACL for $var(realm)\n"); | |||||
| return; | |||||
| } | |||||
| $var(i) = $var(i) + 1; | |||||
| } | |||||
| } else { | |||||
| xlog("L_INFO", "$ci |ACL-realm| undefined CIDR in response for $var(realm)"); | |||||
| } | |||||
| # Remember in CACHE and DENY | |||||
| $sht(acl=>$var(realm)/$si) = 0; | |||||
| if (!isflagset(FLAG_IS_REPLY)) { | |||||
| sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY); | |||||
| } | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is rejected by ACL for $var(realm)\n"); | |||||
| exit; | |||||
| } | |||||
| route[ACL_CHECK_REALM_DENY] { | |||||
| $var(size) = $(kzR{kz.json,Realm.CIDR.length}); | |||||
| if (not_empty("$var(acl-realm-cidr)")) { | |||||
| $var(i) = 0; | |||||
| xlog("L_INFO", "$ci |ACL-realm| checking $var(acl-realm-cidr-len) record(s)"); | |||||
| while($var(i) < $var(acl-realm-cidr-len)) { | |||||
| kazoo_json($var(acl-realm-cidr), "[$var(i)]", "$var(record)"); | |||||
| xlog("L_INFO", "$ci |ACL-realm| checking if $si is in $var(record)"); | |||||
| if (($var(record) == ACL_IP_ADDR_ANY) || is_in_subnet("$si", $var(record))) { | |||||
| $sht(acl=>$var(realm)/$si) = 0; | |||||
| if (!isflagset(FLAG_IS_REPLY)) { | |||||
| sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY); | |||||
| } | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is rejected by ACL for $var(realm)\n"); | |||||
| exit; | |||||
| } | |||||
| $var(i) = $var(i) + 1; | |||||
| } | |||||
| } else { | |||||
| xlog("L_INFO", "$ci |ACL-realm| undefined CIDR in response for $var(realm)"); | |||||
| } | |||||
| # Remember in CACHE and ALLOW | |||||
| $sht(acl=>$var(realm)/$si) = 1; | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is permitted by ACL for $var(realm)\n"); | |||||
| return; | |||||
| } | |||||
| # Check ORDER setting for DEVICE | |||||
| route[ACL_CHECK_DEVICE] { | |||||
| if (not_empty("$var(acl-device-order)")) { | |||||
| if ($var(acl-device-order) == ACL_ORDER_ALLOW_DENY) { | |||||
| route(ACL_CHECK_DEVICE_ALLOW); | |||||
| } else { | |||||
| route(ACL_CHECK_DEVICE_DENY); | |||||
| } | |||||
| } else { | |||||
| xlog("L_INFO","$ci |ACL-device| undefined Order in response for $var(device)"); | |||||
| $sht(acl=>$var(device)/$si) = 1; | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is permitted by ACL for $var(device)\n"); | |||||
| } | |||||
| } | |||||
| route[ACL_CHECK_DEVICE_ALLOW] { | |||||
| if (not_empty("$var(acl-device-cidr)")) { | |||||
| $var(i) = 0; | |||||
| xlog("L_INFO", "$ci |ACL-realm| checking $var(acl-device-cidr-len) record(s)"); | |||||
| while($var(i) < $var(acl-device-cidr-len)) { | |||||
| kazoo_json($var(acl-device-cidr), "[$var(i)]", "$var(record)"); | |||||
| xlog("L_INFO", "$ci |ACL-realm| checking if $si is in $var(record)"); | |||||
| if (($var(record) == ACL_IP_ADDR_ANY) || is_in_subnet("$si", $var(record))) { | |||||
| $sht(acl=>$var(device)/$si) = 1; | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is permitted by ACL for $var(device)\n"); | |||||
| return; | |||||
| } | |||||
| $var(i) = $var(i) + 1; | |||||
| } | |||||
| } else { | |||||
| xlog("L_INFO", "$ci |ACL-realm| undefined CIDR in response for $var(device)"); | |||||
| } | |||||
| # Remember in CACHE and DENY | |||||
| $sht(acl=>$var(device)/$si) = 0; | |||||
| if (!isflagset(FLAG_IS_REPLY)) { | |||||
| sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY); | |||||
| } | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is rejected by ACL for $var(device)\n"); | |||||
| exit; | |||||
| } | |||||
| route[ACL_CHECK_DEVICE_DENY] { | |||||
| if (not_empty("$var(acl-device-cidr)")) { | |||||
| $var(i) = 0; | |||||
| xlog("L_INFO", "$ci |ACL-device| checking $var(acl-device-cidr-len) record(s)"); | |||||
| while($var(i) < $var(acl-device-cidr-len)) { | |||||
| kazoo_json($var(acl-device-cidr), "[$var(i)]", "$var(record)"); | |||||
| xlog("L_INFO", "$ci |ACL-device| checking if $si is in $var(record)"); | |||||
| if (($var(record) == ACL_IP_ADDR_ANY) || is_in_subnet("$si", $var(record))) { | |||||
| $sht(acl=>$var(device)/$si) = 0; | |||||
| if (!isflagset(FLAG_IS_REPLY)) { | |||||
| sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY); | |||||
| } | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is rejected by ACL for $var(device)\n"); | |||||
| exit; | |||||
| } | |||||
| $var(i) = $var(i) + 1; | |||||
| } | |||||
| } else { | |||||
| xlog("L_INFO", "$ci |ACL-device| undefined CIDR in response for $var(device)"); | |||||
| } | |||||
| # Remember in CACHE and ALLOW | |||||
| $sht(acl=>$var(device)/$si) = 1; | |||||
| xlog("L_INFO", "$ci |ACL| $var(sip-packet) from $si is permitted by ACL for $var(device)\n"); | |||||
| return; | |||||
| } | |||||