Edit file File name : mass_hosting.lua Content :-- vim: set ts=2 expandtab: require "apache2" -- NOTE: apache2.DECLINED simply means that we're returning without modifying the request at all -- Converts an IP string into an integer for trivial comparison function ip_to_int(ip) oct1, oct2, oct3, oct4 = string.match(ip, "(%d+)%.(%d+)%.(%d+)%.(%d+)") return ((oct1 * 256 + oct2)*256+oct3)*256+oct4 end network_list = {} network_list_file = '/etc/mass_hosting.list' -- Doing this here rather than in mass_hosting() provides a speed improvement under certain configurations test_file = io.open(network_list_file) if test_file then for network in test_file:lines() do table.insert(network_list, network) end io.close(test_file) end function mass_hosting(r) test_ip = r.useragent_ip --[[ Handle Ezoic customers. This header is akin to X-Forwarded-For. This has the potential to be abused, but Ezoic uses EC2 so we're short on viable alternatives at this time. ]]-- if r.headers_in['X-Middleton-Ip'] then test_ip = r.headers_in['X-Middleton-Ip'] end -- We only care about POST requests right now if r.method ~= 'POST' then return apache2.DECLINED end -- Check for IPv4 IPs if not string.match(test_ip, "%d+%.%d+%.%d+%.%d+") then r:warn("useragent_ip is not an ipv4 IP; declining") return apache2.DECLINED end ip_int_rep = ip_to_int(test_ip) for idx, network in ipairs(network_list) do -- Ignore comments if string.find(network, '%#') == 1 then goto continue end net_addr, maskbits = string.match(network, "(%d+%.%d+%.%d+%.%d+)/(%d+)") -- Figure out how many host bits we're working with hostbits = 32 - maskbits --integer representation of the starting and ending IPs of the network space base_int_rep = ip_to_int(net_addr) max_int_rep = base_int_rep + (2^hostbits) if (ip_int_rep >= base_int_rep and ip_int_rep <= max_int_rep) then -- Found the connecting IP in a mass hosting network so return HTTP_FORBIDDEN r:debug(string.format("Found %s inside %s", test_ip, network)) r.status = 403 return apache2.DONE end ::continue:: end -- If we got this far, we didn't find the IP listed so do nothing r:debug(string.format("Unable to find %s inside any known networks", test_ip)) return apache2.DECLINED end Save