bad behavior - move from fail2ban to pure lua
This commit is contained in:
parent
eb2d0d330d
commit
0b3ff6a9f4
|
@ -14,8 +14,6 @@ RUN chmod +x /tmp/dependencies.sh && \
|
|||
COPY entrypoint/ /opt/entrypoint
|
||||
COPY confs/ /opt/confs
|
||||
COPY scripts/ /opt/scripts
|
||||
COPY fail2ban/ /opt/fail2ban
|
||||
COPY logs/ /opt/logs
|
||||
COPY lua/ /opt/lua
|
||||
|
||||
COPY prepare.sh /tmp/prepare.sh
|
||||
|
|
|
@ -14,8 +14,6 @@ RUN chmod +x /tmp/dependencies.sh && \
|
|||
COPY entrypoint/ /opt/entrypoint
|
||||
COPY confs/ /opt/confs
|
||||
COPY scripts/ /opt/scripts
|
||||
COPY fail2ban/ /opt/fail2ban
|
||||
COPY logs/ /opt/logs
|
||||
COPY lua/ /opt/lua
|
||||
|
||||
COPY prepare.sh /tmp/prepare.sh
|
||||
|
|
|
@ -21,8 +21,6 @@ RUN chmod +x /tmp/dependencies.sh && \
|
|||
COPY entrypoint/ /opt/entrypoint
|
||||
COPY confs/ /opt/confs
|
||||
COPY scripts/ /opt/scripts
|
||||
COPY fail2ban/ /opt/fail2ban
|
||||
COPY logs/ /opt/logs
|
||||
COPY lua/ /opt/lua
|
||||
|
||||
COPY prepare.sh /tmp/prepare.sh
|
||||
|
|
|
@ -21,8 +21,6 @@ RUN chmod +x /tmp/dependencies.sh && \
|
|||
COPY entrypoint/ /opt/entrypoint
|
||||
COPY confs/ /opt/confs
|
||||
COPY scripts/ /opt/scripts
|
||||
COPY fail2ban/ /opt/fail2ban
|
||||
COPY logs/ /opt/logs
|
||||
COPY lua/ /opt/lua
|
||||
|
||||
COPY prepare.sh /tmp/prepare.sh
|
||||
|
|
|
@ -14,8 +14,6 @@ RUN chmod +x /tmp/dependencies.sh && \
|
|||
COPY entrypoint/ /opt/entrypoint
|
||||
COPY confs/ /opt/confs
|
||||
COPY scripts/ /opt/scripts
|
||||
COPY fail2ban/ /opt/fail2ban
|
||||
COPY logs/ /opt/logs
|
||||
COPY lua/ /opt/lua
|
||||
|
||||
COPY prepare.sh /tmp/prepare.sh
|
||||
|
|
|
@ -89,6 +89,7 @@ http {
|
|||
%BLOCK_TOR_EXIT_NODES%
|
||||
%BLOCK_USER_AGENTS%
|
||||
%BLOCK_REFERRERS%
|
||||
%BAD_BEHAVIOR%
|
||||
|
||||
# crowdsec init
|
||||
%USE_CROWDSEC%
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
log_by_lua_block {
|
||||
|
||||
local use_bad_behavior = %USE_BAD_BEHAVIOR%
|
||||
|
||||
local behavior = require "behavior"
|
||||
|
||||
if use_bad_behavior then
|
||||
behavior.count()
|
||||
end
|
||||
|
||||
}
|
|
@ -20,6 +20,7 @@ local use_antibot_cookie = %USE_ANTIBOT_COOKIE%
|
|||
local use_antibot_javascript = %USE_ANTIBOT_JAVASCRIPT%
|
||||
local use_antibot_captcha = %USE_ANTIBOT_CAPTCHA%
|
||||
local use_antibot_recaptcha = %USE_ANTIBOT_RECAPTCHA%
|
||||
local use_bad_behavior = %USE_BAD_BEHAVIOR%
|
||||
|
||||
-- include LUA code
|
||||
local whitelist = require "whitelist"
|
||||
|
@ -30,6 +31,7 @@ local javascript = require "javascript"
|
|||
local captcha = require "captcha"
|
||||
local recaptcha = require "recaptcha"
|
||||
local iputils = require "resty.iputils"
|
||||
local behavior = require "behavior"
|
||||
|
||||
-- user variables
|
||||
local antibot_uri = "%ANTIBOT_URI%"
|
||||
|
@ -98,6 +100,12 @@ if use_blacklist_reverse and not blacklist.reverse_cached() then
|
|||
end
|
||||
end
|
||||
|
||||
-- check if IP is banned because of "bad behavior"
|
||||
if use_bad_behavior and behavior.is_banned() then
|
||||
ngx.log(ngx.NOTICE, "[BLOCK] IP " .. ngx.var.remote_addr .. " is banned because of bad behavior")
|
||||
ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||
end
|
||||
|
||||
-- check if IP is in proxies list
|
||||
if use_proxies then
|
||||
local value, flags = ngx.shared.proxies_data:get(iputils.ip2bin(ngx.var.remote_addr))
|
||||
|
|
|
@ -4,7 +4,7 @@ server {
|
|||
%FASTCGI_PATH%
|
||||
%SERVER_CONF%
|
||||
%PROXY_REAL_IP%
|
||||
%MAIN_LUA%
|
||||
%INCLUDE_LUA%
|
||||
%USE_MODSECURITY%
|
||||
%LISTEN_HTTP%
|
||||
%USE_HTTPS%
|
||||
|
@ -29,7 +29,6 @@ server {
|
|||
%PERMISSIONS_POLICY%
|
||||
%COOKIE_FLAGS%
|
||||
%ERRORS%
|
||||
%USE_FAIL2BAN%
|
||||
%USE_CLIENT_CACHE%
|
||||
%USE_GZIP%
|
||||
%USE_BROTLI%
|
||||
|
|
|
@ -69,15 +69,13 @@ CONTENT_SECURITY_POLICY="${CONTENT_SECURITY_POLICY-object-src 'none'; frame-ance
|
|||
COOKIE_FLAGS="${COOKIE_FLAGS-* HttpOnly SameSite=Lax}"
|
||||
COOKIE_AUTO_SECURE_FLAG="${COOKIE_AUTO_SECURE_FLAG-yes}"
|
||||
SERVE_FILES="${SERVE_FILES-yes}"
|
||||
WRITE_ACCESS="${WRITE_ACCESS-no}"
|
||||
REDIRECT_HTTP_TO_HTTPS="${REDIRECT_HTTP_TO_HTTPS-no}"
|
||||
LISTEN_HTTP="${LISTEN_HTTP-yes}"
|
||||
USE_FAIL2BAN="${USE_FAIL2BAN-yes}"
|
||||
FAIL2BAN_STATUS_CODES="${FAIL2BAN_STATUS_CODES-400|401|403|404|405|444}"
|
||||
FAIL2BAN_BANTIME="${FAIL2BAN_BANTIME-3600}"
|
||||
FAIL2BAN_FINDTIME="${FAIL2BAN_FINDTIME-60}"
|
||||
FAIL2BAN_MAXRETRY="${FAIL2BAN_MAXRETRY-15}"
|
||||
FAIL2BAN_IGNOREIP="${FAIL2BAN_IGNOREIP-127.0.0.1/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8}"
|
||||
USE_BAD_BEHAVIOR="${USE_BAD_BEHAVIOR-yes}"
|
||||
BAD_BEHAVIOR_STATUS_CODES="${BAD_BEHAVIOR_STATUS_CODES-400 401 403 404 405 429 444}"
|
||||
BAD_BEHAVIOR_THRESHOLD="${BAD_BEHAVIOR_THRESHOLD-10}"
|
||||
BAD_BEHAVIOR_BAN_TIME="${BAD_BEHAVIOR_BAN_TIME-86400}"
|
||||
BAD_BEHAVIOR_COUNT_TIME="${BAD_BEHAVIOR_COUNT_TIME-60}"
|
||||
USE_CLAMAV_UPLOAD="${USE_CLAMAV_UPLOAD-yes}"
|
||||
USE_CLAMAV_SCAN="${USE_CLAMAV_SCAN-yes}"
|
||||
USE_CLAMAV_SCAN_CRON="${USE_CLAMAV_SCAN_CRON-30 1 * * *}"
|
||||
|
|
|
@ -105,11 +105,6 @@ fi
|
|||
echo "[*] Running nginx ..."
|
||||
nginx &
|
||||
pid="$!"
|
||||
#if [ "$?" -eq 0 ] ; then
|
||||
# echo "[*] nginx successfully started !"
|
||||
#else
|
||||
# echo "[!] nginx failed to start"
|
||||
#fi
|
||||
|
||||
# autotest
|
||||
if [ "$1" == "test" ] ; then
|
||||
|
|
|
@ -220,9 +220,11 @@ else
|
|||
replace_in_file "/etc/nginx/multisite-default-server.conf" "%MULTISITE_DISABLE_DEFAULT_SERVER%" ""
|
||||
fi
|
||||
|
||||
# fail2ban setup
|
||||
if [ "$(has_value USE_FAIL2BAN yes)" != "" ] ; then
|
||||
echo "" > /etc/nginx/fail2ban-ip.conf
|
||||
# bad behavior
|
||||
if [ "$(has_value USE_BAD_BEHAVIOR yes)" != "" ] ; then
|
||||
replace_in_file "/etc/nginx/nginx.conf" "%BAD_BEHAVIOR%" "lua_shared_dict behavior_ban 10m;\nlua_shared_dict behavior_count 10m;"
|
||||
else
|
||||
replace_in_file "/etc/nginx/nginx.conf" "%BAD_BEHAVIOR%" ""
|
||||
fi
|
||||
|
||||
# CrowdSec setup
|
||||
|
|
|
@ -33,6 +33,13 @@ replace_in_file "/usr/local/lib/lua/blacklist.lua" "%BLACKLIST_REVERSE_LIST%" "$
|
|||
list=$(spaces_to_lua "$DNSBL_LIST")
|
||||
replace_in_file "/usr/local/lib/lua/dnsbl.lua" "%DNSBL_LIST%" "$list"
|
||||
|
||||
# bad behavior
|
||||
list=$(spaces_to_lua "$BAD_BEHAVIOR_STATUS_CODES")
|
||||
replace_in_file "/usr/local/lib/lua/behavior.lua" "%STATUS_CODES%" "$list"
|
||||
replace_in_file "/usr/local/lib/lua/behavior.lua" "%THRESHOLD%" "$BAD_BEHAVIOR_THRESHOLD"
|
||||
replace_in_file "/usr/local/lib/lua/behavior.lua" "%BAN_TIME%" "$BAD_BEHAVIOR_BAN_TIME"
|
||||
replace_in_file "/usr/local/lib/lua/behavior.lua" "%COUNT_TIME%" "$BAD_BEHAVIOR_COUNT_TIME"
|
||||
|
||||
# CrowdSec setup
|
||||
if [ "$(has_value USE_CROWDSEC yes)" != "" ] ; then
|
||||
replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_HOST%" "$CROWDSEC_HOST"
|
||||
|
|
|
@ -38,7 +38,7 @@ fi
|
|||
cp /opt/confs/site/* "$NGINX_PREFIX"
|
||||
|
||||
# replace paths
|
||||
replace_in_file "${NGINX_PREFIX}server.conf" "%MAIN_LUA%" "include ${NGINX_PREFIX}main-lua.conf;"
|
||||
replace_in_file "${NGINX_PREFIX}server.conf" "%INCLUDE_LUA%" "include ${NGINX_PREFIX}main-lua.conf;\ninclude ${NGINX_PREFIX}log-lua.conf;"
|
||||
if [ "$MULTISITE" = "yes" ] ; then
|
||||
replace_in_file "${NGINX_PREFIX}server.conf" "%SERVER_CONF%" "include /server-confs/*.conf;\ninclude /server-confs/${first_server}/*.conf;"
|
||||
replace_in_file "${NGINX_PREFIX}server.conf" "%PRE_SERVER_CONF%" "include /pre-server-confs/*.conf;\ninclude /pre-server-confs/${first_server}/*.conf;"
|
||||
|
@ -562,6 +562,15 @@ else
|
|||
replace_in_file "${NGINX_PREFIX}main-lua.conf" "%INCLUDE_ANTIBOT_RECAPTCHA%" ""
|
||||
fi
|
||||
|
||||
# bad behavior
|
||||
if [ "$USE_BAD_BEHAVIOR" = "yes" ] ; then
|
||||
replace_in_file "${NGINX_PREFIX}main-lua.conf" "%USE_BAD_BEHAVIOR%" "true"
|
||||
replace_in_file "${NGINX_PREFIX}log-lua.conf" "%USE_BAD_BEHAVIOR%" "true"
|
||||
else
|
||||
replace_in_file "${NGINX_PREFIX}main-lua.conf" "%USE_BAD_BEHAVIOR%" "false"
|
||||
replace_in_file "${NGINX_PREFIX}log-lua.conf" "%USE_BAD_BEHAVIOR%" "false"
|
||||
fi
|
||||
|
||||
# request limiting
|
||||
if [ "$USE_LIMIT_REQ" = "yes" ] ; then
|
||||
replace_in_file "${NGINX_PREFIX}server.conf" "%LIMIT_REQ%" "include ${NGINX_PREFIX}limit-req.conf;"
|
||||
|
@ -578,13 +587,6 @@ else
|
|||
replace_in_file "${NGINX_PREFIX}server.conf" "%LIMIT_CONN%" ""
|
||||
fi
|
||||
|
||||
# fail2ban
|
||||
if [ "$USE_FAIL2BAN" = "yes" ] ; then
|
||||
replace_in_file "${NGINX_PREFIX}server.conf" "%USE_FAIL2BAN%" "include /etc/nginx/fail2ban-ip.conf;"
|
||||
else
|
||||
replace_in_file "${NGINX_PREFIX}server.conf" "%USE_FAIL2BAN%" ""
|
||||
fi
|
||||
|
||||
# clamav scan uploaded files
|
||||
if [ "$USE_CLAMAV_UPLOAD" = "yes" ] ; then
|
||||
replace_in_file "${NGINX_PREFIX}modsecurity-rules.conf" "%USE_CLAMAV_UPLOAD%" "include ${NGINX_PREFIX}modsecurity-clamav.conf"
|
||||
|
|
|
@ -30,7 +30,7 @@ services:
|
|||
- nc.website.com_LIMIT_REQ_BURST=10
|
||||
- nc.website.com_ALLOWED_METHODS=GET|POST|HEAD|COPY|DELETE|LOCK|MKCOL|MOVE|PROPFIND|PROPPATCH|PUT|UNLOCK|OPTIONS
|
||||
- nc.website.com_X_FRAME_OPTIONS=SAMEORIGIN
|
||||
- nc.website.com_FAIL2BAN_STATUS_CODE=400|401|403|405|444
|
||||
- nc.website.com_BAD_BEHAVIOR_STATUS_CODE=400|401|403|405|444
|
||||
networks:
|
||||
- net1
|
||||
- net2
|
||||
|
|
|
@ -28,7 +28,7 @@ services:
|
|||
- ALLOWED_METHODS=GET|POST|HEAD|COPY|DELETE|LOCK|MKCOL|MOVE|PROPFIND|PROPPATCH|PUT|UNLOCK|OPTIONS
|
||||
- X_FRAME_OPTIONS=SAMEORIGIN
|
||||
- USE_GZIP=yes
|
||||
- FAIL2BAN_STATUS_CODE=400|401|403|405|444
|
||||
- BAD_BEHAVIOR_STATUS_CODE=400|401|403|405|444
|
||||
|
||||
mync:
|
||||
image: nextcloud:21-fpm
|
||||
|
|
|
@ -20,7 +20,7 @@ services:
|
|||
- BLOCK_TOR_EXIT_NODE=no
|
||||
- BLOCK_ABUSERS=no
|
||||
- BLOCK_PROXIES=no
|
||||
- USE_FAIL2BAN=no
|
||||
- USE_BAD_BEHAVIOR=no
|
||||
- USE_DNSBL=no
|
||||
- USE_WHITELIST_IP=no
|
||||
- USE_WHITELIST_REVERSE=no
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
[Definition]
|
||||
|
||||
actionstart = echo "" > /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
|
||||
actionstop = echo "" > /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
|
||||
actioncheck =
|
||||
actionflush = echo "" > /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
|
||||
actionban = echo -n "deny <ip>;" >> /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
|
||||
actionunban = sed -i "s/deny <ip>;//g" /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
|
|
@ -1,7 +0,0 @@
|
|||
[INCLUDES]
|
||||
before = common.conf
|
||||
|
||||
[Definition]
|
||||
failregex = <HOST> - .* \[.*\] ".*" (%FAIL2BAN_STATUS_CODES%) .* ".*" ".*"
|
||||
ignoreregex =
|
||||
datepattern = %%d/%%b/%%Y:%%H:%%M:%%S
|
|
@ -1,8 +0,0 @@
|
|||
[nginx-filter]
|
||||
bantime = %FAIL2BAN_BANTIME%
|
||||
findtime = %FAIL2BAN_FINDTIME%
|
||||
maxretry = %FAIL2BAN_MAXRETRY%
|
||||
ignoreip = %FAIL2BAN_IGNOREIP%
|
||||
enabled = true
|
||||
action = nginx-action
|
||||
logpath = /var/log/access.log
|
|
@ -1,23 +0,0 @@
|
|||
/var/log/*.log /var/log/clamav/*.log /var/log/nginx/*.log /var/log/letsencrypt/*.log {
|
||||
# compress old files using gzip
|
||||
compress
|
||||
|
||||
# rotate everyday
|
||||
daily
|
||||
|
||||
# remove old logs after X days
|
||||
maxage %LOGROTATE_MAXAGE%
|
||||
rotate %LOGROTATE_MAXAGE%
|
||||
|
||||
# no errors if a file is missing
|
||||
missingok
|
||||
|
||||
# disable mailing
|
||||
nomail
|
||||
|
||||
# mininum size of a logfile before rotating
|
||||
minsize %LOGROTATE_MINSIZE%
|
||||
|
||||
# make a copy and truncate the files
|
||||
copytruncate
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
#### Global directives ####
|
||||
|
||||
# Sets the directory that rsyslog uses for work files.
|
||||
$WorkDirectory /var/lib/rsyslog
|
||||
|
||||
# Sets default permissions for all log files.
|
||||
$FileOwner nginx
|
||||
$FileGroup nginx
|
||||
$FileCreateMode 0660
|
||||
$DirCreateMode 0770
|
||||
$Umask 0007
|
||||
|
||||
# Include all config files in /etc/rsyslog.d/.
|
||||
include(file="/etc/rsyslog.d/*.conf" mode="optional")
|
||||
|
||||
#### Modules ####
|
||||
|
||||
# Provides --MARK-- message capability.
|
||||
#module(load="immark")
|
||||
|
||||
# Provides support for local system logging (e.g. via logger command).
|
||||
module(load="imuxsock" SysSock.Name="/tmp/log")
|
||||
|
||||
# Nginx
|
||||
$template rawFormat,"%msg:2:2048%\n"
|
||||
local0.=notice /var/log/access.log;rawFormat
|
||||
local0.*;local0.!=notice /var/log/error.log;rawFormat
|
||||
|
||||
%REMOTE_SYSLOG%
|
|
@ -0,0 +1,37 @@
|
|||
local M = {}
|
||||
local status_codes = {%STATUS_CODES%}
|
||||
local threshold = %THRESHOLD%
|
||||
local count_time = %COUNT_TIME%
|
||||
local ban_time = %BAN_TIME%
|
||||
|
||||
function M.is_banned ()
|
||||
return ngx.shared.behavior_ban:get(ngx.var.remote_addr) == true
|
||||
end
|
||||
|
||||
function M.count ()
|
||||
for k, v in ipairs(status_codes) do
|
||||
if v == tostring(ngx.status) then
|
||||
local count = ngx.shared.behavior_count:get(ngx.var.remote_addr)
|
||||
if count == nil then
|
||||
count = 0
|
||||
end
|
||||
count = count + 1
|
||||
local ok, err = ngx.shared.behavior_count:set(ngx.var.remote_addr, count, count_time)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, "[BEHAVIOR] not enough memory allocated to behavior_ip_count")
|
||||
return
|
||||
end
|
||||
if count >= threshold then
|
||||
ngx.log(ngx.NOTICE, "[BEHAVIOR] threshold reached for " .. ngx.var.remote_addr .. " (" .. count .. " / " .. threshold .. ") : IP is banned for " .. ban_time .. " seconds")
|
||||
local ok, err = ngx.shared.behavior_ban:safe_set(ngx.var.remote_addr, true, ban_time)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, "[BEHAVIOR] not enough memory allocated to behavior_ip_ban")
|
||||
return
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
|
@ -28,7 +28,6 @@ ln -s /proc/1/fd/2 /var/log/nginx/modsec_audit.log
|
|||
ln -s /proc/1/fd/1 /var/log/access.log
|
||||
ln -s /proc/1/fd/2 /var/log/error.log
|
||||
ln -s /proc/1/fd/1 /var/log/jobs.log
|
||||
ln -s /proc/1/fd/1 /var/log/fail2ban.log
|
||||
ln -s /proc/1/fd/1 /var/log/clamav.log
|
||||
mkdir /var/log/letsencrypt
|
||||
chown nginx:nginx /var/log/letsencrypt
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# load some functions
|
||||
. /opt/entrypoint/utils.sh
|
||||
|
||||
logrotate -f /etc/logrotate.conf > /dev/null 2>&1
|
||||
|
||||
pkill -HUP rsyslogd
|
||||
|
||||
fail2ban-client flushlogs
|
||||
|
||||
if [ -f /tmp/nginx.pid ] ; then
|
||||
/usr/sbin/nginx -s reload > /dev/null 2>&1
|
||||
if [ "$?" -eq 0 ] ; then
|
||||
job_log "[NGINX] successfull nginx reload after logrotate"
|
||||
else
|
||||
job_log "[NGINX] failed nginx reload after logrotate"
|
||||
fi
|
||||
fi
|
|
@ -804,19 +804,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"Fail2ban":{
|
||||
"id":"fail2ban",
|
||||
"params":[
|
||||
{
|
||||
"type":"checkbox",
|
||||
"label":"Use fail2ban",
|
||||
"env":"USE_FAIL2BAN",
|
||||
"regex":"^(yes|no)$",
|
||||
"id":"use-fail2ban",
|
||||
"default":"yes"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ClamAV":{
|
||||
"id":"clamav",
|
||||
"params":[
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
<div class="col col-6 text-center"><i class="fas fa-{{ env_to_summary_class([service["AUTO_LETS_ENCRYPT"], service["USE_CUSTOM_HTTPS"], service["GENERATE_SELF_SIGNED_SSL"]], ["yes", "yes", "yes"]) }}"></i></div>
|
||||
<div class="col col-6">ModSecurity</div>
|
||||
<div class="col col-6 text-center"><i class="fas fa-{{ env_to_summary_class(service["USE_MODSECURITY"], "yes") }}"></i></div>
|
||||
<div class="col col-6">Fail2Ban</div>
|
||||
<div class="col col-6 text-center"><i class="fas fa-{{ env_to_summary_class(service["USE_FAIL2BAN"], "yes") }}"></i></div>
|
||||
<div class="col col-6">Bad behavior</div>
|
||||
<div class="col col-6 text-center"><i class="fas fa-{{ env_to_summary_class(service["USE_BAD_BEHAVIOR"], "yes") }}"></i></div>
|
||||
<div class="col col-6">Limit req</div>
|
||||
<div class="col col-6 text-center"><i class="fas fa-{{ env_to_summary_class(service["USE_LIMIT_REQ"], "yes") }}"></i></div>
|
||||
<div class="col col-6">DNSBL</div>
|
||||
|
|
Loading…
Reference in New Issue