diff --git a/src/bw/lua/utils.lua b/src/bw/lua/utils.lua index 2204b6f3f..ae86ef459 100644 --- a/src/bw/lua/utils.lua +++ b/src/bw/lua/utils.lua @@ -353,8 +353,8 @@ utils.rand = function(nb) return result end -utils.get_deny_status = function(stream) - if stream then +utils.get_deny_status = function() + if ngx.var.is_stream == "yes" then return 403 end local status, err = datastore:get("variable_DENY_HTTP_STATUS") diff --git a/src/common/confs/server-stream/preread-stream-lua.conf b/src/common/confs/server-stream/preread-stream-lua.conf index 834038aa8..6eb01cf9f 100644 --- a/src/common/confs/server-stream/preread-stream-lua.conf +++ b/src/common/confs/server-stream/preread-stream-lua.conf @@ -11,7 +11,7 @@ logger.log(ngx.INFO, "PREREAD", "Preread phase started") local banned, err = datastore:get("bans_ip_" .. ngx.var.remote_addr) if banned then logger.log(ngx.WARN, "PREREAD", "IP " .. ngx.var.remote_addr .. " is banned with reason : " .. banned) - ngx.exit(utils.get_deny_status(true)) + ngx.exit(utils.get_deny_status()) end -- Redis case local use_redis = utils.get_variable("USE_REDIS") @@ -64,7 +64,7 @@ for i, plugin in ipairs(list) do end if ret then if type(value) == "number" then - if value == utils.get_deny_status(true) then + if value == utils.get_deny_status() then logger.log(ngx.WARN, "PREREAD", "Denied access from " .. plugin.id .. " : " .. err) ngx.var.reason = plugin.id else diff --git a/src/common/confs/server-stream/server-stream.conf b/src/common/confs/server-stream/server-stream.conf index ca55e6a8a..d89d6fc4d 100644 --- a/src/common/confs/server-stream/server-stream.conf +++ b/src/common/confs/server-stream/server-stream.conf @@ -14,6 +14,9 @@ server { # reason variable set $reason ''; + # stream flag + set $is_stream 'yes'; + # include LUA files include {{ NGINX_PREFIX }}preread-stream-lua.conf; include {{ NGINX_PREFIX }}log-stream-lua.conf; diff --git a/src/common/core/blacklist/blacklist.lua b/src/common/core/blacklist/blacklist.lua index 1771c65ea..246784125 100644 --- a/src/common/core/blacklist/blacklist.lua +++ b/src/common/core/blacklist/blacklist.lua @@ -329,6 +329,179 @@ function _M:access() return ret, "IP is not in list (error = " .. ret_err .. ")", false, nil end +function _M:preread() + -- Check if preread is needed + local preread_needed, err = utils.get_variable("USE_BLACKLIST") + if preread_needed == nil then + return false, err + end + if access_needed ~= "yes" then + return true, "Blacklist not activated" + end + + -- Check the cache + local cached_ip, err = self:is_in_cache("ip" .. ngx.var.remote_addr) + local cached_ignored_ip, err = self:is_in_cache("ignore_ip" .. ngx.var.remote_addr) + if cached_ignored_ip then + logger.log(ngx.NOTICE, "BLACKLIST", "IP is in cached ignore blacklist (info: " .. cached_ignored_ip .. ")") + elseif cached_ip and cached_ip ~= "ok" then + return true, "IP is in blacklist cache (info = " .. cached_ip .. ")", true, utils.get_deny_status() + elseif cached_ip + return true, "IP is in blacklist cache (not blacklisted)", false, nil + end + + -- Get list + local data, err = datastore:get("plugin_blacklist_list") + if not data then + return false, "can't get Blacklist list : " .. err, false, nil + end + local ok, blacklists = pcall(cjson.decode, data) + if not ok then + return false, "error while decoding blacklists : " .. blacklists, false, nil + end + + -- Return value + local ret, ret_err = true, "success" + + -- Check if IP is in IP/net blacklist + local ip_net, err = utils.get_variable("BLACKLIST_IP") + local ignored_ip_net, err = utils.get_variable("BLACKLIST_IGNORE_IP") + if ip_net and ip_net ~= "" then + for element in ip_net:gmatch("%S+") do + table.insert(blacklists["IP"], element) + end + end + if ignored_ip_net and ignored_ip_net ~= "" then + for element in ignored_ip_net:gmatch("%S+") do + table.insert(blacklists["IGNORE_IP"], element) + end + end + if not cached_ip then + local ipm, err = ipmatcher.new(blacklists["IP"]) + local ipm_ignore, err_ignore = ipmatcher.new(blacklists["IGNORE_IP"]) + if not ipm then + ret = false + ret_err = "can't instantiate ipmatcher " .. err + elseif not ipm_ignore then + ret = false + ret_err = "can't instantiate ipmatcher " .. err_ignore + else + if ipm:match(ngx.var.remote_addr) then + if ipm_ignore:match(ngx.var.remote_addr) then + self:add_to_cache("ignore_ip" .. ngx.var.remote_addr, "ip/net") + logger.log(ngx.NOTICE, "BLACKLIST", "client IP " .. ngx.var.remote_addr .. " is in blacklist but is ignored") + else + self:add_to_cache("ip" .. ngx.var.remote_addr, "ip/net") + return ret, "client IP " .. ngx.var.remote_addr .. " is in blacklist", true, utils.get_deny_status() + end + end + end + end + + -- Instantiate ignore variable + local ignore = false + + -- Check if rDNS is in blacklist + local rdns_global, err = utils.get_variable("BLACKLIST_RDNS_GLOBAL") + local check = true + if not rdns_global then + logger.log(ngx.ERR, "BLACKLIST", "Error while getting BLACKLIST_RDNS_GLOBAL variable : " .. err) + elseif rdns_global == "yes" then + check, err = utils.ip_is_global(ngx.var.remote_addr) + if check == nil then + logger.log(ngx.ERR, "BLACKLIST", "Error while getting checking if IP is global : " .. err) + end + end + if not cached_ip and check then + local rdns, err = utils.get_rdns(ngx.var.remote_addr) + if not rdns then + ret = false + ret_err = "error while trying to get reverse dns : " .. err + else + local rdns_list, err = utils.get_variable("BLACKLIST_RDNS") + local ignored_rdns_list, err = utils.get_variable("BLACKLIST_IGNORE_RDNS") + if rdns_list and rdns_list ~= "" then + for element in rdns_list:gmatch("%S+") do + table.insert(blacklists["RDNS"], element) + end + end + if ignored_rdns_list and ignored_rdns_list ~= "" then + for element in ignored_rdns_list:gmatch("%S+") do + table.insert(blacklists["IGNORE_RDNS"], element) + end + end + for i, suffix in ipairs(blacklists["RDNS"]) do + if rdns:sub(- #suffix) == suffix then + for j, ignore_suffix in ipairs(blacklists["IGNORE_RDNS"]) do + if rdns:sub(- #ignore_suffix) == ignore_suffix then + ignore = true + self:add_to_cache("ignore_rdns" .. ngx.var.remote_addr, "rDNS" .. suffix) + logger.log(ngx.NOTICE, "BLACKLIST", + "client IP " .. ngx.var.remote_addr .. " is in blacklist (info = rDNS " .. suffix .. ") but is ignored") + break + end + end + if not ignore then + self:add_to_cache("ip" .. ngx.var.remote_addr, "rDNS" .. suffix) + return ret, "client IP " .. ngx.var.remote_addr .. " is in blacklist (info = rDNS " .. suffix .. ")", true, + utils.get_deny_status() + end + end + end + end + end + + -- Check if ASN is in blacklist + if not cached_ip then + if utils.ip_is_global(ngx.var.remote_addr) then + local asn, err = utils.get_asn(ngx.var.remote_addr) + if not asn then + ret = false + ret_err = "error while trying to get asn number : " .. err + else + local asn_list, err = utils.get_variable("BLACKLIST_ASN") + local ignored_asn_list, err = utils.get_variable("BLACKLIST_IGNORE_ASN") + if asn_list and asn_list ~= "" then + for element in asn_list:gmatch("%S+") do + table.insert(blacklists["ASN"], element) + end + end + if ignored_asn_list and ignored_asn_list ~= "" then + for element in ignored_asn_list:gmatch("%S+") do + table.insert(blacklists["IGNORE_ASN"], element) + end + end + for i, asn_bl in ipairs(blacklists["ASN"]) do + if tostring(asn) == asn_bl then + for j, ignore_asn_bl in ipairs(blacklists["IGNORE_ASN"]) do + if tostring(asn) == ignore_asn_bl then + ignore = true + self:add_to_cache("ignore_asn" .. ngx.var.remote_addr, "ASN" .. tostring(asn)) + logger.log(ngx.NOTICE, "BLACKLIST", + "client IP " .. ngx.var.remote_addr .. " is in blacklist (info = ASN " .. tostring(asn) .. ") but is ignored") + break + end + end + if not ignore then + self:add_to_cache("ip" .. ngx.var.remote_addr, "ASN " .. tostring(asn)) + return ret, "client IP " .. ngx.var.remote_addr .. " is in blacklist (kind = ASN " .. tostring(asn) .. ")", true, + utils.get_deny_status() + end + end + end + end + end + end + + -- IP is not blacklisted + local ok, err = self:add_to_cache("ip" .. ngx.var.remote_addr, "ok") + if not ok then + ret = false + ret_err = err + end + return ret, "IP is not in list (error = " .. ret_err .. ")", false, nil +end + function _M:is_in_cache(ele) local kind, err = datastore:get("plugin_blacklist_cache_" .. ngx.var.server_name .. ele) if not kind then diff --git a/src/common/core/customcert/confs/server-stream/custom-cert.conf b/src/common/core/customcert/confs/server-stream/custom-cert.conf new file mode 100644 index 000000000..0b71534d6 --- /dev/null +++ b/src/common/core/customcert/confs/server-stream/custom-cert.conf @@ -0,0 +1,20 @@ +{% set os_path = import("os.path") %} +{% if USE_CUSTOM_HTTPS == "yes" and os_path.isfile("/data/cache/customcert/{}".format(CUSTOM_HTTPS_CERT.replace("/", "_"))) and os_path.isfile("/data/cache/customcert/{}".format(CUSTOM_HTTPS_KEY.replace("/", "_"))) +%} + +# listen +listen 0.0.0.0:{{ LISTEN_STREAM_PORT_SSL }} ssl {% if USE_UDP == "yes" %} udp {% endif %}{% if USE_PROXY_PROTOCOL == "yes" %} proxy_protocol {% endif %}; + +# TLS config +ssl_certificate /data/cache/customcert/{{ CUSTOM_HTTPS_CERT.replace("/", "_") }}; +ssl_certificate_key /data/cache/customcert/{{ CUSTOM_HTTPS_KEY.replace("/", "_") }}; +ssl_protocols {{ HTTPS_PROTOCOLS }}; +ssl_prefer_server_ciphers on; +ssl_session_tickets off; +ssl_session_timeout 1d; +ssl_session_cache shared:MozSSL:10m; +{% if "TLSv1.2" in HTTPS_PROTOCOLS +%} +ssl_dhparam /etc/nginx/dhparam; +ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; +{% endif %} + +{% endif %} \ No newline at end of file diff --git a/src/common/core/dnsbl/dnsbl.lua b/src/common/core/dnsbl/dnsbl.lua index b449a87bf..1ac7669f6 100644 --- a/src/common/core/dnsbl/dnsbl.lua +++ b/src/common/core/dnsbl/dnsbl.lua @@ -97,6 +97,10 @@ function _M:access() end +function _M:preread() + return self:access() +end + function _M:is_in_dnsbl(dnsbl, ip) local request = resolver.arpa_str(ip) .. "." .. dnsbl local ips, err = utils.get_ips(request) diff --git a/src/common/core/whitelist/confs/modsec/whitelist.conf b/src/common/core/whitelist/confs/modsec/whitelist.conf new file mode 100644 index 000000000..fd3d6fef7 --- /dev/null +++ b/src/common/core/whitelist/confs/modsec/whitelist.conf @@ -0,0 +1,5 @@ +{% if USE_WHITELIST == "yes" +%} + {% if WHITELIST_IP != "" +%} +SecRule REMOTE_ADDR "@ipMatch {{ WHITELIST_IP.replace(" ", ",") }}" "id:1000,phase:1,t:none,nolog,pass,ctl:ruleEngine=Off" + {% endif +%} +{% endif +%} \ No newline at end of file